From 253ab63403c19da19297de8e6f1538bf95243268 Mon Sep 17 00:00:00 2001
From: Incardona Pietro <incardon@mpi-cbg.de>
Date: Mon, 3 Jun 2024 01:49:32 +0200
Subject: [PATCH] Latest CNV caller

---
 example/Sequencing/CNVcaller/functions.hpp | 8015 +++++++++++---------
 example/Sequencing/CNVcaller/testing.cpp   | 2305 +++---
 2 files changed, 5731 insertions(+), 4589 deletions(-)

diff --git a/example/Sequencing/CNVcaller/functions.hpp b/example/Sequencing/CNVcaller/functions.hpp
index f58cf4c85..7644d79e9 100644
--- a/example/Sequencing/CNVcaller/functions.hpp
+++ b/example/Sequencing/CNVcaller/functions.hpp
@@ -14,4357 +14,5400 @@
 #include "hash_map/hopscotch_set.h"
 #include "sm_classes/SequentialImplementation.h"
 #include "htslib/hts.h"
-extern "C" {
+extern "C"
+{
 #include "htslib/synced_bcf_reader.h"
 }
 #include <string>
 
 #define NO_PRINT
 
+#define MAX_READ_LENGTH 256
+
 constexpr int chromosome = 0;
 constexpr int start_interval = 1;
 constexpr int stop_interval = 2;
 constexpr int Num_bases = 3;
 
 // NO PADDING integer
-constexpr size_t NO_PADDING=0x7FFFFFFF;
+constexpr size_t NO_PADDING = 0x7FFFFFFF;
 
-typedef openfpm::vector<aggregate<char,char,char>> Pair_read_type;
-typedef aggregate<Pair_read_type,short int, int, int, int> Relevant_read_type;
+typedef openfpm::vector<aggregate<char, char, char>> Pair_read_type;
+typedef aggregate<Pair_read_type, short int, int, int, int> Relevant_read_type;
 typedef openfpm::vector<Relevant_read_type> Call_related_relevant_read_type;
 typedef openfpm::vector<aggregate<Call_related_relevant_read_type>> Sample_call_related_relevant_read_type;
 typedef openfpm::vector<aggregate<Sample_call_related_relevant_read_type>> All_samples_call_related_relevant_read_type;
 
-namespace CNVcaller 
+namespace CNVcaller
 {
 
-std::string string_from_32bases_pattern(size_t seq) {
-    std::string str;
-    str.resize(32);
-    for (int i = 31 ; i >= 0 ; i--) {
-        if ((seq & 0x03) == 0) {str[i] = 'A';}
-        if ((seq & 0x03) == 1) {str[i] = 'C';}
-        if ((seq & 0x03) == 2) {str[i] = 'T';}
-        if ((seq & 0x03) == 3) {str[i] = 'G';}
-        seq = seq >> 2;
+    std::string string_from_32bases_pattern(size_t seq)
+    {
+        std::string str;
+        str.resize(32);
+        for (int i = 31; i >= 0; i--)
+        {
+            if ((seq & 0x03) == 0)
+            {
+                str[i] = 'A';
+            }
+            if ((seq & 0x03) == 1)
+            {
+                str[i] = 'C';
+            }
+            if ((seq & 0x03) == 2)
+            {
+                str[i] = 'T';
+            }
+            if ((seq & 0x03) == 3)
+            {
+                str[i] = 'G';
+            }
+            seq = seq >> 2;
+        }
+        return str;
     }
-    return str;
-}
 
-short int chr_to_chr_int(const char * chr) {
-    short int chr_int;
-    char chr_base[3];
+    short int chr_to_chr_int(const char *chr)
+    {
+        short int chr_int;
+        char chr_base[3];
 
-    if (chr[0] == 'c' && chr[1] == 'h' && chr[2] == 'r') {
-        chr_base[0] = chr[3];
-        chr_base[1] = chr[4];
-        chr_base[2] = 0;
-    }
+        if (chr[0] == 'c' && chr[1] == 'h' && chr[2] == 'r')
+        {
+            chr_base[0] = chr[3];
+            chr_base[1] = chr[4];
+            chr_base[2] = 0;
+        }
 
-    if (chr[0] == 'X') {
-        chr_int = 22;
-    } else if (chr[0] == 'Y') {
-        chr_int = 23;
-    } else {
-        chr_int = (short int)atoi(chr);
-        if (chr_int == 0) {return -1;}
-        chr_int -= 1;
-    }
+        if (chr[0] == 'X')
+        {
+            chr_int = 22;
+        }
+        else if (chr[0] == 'Y')
+        {
+            chr_int = 23;
+        }
+        else
+        {
+            chr_int = (short int)atoi(chr);
+            if (chr_int == 0)
+            {
+                return -1;
+            }
+            chr_int -= 1;
+        }
 
-    return chr_int;
-}
+        return chr_int;
+    }
 
-std::string chr_int_to_chr(int chr) {
+    std::string chr_int_to_chr(int chr)
+    {
 
-    if (chr == 23) {return "X";}
-    if (chr == 24) {return "Y";}
-    if (chr == 25) {return "MT";}
+        if (chr == 23)
+        {
+            return "X";
+        }
+        if (chr == 24)
+        {
+            return "Y";
+        }
+        if (chr == 25)
+        {
+            return "MT";
+        }
 
-    return std::to_string(chr);
-}
+        return std::to_string(chr);
+    }
 
-template<typename T> T CN_factor(const T & CN) {
-    if (CN > 1.9) {
-        if (CN <= 2.0)
-        {return 1.0 - 5.0*(CN-1.9);}
-        else if (CN > 2.0) {
-            if (CN < 2.1) {
-                return 0.5 + 5.0*(CN - 2.0);
+    template <typename T>
+    T CN_factor(const T &CN)
+    {
+        if (CN > 1.9)
+        {
+            if (CN <= 2.0)
+            {
+                return 1.0 - 5.0 * (CN - 1.9);
+            }
+            else if (CN > 2.0)
+            {
+                if (CN < 2.1)
+                {
+                    return 0.5 + 5.0 * (CN - 2.0);
+                }
             }
         }
-    }
 
+        return 1.0;
+    }
 
-    return 1.0;
-}
-
-template<typename T> T CN_offset(const T & CN) {    
-    return (CN - 2.0f)*(CN - 2.0f);
-}
+    template <typename T>
+    T CN_offset(const T &CN)
+    {
+        return (CN - 2.0f) * (CN - 2.0f);
+    }
+
+    // template<bool print_terms,int dim, int N_int_opt, int N_sample_opt>
+    // auto model_function(int selected_interval,
+    //                     Eigen::VectorXd & vars,
+    //                     Box<dim,double> & domain,
+    //                     openfpm::vector<int> & chr_counts,
+    //                     openfpm::vector<int> & counts,
+    //                     int chromosome,
+    //                     float reg) {
+
+    //     double val = 0.0;
+
+    //     for (int j = 0 ; j < N_sample_opt ; j++) {
+    //         for (int i = selected_interval,k=0 ; i < selected_interval + N_int_opt ; i++, k++ ) {
+    //             if (vars(k) < 0.0 || vars(N_int_opt+j) < 0.0) {
+    //                 val += domain.getHigh(0)*domain.getHigh(N_int_opt)*chr_counts.get(chromosome*N_sample_opt+j);
+    //                 if (print_terms) {std::cout << "OUT OF BOUND " << vars(k) << std::endl;}
+    //             } else {
+    //                 val += fabs(chr_counts.get(chromosome*N_sample_opt+j)*vars(k)*vars(N_int_opt+j) - counts.get(i*N_sample_opt + j))*CN_factor(vars(N_int_opt+j)) + 2.0f*CN_offset(vars(N_int_opt+j));
+    //                 if (print_terms) {std::cout << "External: " << vars(k)*chr_counts.get(chromosome*N_sample_opt+j)*vars(N_int_opt+j) - counts.get(i*N_sample_opt + j) << "*" << CN_factor(vars(N_int_opt+j)) << "+" << 2.0f*CN_offset(vars(N_int_opt+j)) << std::endl;}
+    //             }
+
+    //             // near integer
+    //             int near_int = std::round(vars(N_int_opt+j));
+
+    //             // Penalization for CN not being an integer
+    //             val += fabs(vars(N_int_opt+j) - near_int) * reg;
+
+    //             // Penalization for not being near the other regions for fishing
+    //             //val += penalization_fishing(vars(k),fishing_left,fishing_right);
+    //         }
+    //     }
+
+    //     // Penalization for out of bound parameters
+    //     for (int i = 0 ; i < N_sample_opt + N_int_opt ; i++) {
+    //         if (vars(i) < domain.getLow(i)) {
+    //             val += (domain.getLow(i) - vars(i))*20000.0;
+    //         }
+    //         if (vars(i) > domain.getHigh(i)) {
+    //             val += (vars(i) - domain.getHigh(i))*20000.0;
+    //         }
+    //     }
+
+    //     // Penalization for majority of samples CN bigger than two
+    //     auto majority = (float)N_sample_opt/2.0;
+    //     for (int i = 0 ; i < N_sample_opt ; i++) {
+    //         majority -= (vars(N_int_opt+i) - 2);
+    //     }
+    //     if (majority < 0) {
+    //         majority = fabs(majority);
+    //     } else {
+    //         majority = 0.0;
+    //     }
+    //     val += majority*1000.0;
+
+    //     //std::cout << "VALUE " << val << "  " << vars(0) << " " << vars(1) << " " << vars(2) << vars(3) << " " << vars(4) << " " << vars(5) << " || " << vars(6) << " " << vars(7) << std::endl;
+
+    //     #ifdef DEBUG_PRINT
+    //     std::cout << "VALUE " << val;
+    //     for (int i = 0 ; i < N_sample_opt + N_int_opt; i++) {
+    //         std::cout << vars(i)
+    //     }
+    //     std::cout << std::endl;
+    //     #endif
+
+    //     return val;
+    // }
+
+    // Function to calculate the volume of the Poisson distribution in an interval [start, end]
+    double poisson_distribution(double lambda, int ele)
+    {
+        if (lambda == 0)
+        {
+            if (ele == 0)
+            {
+                return 1.0;
+            }
+            else
+            {
+                return std::numeric_limits<double>::min();
+            }
+        }
+        if (lambda < 0.0)
+        {
+            return 1e-13;
+        }
 
+        boost::math::poisson_distribution<double> pd((double)lambda);
 
-// template<bool print_terms,int dim, int N_int_opt, int N_sample_opt> 
-// auto model_function(int selected_interval,
-//                     Eigen::VectorXd & vars, 
-//                     Box<dim,double> & domain,
-//                     openfpm::vector<int> & chr_counts,
-//                     openfpm::vector<int> & counts,
-//                     int chromosome,
-//                     float reg) {
-
-//     double val = 0.0;
-
-//     for (int j = 0 ; j < N_sample_opt ; j++) {
-//         for (int i = selected_interval,k=0 ; i < selected_interval + N_int_opt ; i++, k++ ) {
-//             if (vars(k) < 0.0 || vars(N_int_opt+j) < 0.0) {
-//                 val += domain.getHigh(0)*domain.getHigh(N_int_opt)*chr_counts.get(chromosome*N_sample_opt+j);
-//                 if (print_terms) {std::cout << "OUT OF BOUND " << vars(k) << std::endl;}
-//             } else {
-//                 val += fabs(chr_counts.get(chromosome*N_sample_opt+j)*vars(k)*vars(N_int_opt+j) - counts.get(i*N_sample_opt + j))*CN_factor(vars(N_int_opt+j)) + 2.0f*CN_offset(vars(N_int_opt+j));
-//                 if (print_terms) {std::cout << "External: " << vars(k)*chr_counts.get(chromosome*N_sample_opt+j)*vars(N_int_opt+j) - counts.get(i*N_sample_opt + j) << "*" << CN_factor(vars(N_int_opt+j)) << "+" << 2.0f*CN_offset(vars(N_int_opt+j)) << std::endl;}
-//             }
-
-
-//             // near integer
-//             int near_int = std::round(vars(N_int_opt+j));
-
-//             // Penalization for CN not being an integer
-//             val += fabs(vars(N_int_opt+j) - near_int) * reg;
-
-//             // Penalization for not being near the other regions for fishing
-//             //val += penalization_fishing(vars(k),fishing_left,fishing_right);
-//         }
-//     }
-
-//     // Penalization for out of bound parameters
-//     for (int i = 0 ; i < N_sample_opt + N_int_opt ; i++) {
-//         if (vars(i) < domain.getLow(i)) {
-//             val += (domain.getLow(i) - vars(i))*20000.0;
-//         }
-//         if (vars(i) > domain.getHigh(i)) {
-//             val += (vars(i) - domain.getHigh(i))*20000.0;
-//         }
-//     }
-
-//     // Penalization for majority of samples CN bigger than two
-//     auto majority = (float)N_sample_opt/2.0;
-//     for (int i = 0 ; i < N_sample_opt ; i++) {
-//         majority -= (vars(N_int_opt+i) - 2);
-//     }
-//     if (majority < 0) {
-//         majority = fabs(majority);
-//     } else {
-//         majority = 0.0;
-//     }
-//     val += majority*1000.0;
-
-
-//     //std::cout << "VALUE " << val << "  " << vars(0) << " " << vars(1) << " " << vars(2) << vars(3) << " " << vars(4) << " " << vars(5) << " || " << vars(6) << " " << vars(7) << std::endl;
-
-//     #ifdef DEBUG_PRINT
-//     std::cout << "VALUE " << val;
-//     for (int i = 0 ; i < N_sample_opt + N_int_opt; i++) {
-//         std::cout << vars(i)
-//     }
-//     std::cout << std::endl;
-//     #endif
-
-//     return val;
-// }
-
-
-// Function to calculate the volume of the Poisson distribution in an interval [start, end]
-double poisson_distribution(double lambda, int ele) {
-    if (lambda == 0) {
-        if (ele == 0) {return 1.0;}
-        else {return std::numeric_limits<double>::min();}
+        return boost::math::pdf(pd, ele);
     }
-    if (lambda < 0.0) {return 1e-13;}
 
-    boost::math::poisson_distribution<double> pd((double)lambda);
+    // Function to calculate the volume of the Poisson distribution in an interval [start, end]
+    double poisson_distribution_volume(int lambda, int start, int end)
+    {
+        // We will assume that the range is reasonably small so that the calculation remains efficient.
+        double volume = 0.0;
+        for (int i = start; i <= end; ++i)
+        {
+            // Calculating the probability of exactly i events
+            volume += poisson_distribution(lambda, i);
+        }
+        return volume;
+    }
 
-    return boost::math::pdf(pd,ele);
-}
+    template <bool print_terms, int dim, int N_int_opt, int N_sample_opt>
+    auto model_function(int selected_interval,
+                        Eigen::VectorXd &vars,
+                        Box<dim, double> &domain,
+                        openfpm::vector<int> &chr_counts,
+                        openfpm::vector<int> &counts,
+                        int chromosome,
+                        float reg)
+    {
 
-// Function to calculate the volume of the Poisson distribution in an interval [start, end]
-double poisson_distribution_volume(int lambda, int start, int end) {
-    // We will assume that the range is reasonably small so that the calculation remains efficient.
-    double volume = 0.0;
-    for (int i = start; i <= end; ++i) {
-        // Calculating the probability of exactly i events
-        volume += poisson_distribution(lambda,i);
-    }
-    return volume;
-}
+        double val = 0.0;
 
-template<bool print_terms,int dim, int N_int_opt, int N_sample_opt> 
-auto model_function(int selected_interval,
-                    Eigen::VectorXd & vars, 
-                    Box<dim,double> & domain,
-                    openfpm::vector<int> & chr_counts,
-                    openfpm::vector<int> & counts,
-                    int chromosome,
-                    float reg) {
-
-    double val = 0.0;
-
-    for (int j = 0 ; j < N_sample_opt ; j++) {
-        for (int i = selected_interval,k=0 ; i < selected_interval + N_int_opt ; i++, k++ ) {
-            if (vars(k) < 0.0 || vars(N_int_opt+j) < 0.0) {
-                val += 1000000.0;
-                if (print_terms) {std::cout << "OUT OF BOUND " << vars(k) << std::endl;}
-            } else {
-                if (chr_counts.get(chromosome*N_sample_opt+j)*vars(k)*vars(N_int_opt+j) > 1000000 || 
-                    chr_counts.get(chromosome*N_sample_opt+j)*vars(k)*vars(N_int_opt+j) < 0.0) 
+        for (int j = 0; j < N_sample_opt; j++)
+        {
+            for (int i = selected_interval, k = 0; i < selected_interval + N_int_opt; i++, k++)
+            {
+                if (vars(k) < 0.0 || vars(N_int_opt + j) < 0.0)
                 {
-                    val += 1000.0;
-                    if (print_terms) {std::cout << "External: " << 1000.0 << std::endl;}
+                    val += 1000000.0;
+                    if (print_terms)
+                    {
+                        std::cout << "OUT OF BOUND " << vars(k) << std::endl;
+                    }
                 }
-                else {
-                    auto pv = poisson_distribution(chr_counts.get(chromosome*N_sample_opt+j)*vars(k)*vars(N_int_opt+j),counts.get(i*N_sample_opt + j));
-                    if (pv == 0) {
+                else
+                {
+                    if (chr_counts.get(chromosome * N_sample_opt + j) * vars(k) * vars(N_int_opt + j) > 1000000 ||
+                        chr_counts.get(chromosome * N_sample_opt + j) * vars(k) * vars(N_int_opt + j) < 0.0)
+                    {
                         val += 1000.0;
-                        if (print_terms) {std::cout << "External: " << 1000.0 << std::endl;}
-                    } else {
-                        val += -std::log(pv)*CN_factor(vars(N_int_opt+j)) + 2.0f*CN_offset(vars(N_int_opt+j));
-                        if (print_terms) {std::cout << "External: " << -std::log(poisson_distribution(chr_counts.get(chromosome*N_sample_opt+j)*vars(k)*vars(N_int_opt+j),counts.get(i*N_sample_opt + j))) << "*" << CN_factor(vars(N_int_opt+j)) << "+" << 2.0f*CN_offset(vars(N_int_opt+j)) << std::endl;}
+                        if (print_terms)
+                        {
+                            std::cout << "External: " << 1000.0 << std::endl;
+                        }
+                    }
+                    else
+                    {
+                        auto pv = poisson_distribution(chr_counts.get(chromosome * N_sample_opt + j) * vars(k) * vars(N_int_opt + j), counts.get(i * N_sample_opt + j));
+                        if (pv == 0)
+                        {
+                            val += 1000.0;
+                            if (print_terms)
+                            {
+                                std::cout << "External: " << 1000.0 << std::endl;
+                            }
+                        }
+                        else
+                        {
+                            val += -std::log(pv) * CN_factor(vars(N_int_opt + j)) + 2.0f * CN_offset(vars(N_int_opt + j));
+                            if (print_terms)
+                            {
+                                std::cout << "External: " << -std::log(poisson_distribution(chr_counts.get(chromosome * N_sample_opt + j) * vars(k) * vars(N_int_opt + j), counts.get(i * N_sample_opt + j))) << "*" << CN_factor(vars(N_int_opt + j)) << "+" << 2.0f * CN_offset(vars(N_int_opt + j)) << std::endl;
+                            }
+                        }
                     }
                 }
-            }
 
+                // near integer
+                int near_int = std::round(vars(N_int_opt + j));
 
-            // near integer
-            int near_int = std::round(vars(N_int_opt+j));
+                // Penalization for CN not being an integer
+                val += fabs(vars(N_int_opt + j) - near_int) * reg;
 
-            // Penalization for CN not being an integer
-            val += fabs(vars(N_int_opt+j) - near_int) * reg;
+                // Penalization for not being near the other regions for fishing
+                // val += penalization_fishing(vars(k),fishing_left,fishing_right);
+            }
+        }
 
-            // Penalization for not being near the other regions for fishing
-            //val += penalization_fishing(vars(k),fishing_left,fishing_right);
+        // Penalization for out of bound parameters
+        for (int i = 0; i < N_sample_opt + N_int_opt; i++)
+        {
+            if (vars(i) < domain.getLow(i))
+            {
+                val += (domain.getLow(i) - vars(i)) * 20000.0;
+            }
+            if (vars(i) > domain.getHigh(i))
+            {
+                val += (vars(i) - domain.getHigh(i)) * 20000.0;
+            }
         }
-    }
 
-    // Penalization for out of bound parameters
-    for (int i = 0 ; i < N_sample_opt + N_int_opt ; i++) {
-        if (vars(i) < domain.getLow(i)) {
-            val += (domain.getLow(i) - vars(i))*20000.0;
+        // Penalization for majority of samples CN bigger than two
+        auto majority = (float)N_sample_opt / 2.0;
+        for (int i = 0; i < N_sample_opt; i++)
+        {
+            majority -= (vars(N_int_opt + i) - 2);
+        }
+        if (majority < 0)
+        {
+            majority = fabs(majority);
         }
-        if (vars(i) > domain.getHigh(i)) {
-            val += (vars(i) - domain.getHigh(i))*20000.0;
+        else
+        {
+            majority = 0.0;
         }
-    }
-
-    // Penalization for majority of samples CN bigger than two
-    auto majority = (float)N_sample_opt/2.0;
-    for (int i = 0 ; i < N_sample_opt ; i++) {
-        majority -= (vars(N_int_opt+i) - 2);
-    }
-    if (majority < 0) {
-        majority = fabs(majority);
-    } else {
-        majority = 0.0;
-    }
-    val += majority*1000.0;
+        val += majority * 1000.0;
 
+        // std::cout << "VALUE " << val << "  " << vars(0) << " " << vars(1) << " " << vars(2) << vars(3) << " " << vars(4) << " " << vars(5) << " || " << vars(6) << " " << vars(7) << std::endl;
 
-    //std::cout << "VALUE " << val << "  " << vars(0) << " " << vars(1) << " " << vars(2) << vars(3) << " " << vars(4) << " " << vars(5) << " || " << vars(6) << " " << vars(7) << std::endl;
+#ifdef DEBUG_PRINT
+        std::cout << "VALUE " << val;
+        for (int i = 0; i < N_sample_opt + N_int_opt; i++)
+        {
+            std::cout << vars(i)
+        }
+        std::cout << std::endl;
+#endif
 
-    #ifdef DEBUG_PRINT
-    std::cout << "VALUE " << val;
-    for (int i = 0 ; i < N_sample_opt + N_int_opt; i++) {
-        std::cout << vars(i)
+        return val;
     }
-    std::cout << std::endl;
-    #endif
 
-    return val;
-}
+    template <unsigned int N_int_opt, unsigned int N_sample_opt>
+    auto model_function_confidence(int selected_interval,
+                                   int selected_sample,
+                                   Eigen::VectorXd &solution,
+                                   openfpm::vector<int> &chr_counts,
+                                   openfpm::vector<int> &counts,
+                                   int chromosome)
+    {
 
+        double prob = 1.0;
+        int j = selected_sample;
 
-template<unsigned int N_int_opt, unsigned int N_sample_opt>
-auto model_function_confidence(int selected_interval,
-                    int selected_sample,
-                    Eigen::VectorXd & solution,
-                    openfpm::vector<int> & chr_counts,
-                    openfpm::vector<int> & counts,
-                    int chromosome) {
+        auto solution_cn = std::round(solution(N_int_opt + selected_sample));
 
-    double prob = 1.0;
-    int j = selected_sample;
+        if (solution_cn == 2)
+        {
+            return -1.0;
+        }
 
-    auto solution_cn = std::round(solution(N_int_opt + selected_sample));
+        auto estimated_cn2 = solution(0) * chr_counts.get(chromosome * N_sample_opt + j) * 2;
+        auto estimated_solution_cn = solution(0) * chr_counts.get(chromosome * N_sample_opt + j) * solution_cn;
+        auto estimated_solution_cn_next = solution(0) * chr_counts.get(chromosome * N_sample_opt + j) * (solution_cn + 1);
 
-    if (solution_cn == 2) {return -1.0;}
+        // the start is given when the external energy function transition
 
-    auto estimated_cn2 = solution(0)*chr_counts.get(chromosome*N_sample_opt+j)*2;
-    auto estimated_solution_cn = solution(0)*chr_counts.get(chromosome*N_sample_opt+j)*solution_cn;
-    auto estimated_solution_cn_next = solution(0)*chr_counts.get(chromosome*N_sample_opt+j)*(solution_cn+1);
+        int start = 0;
+        int end = 0;
 
+        // solution of the equation: fabs(start - estimated_cn2)*CN_factor(2) = fabs(estimated_solution_cn - start)*CN_factor(solution_cn)
+        if (solution_cn > 2)
+        {
+            // solution of the equation: (start - estimated_cn2)*CN_factor(2) = (estimated_solution_cn - start)*CN_factor(solution_cn);
+            start = (estimated_solution_cn * CN_factor(solution_cn) + estimated_cn2 * CN_factor(2)) / (CN_factor(2) + CN_factor(solution_cn));
+            end = (estimated_solution_cn_next * CN_factor(solution_cn + 1) + estimated_cn2 * CN_factor(2)) / (CN_factor(2) + CN_factor(solution_cn + 1));
+            std::cout << "START: " << start << " END: " << end << std::endl;
+        }
+        else
+        {
+            // solution of the equation: (estimated_cn2 - start)*CN_factor(2) = (start - estimated_solution_cn)*CN_factor(solution_cn);
+            start = (estimated_solution_cn * CN_factor(solution_cn - 1) + estimated_cn2 * CN_factor(2)) / (CN_factor(2) + CN_factor(solution_cn - 1));
+            end = (estimated_solution_cn_next * CN_factor(solution_cn) + estimated_cn2 * CN_factor(2)) / (CN_factor(2) + CN_factor(solution_cn));
+            std::cout << "START: " << start << " END: " << end << std::endl;
+        }
 
-    // the start is given when the external energy function transition
+        // the stop is given when the external energy function
 
-    int start = 0; 
-    int end = 0;
+        // auto prop = poisson_distribution_volume(estimated_cn2,start,end);
 
-    // solution of the equation: fabs(start - estimated_cn2)*CN_factor(2) = fabs(estimated_solution_cn - start)*CN_factor(solution_cn)
-    if (solution_cn > 2) {
-        // solution of the equation: (start - estimated_cn2)*CN_factor(2) = (estimated_solution_cn - start)*CN_factor(solution_cn);
-        start = (estimated_solution_cn*CN_factor(solution_cn) + estimated_cn2*CN_factor(2)) / (CN_factor(2) + CN_factor(solution_cn));
-        end = (estimated_solution_cn_next*CN_factor(solution_cn+1) + estimated_cn2*CN_factor(2)) / (CN_factor(2) + CN_factor(solution_cn+1));
-        std::cout << "START: " << start << " END: " << end << std::endl;
-    } else {
-        // solution of the equation: (estimated_cn2 - start)*CN_factor(2) = (start - estimated_solution_cn)*CN_factor(solution_cn);
-        start = (estimated_solution_cn*CN_factor(solution_cn-1) + estimated_cn2*CN_factor(2)) / (CN_factor(2) + CN_factor(solution_cn-1));
-        end = (estimated_solution_cn_next*CN_factor(solution_cn) + estimated_cn2*CN_factor(2)) / (CN_factor(2) + CN_factor(solution_cn));
-        std::cout << "START: " << start << " END: " << end << std::endl;
+        return -1.0;
     }
 
-    // the stop is given when the external energy function
+    template <bool print_terms, int dim, int N_int_opt, int N_sample_opt>
+    auto model_function_CN2(int selected_interval,
+                            Eigen::VectorXd &vars,
+                            Box<dim, double> &domain,
+                            openfpm::vector<int> &chr_counts,
+                            openfpm::vector<int> &counts,
+                            int chromosome,
+                            float reg)
+    {
 
-    //auto prop = poisson_distribution_volume(estimated_cn2,start,end);
+        double val = 0.0;
 
-    return -1.0;
-}
+        for (int j = 0; j < N_sample_opt; j++)
+        {
+            for (int i = selected_interval, k = 0; i < selected_interval + N_int_opt; i++, k++)
+            {
+                if (vars(k) < 0.0)
+                {
+                    val += domain.getHigh(0) * 6.0 * chr_counts.get(chromosome * N_sample_opt + j);
+                    if (print_terms)
+                    {
+                        std::cout << "OUT OF BOUND" << std::endl;
+                    }
+                }
+                else
+                {
+                    val += fabs(vars(k) * chr_counts.get(chromosome * N_sample_opt + j) * 2.0f - counts.get(i * N_sample_opt + j)) * CN_factor(2.0f) + 2.0f * CN_offset(2.0f);
+                    if (print_terms)
+                    {
+                        std::cout << "External: " << vars(k) * chr_counts.get(chromosome * N_sample_opt + j) * 2.0f - counts.get(i * N_sample_opt + j) << "*" << CN_factor(2.0f) << "+" << 2.0f * CN_offset(2.0f) << std::endl;
+                    }
+                }
 
-template<bool print_terms,int dim, int N_int_opt, int N_sample_opt> 
-auto model_function_CN2(int selected_interval,
-                    Eigen::VectorXd & vars, 
-                    Box<dim,double> & domain,
-                    openfpm::vector<int> & chr_counts,
-                    openfpm::vector<int> & counts,
-                    int chromosome,
-                    float reg) {
-
-    double val = 0.0;
-
-    for (int j = 0 ; j < N_sample_opt ; j++) {
-        for (int i = selected_interval,k=0 ; i < selected_interval + N_int_opt ; i++, k++ ) {
-            if (vars(k) < 0.0) {
-                val += domain.getHigh(0)*6.0*chr_counts.get(chromosome*N_sample_opt+j);
-                if (print_terms) {std::cout << "OUT OF BOUND" << std::endl;}
-            } else {
-                val += fabs(vars(k)*chr_counts.get(chromosome*N_sample_opt+j)*2.0f - counts.get(i*N_sample_opt + j))*CN_factor(2.0f) + 2.0f*CN_offset(2.0f);
-                if (print_terms) {std::cout << "External: " << vars(k)*chr_counts.get(chromosome*N_sample_opt+j)*2.0f - counts.get(i*N_sample_opt + j) << "*" << CN_factor(2.0f) << "+" << 2.0f*CN_offset(2.0f) << std::endl;}
+                // Penalization for not being near the other regions for fishing
+                // val += penalization_fishing(vars(k),fishing_left,fishing_right);
             }
-
-            // Penalization for not being near the other regions for fishing
-            //val += penalization_fishing(vars(k),fishing_left,fishing_right);
         }
-    }
-
-    return val;
-}
-
-void add_to_interval(openfpm::vector<int> & base_count, 
-                     openfpm::vector<aggregate<short int,int,int>> & intervals,
-                     int interval,
-                     int sample, 
-                     int N_samples, 
-                     int pos, 
-                     int num) {
-
-    int overlap_start = std::max(pos,intervals.template get<start_interval>(interval));
-    int overlap_stop = std::min(pos+num,intervals.template get<stop_interval>(interval));
 
-    base_count.get<0>(N_samples*interval + sample) += std::max(overlap_stop - overlap_start,0);
-}
+        return val;
+    }
 
-void add_to_interval_hist(openfpm::vector<openfpm::vector<int>> & histogram,
-                     openfpm::vector<aggregate<short int,int,int>> & intervals,
-                     int interval,
-                     int sample, 
-                     int N_samples, 
-                     int pos, 
-                     int num) {
+    void add_to_interval(openfpm::vector<int> &base_count,
+                         openfpm::vector<aggregate<short int, int, int>> &intervals,
+                         int interval,
+                         int sample,
+                         int N_samples,
+                         int pos,
+                         int num)
+    {
 
-    int overlap_start = std::max(pos,intervals.template get<start_interval>(interval));
-    int overlap_stop = std::min(pos+num,intervals.template get<stop_interval>(interval));
+        int overlap_start = std::max(pos, intervals.template get<start_interval>(interval));
+        int overlap_stop = std::min(pos + num, intervals.template get<stop_interval>(interval));
 
-    for (int i = overlap_start-intervals.template get<start_interval>(interval) ; i < overlap_stop - overlap_start; i++) {
-        histogram.get(interval).get(i)++;
+        base_count.get<0>(N_samples * interval + sample) += std::max(overlap_stop - overlap_start, 0);
     }
 
-}
+    void add_to_interval_hist(openfpm::vector<openfpm::vector<int>> &histogram,
+                              openfpm::vector<aggregate<short int, int, int>> &intervals,
+                              int interval,
+                              int sample,
+                              int N_samples,
+                              int pos,
+                              int num)
+    {
 
-void find_interval(openfpm::vector<aggregate<short int,int,int>> & intervals, short int chrom_t, int start_t , int & interval) {
-    if (interval != -1 && 
-        intervals.get<chromosome>(interval) == chrom_t && 
-        start_t < intervals.get<stop_interval>(interval) && 
-        start_t >= intervals.get<start_interval>(interval) )
-    {return;}
-
-    interval = 0;
-    int end = intervals.size() - 1;
-
-    while (end != interval) {
-        int mid;
-        if (end - interval == 1) {mid = end; interval = mid;}
-        else 
-        {mid = (end - interval) / 2 + interval;}
-        short int mid_chromosome = intervals.get<chromosome>(mid);
-        int mid_start = intervals.get<start_interval>(mid);
-        int mid_stop = intervals.get<stop_interval>(mid);
-    
-        short int i_chromosome = intervals.get<chromosome>(interval);
-        int i_start = intervals.get<start_interval>(interval);
-        int i_stop = intervals.get<stop_interval>(interval);
-
-        if (chrom_t < mid_chromosome) {end = mid; continue;}
-        if (chrom_t > mid_chromosome) {interval = mid; continue;}
-
-        if (start_t < mid_start) {end = mid; continue;}
-        if (start_t >= mid_stop) {interval = mid; continue;}
-
-        interval = mid;
-        return;
+        int overlap_start = std::max(pos, intervals.template get<start_interval>(interval));
+        int overlap_stop = std::min(pos + num, intervals.template get<stop_interval>(interval));
+
+        for (int i = overlap_start - intervals.template get<start_interval>(interval); i < overlap_stop - overlap_start; i++)
+        {
+            histogram.get(interval).get(i)++;
+        }
     }
 
-    interval = -1;
-    return;
-}
+    void find_interval(openfpm::vector<aggregate<short int, int, int>> &intervals, short int chrom_t, int start_t, int &interval)
+    {
+        if (interval != -1 &&
+            intervals.get<chromosome>(interval) == chrom_t &&
+            start_t < intervals.get<stop_interval>(interval) &&
+            start_t >= intervals.get<start_interval>(interval))
+        {
+            return;
+        }
 
-constexpr int READ_NUM_BASES = 0;
-constexpr int READ_DEPTH = 1;
-
-void read_sample_num_bases(std::string bam_file, 
-                openfpm::vector<int> & base_count,  
-                openfpm::vector<int> & chr_count, 
-                openfpm::vector<aggregate<short int,int,int>> & intervals, 
-                int sample, 
-                int N_samples) {
-
-    samFile *fp_in = hts_open(bam_file.c_str(),"r"); //open bam file
-    bam_hdr_t *bamHdr = sam_hdr_read(fp_in); //read header
-    bam1_t *aln = bam_init1(); //initialize an alignment
-
-    while(sam_read1(fp_in,bamHdr,aln) > 0){
-		
-        int32_t pos = aln->core.pos +1; //left most position of alignment in zero based coordianate (+1)
-        if (aln->core.tid == -1)
-        {continue;}
-        char *chr = bamHdr->target_name[aln->core.tid] ; //contig name (chromosome)
-        uint32_t len = aln->core.l_qseq; //length of the read.
-        int n_cigar = aln->core.n_cigar; // number of cigar operations
-        uint32_t * cigar = (uint32_t *)(aln->data + aln->core.l_qname);
+        interval = 0;
+        int end = intervals.size() - 1;
 
-        short int chr_int = chr_to_chr_int(chr);
-        if (chr_int == -1)  {continue;}
+        while (end != interval)
+        {
+            int mid;
+            if (end - interval == 1)
+            {
+                mid = end;
+                interval = mid;
+            }
+            else
+            {
+                mid = (end - interval) / 2 + interval;
+            }
+            short int mid_chromosome = intervals.get<chromosome>(mid);
+            int mid_start = intervals.get<start_interval>(mid);
+            int mid_stop = intervals.get<stop_interval>(mid);
 
-        chr_count.get(N_samples*chr_int + sample) += len;
+            short int i_chromosome = intervals.get<chromosome>(interval);
+            int i_start = intervals.get<start_interval>(interval);
+            int i_stop = intervals.get<stop_interval>(interval);
 
-        int j = 0;
-        int interval = 0;
-        int interval_end = 0;
-		
-        
+            if (chrom_t < mid_chromosome)
+            {
+                end = mid;
+                continue;
+            }
+            if (chrom_t > mid_chromosome)
+            {
+                interval = mid;
+                continue;
+            }
 
-        for (int k = 0 ; k < n_cigar ;  k++) {
-            int op = bam_cigar_opchr(bam_cigar_op(cigar[k]));
-            int len = bam_cigar_oplen(cigar[k]);
-            find_interval(intervals,chr_int,pos,interval);
-            find_interval(intervals,chr_int,pos+len,interval_end);
-            if (op == 'M') {
-                if (interval != -1) {
-                    add_to_interval(base_count,intervals,interval,sample,N_samples,pos,len);
-                }
-                if (interval_end != -1) {
-                    add_to_interval(base_count,intervals,interval_end,sample,N_samples,pos,len);
-                }
+            if (start_t < mid_start)
+            {
+                end = mid;
+                continue;
             }
-            else if (op == 'D' || op == 'N') {pos += len;}
-            else {
-                pos += len;
+            if (start_t >= mid_stop)
+            {
+                interval = mid;
+                continue;
             }
+
+            interval = mid;
+            return;
         }
-	}
-	
-	bam_destroy1(aln);
-	sam_close(fp_in);
-}
 
-std::string basename(const std::string &path) {
-    size_t found = path.find_last_of("/");
-    if (found != std::string::npos) {
-        return path.substr(found + 1);
+        interval = -1;
+        return;
     }
-    return path;
-}
 
-bool create_histogram(openfpm::vector<openfpm::vector<int>> & histogram,
-                      openfpm::vector<aggregate<short int,int,int>> & intervals,
-                      int chromosome) {
-    bool empty = true;
-    histogram.resize(intervals.size());
-    for (int i = 0 ; i < intervals.size(); i++) {
-        if (intervals.get<0>(i) != chromosome) {continue;}
+    constexpr int READ_NUM_BASES = 0;
+    constexpr int READ_DEPTH = 1;
 
-        histogram.get(i).resize(intervals.get<2>(i) - intervals.get<1>(i));
-        empty = false;
-    }
+    void read_sample_num_bases(std::string bam_file,
+                               openfpm::vector<int> &base_count,
+                               openfpm::vector<int> &chr_count,
+                               openfpm::vector<aggregate<short int, int, int>> &intervals,
+                               int sample,
+                               int N_samples)
+    {
 
-    return empty;
-}
+        samFile *fp_in = hts_open(bam_file.c_str(), "r"); // open bam file
+        bam_hdr_t *bamHdr = sam_hdr_read(fp_in);          // read header
+        bam1_t *aln = bam_init1();                        // initialize an alignment
 
-struct params_sum_poisson {
-    int N_int_opt;
-    int N_sample_opt;
-    int interval;
-    int chromosome;
-    openfpm::vector<int> *CNs;
-    openfpm::vector<int> * chr_counts;
-    openfpm::vector<int> * counts;
-};
+        while (sam_read1(fp_in, bamHdr, aln) > 0)
+        {
 
-/* Paraboloid centered on (p[0],p[1]), with
-   scale factors (p[2],p[3]) and minimum p[4] */
+            int32_t pos = aln->core.pos + 1; // left most position of alignment in zero based coordianate (+1)
+            if (aln->core.tid == -1)
+            {
+                continue;
+            }
+            char *chr = bamHdr->target_name[aln->core.tid]; // contig name (chromosome)
+            uint32_t len = aln->core.l_qseq;                // length of the read.
+            int n_cigar = aln->core.n_cigar;                // number of cigar operations
+            uint32_t *cigar = (uint32_t *)(aln->data + aln->core.l_qname);
 
-double sum_poisson_f (const gsl_vector *v, void *params_)
-{
-    struct params_sum_poisson * p = static_cast<struct params_sum_poisson *>(params_);
-    openfpm::vector<int> * CNs = static_cast<openfpm::vector<int> *>(p->CNs);
-    openfpm::vector<int> * chr_counts = static_cast<openfpm::vector<int> *>(p->chr_counts);
-    openfpm::vector<int> * counts = static_cast<openfpm::vector<int> *>(p->counts);
+            short int chr_int = chr_to_chr_int(chr);
+            if (chr_int == -1)
+            {
+                continue;
+            }
 
-    int N_int_opt = p->N_int_opt;
-    int N_sample_opt = p->N_sample_opt;
-    int interval = p->interval;
-    int chromosome = p->chromosome;
+            chr_count.get(N_samples * chr_int + sample) += len;
 
-    double x;
-    double y = 0.0;
+            int j = 0;
+            int interval = 0;
+            int interval_end = 0;
 
-    x = gsl_vector_get(v, 0);
+            for (int k = 0; k < n_cigar; k++)
+            {
+                int op = bam_cigar_opchr(bam_cigar_op(cigar[k]));
+                int len = bam_cigar_oplen(cigar[k]);
+                find_interval(intervals, chr_int, pos, interval);
+                find_interval(intervals, chr_int, pos + len, interval_end);
+                if (op == 'M')
+                {
+                    if (interval != -1)
+                    {
+                        add_to_interval(base_count, intervals, interval, sample, N_samples, pos, len);
+                    }
+                    if (interval_end != -1)
+                    {
+                        add_to_interval(base_count, intervals, interval_end, sample, N_samples, pos, len);
+                    }
+                }
+                else if (op == 'D' || op == 'N')
+                {
+                    pos += len;
+                }
+                else
+                {
+                    pos += len;
+                }
+            }
+        }
 
-    for (int i = 0 ; i < CNs->size() ; i++) {
-        auto pv = poisson_distribution(x*CNs->get(i)*chr_counts->get(chromosome*N_sample_opt + i),counts->get(N_sample_opt*interval + i));
-        y += -std::log(pv)*CN_factor((double)CNs->get(i)) + 2.0f*CN_offset((double)CNs->get(i));
+        bam_destroy1(aln);
+        sam_close(fp_in);
     }
-    return y;
-}
-
-/* The gradient of f, df = (df/dx, df/dy). */
-void sum_poisson_df (const gsl_vector *v, void *params_,
-       gsl_vector *df)
-{
-    struct params_sum_poisson * p = static_cast<struct params_sum_poisson *>(params_);
-    openfpm::vector<int> * CNs = static_cast<openfpm::vector<int> *>(p->CNs);
-    openfpm::vector<int> * chr_counts = static_cast<openfpm::vector<int> *>(p->chr_counts);
-    openfpm::vector<int> * counts = static_cast<openfpm::vector<int> *>(p->counts);
-
-    int N_int_opt = p->N_int_opt;
-    int N_sample_opt = p->N_sample_opt;
-    int interval = p->interval;
-    int chromosome = p->chromosome;
-
-    double x;
-    double y = 0.0;
 
-    x = gsl_vector_get(v, 0);
-
-    for (int i = 0 ; i < CNs->size() ; i++) {
-        y += -1.0 / poisson_distribution(x*CNs->get(i)*chr_counts->get(chromosome*N_sample_opt + i),counts->get(N_sample_opt*interval + i)) * \
-                    poisson_distribution(x*CNs->get(i)*chr_counts->get(chromosome*N_sample_opt + i),counts->get(N_sample_opt*interval + i)) / x * (counts->get(N_sample_opt*interval + i) - x*CNs->get(i)*chr_counts->get(chromosome*N_sample_opt + i)) * \
-                    (CN_factor((double)CNs->get(i)) + 2.0f*CN_offset((double)CNs->get(i)));
+    std::string basename(const std::string &path)
+    {
+        size_t found = path.find_last_of("/");
+        if (found != std::string::npos)
+        {
+            return path.substr(found + 1);
+        }
+        return path;
     }
 
-    gsl_vector_set(df, 0, y);
-}
-
-/* Compute both f and df together. */
-void sum_poisson_fdf (const gsl_vector *x, void *params,
-        double *f, gsl_vector *df)
-{
-    *f = sum_poisson_f(x, params);
-    sum_poisson_df(x, params, df);
-}
+    bool create_histogram(openfpm::vector<openfpm::vector<int>> &histogram,
+                          openfpm::vector<aggregate<short int, int, int>> &intervals,
+                          int chromosome)
+    {
+        bool empty = true;
+        histogram.resize(intervals.size());
+        for (int i = 0; i < intervals.size(); i++)
+        {
+            if (intervals.get<0>(i) != chromosome)
+            {
+                continue;
+            }
 
+            histogram.get(i).resize(intervals.get<2>(i) - intervals.get<1>(i));
+            empty = false;
+        }
 
-double calculateMean(const openfpm::vector<double>& data) {
-    double sum = 0.0;
-    for (int i = 0 ; i < data.size(); i++) {
-        sum += data.get(i);
+        return empty;
     }
-    return sum / data.size();
-}
 
-double calculateStandardDeviation(const openfpm::vector<double>& data) {
-    double mean = calculateMean(data);
-    double sumSquaredDifferences = 0.0;
-
-    for (int i = 0 ; i < data.size(); i++ ) {
-        double difference = data.get(i) - mean;
-        sumSquaredDifferences += difference * difference;
-    }
+    struct params_sum_poisson
+    {
+        int N_int_opt;
+        int N_sample_opt;
+        int interval;
+        int chromosome;
+        openfpm::vector<int> *CNs;
+        openfpm::vector<int> *chr_counts;
+        openfpm::vector<int> *counts;
+    };
+
+    /* Paraboloid centered on (p[0],p[1]), with
+       scale factors (p[2],p[3]) and minimum p[4] */
+
+    double sum_poisson_f(const gsl_vector *v, void *params_)
+    {
+        struct params_sum_poisson *p = static_cast<struct params_sum_poisson *>(params_);
+        openfpm::vector<int> *CNs = static_cast<openfpm::vector<int> *>(p->CNs);
+        openfpm::vector<int> *chr_counts = static_cast<openfpm::vector<int> *>(p->chr_counts);
+        openfpm::vector<int> *counts = static_cast<openfpm::vector<int> *>(p->counts);
 
-    double standardDev = std::sqrt(sumSquaredDifferences / (data.size() - 1));
+        int N_int_opt = p->N_int_opt;
+        int N_sample_opt = p->N_sample_opt;
+        int interval = p->interval;
+        int chromosome = p->chromosome;
 
-    return standardDev;
-}
+        double x;
+        double y = 0.0;
 
+        x = gsl_vector_get(v, 0);
 
-openfpm::vector<double> centroids;
-openfpm::vector<int> nPoints;
-openfpm::vector<double> sumX;
+        for (int i = 0; i < CNs->size(); i++)
+        {
+            auto pv = poisson_distribution(x * CNs->get(i) * chr_counts->get(chromosome * N_sample_opt + i), counts->get(N_sample_opt * interval + i));
+            y += -std::log(pv) * CN_factor((double)CNs->get(i)) + 2.0f * CN_offset((double)CNs->get(i));
+        }
+        return y;
+    }
 
-struct min_d {
-    double dist;
-    int cluster;
-};
+    /* The gradient of f, df = (df/dx, df/dy). */
+    void sum_poisson_df(const gsl_vector *v, void *params_,
+                        gsl_vector *df)
+    {
+        struct params_sum_poisson *p = static_cast<struct params_sum_poisson *>(params_);
+        openfpm::vector<int> *CNs = static_cast<openfpm::vector<int> *>(p->CNs);
+        openfpm::vector<int> *chr_counts = static_cast<openfpm::vector<int> *>(p->chr_counts);
+        openfpm::vector<int> *counts = static_cast<openfpm::vector<int> *>(p->counts);
 
-openfpm::vector<min_d> minDist;
+        int N_int_opt = p->N_int_opt;
+        int N_sample_opt = p->N_sample_opt;
+        int interval = p->interval;
+        int chromosome = p->chromosome;
 
-double kmean_1d_clustering_mean_bigger(openfpm::vector<double> & points, int k, int epochs = 100) {
-    int n = points.size();
+        double x;
+        double y = 0.0;
 
-    centroids.clear();
-    nPoints.clear();
-    sumX.clear();
-    minDist.clear();
+        x = gsl_vector_get(v, 0);
 
-    // Randomly initialise centroids
-    // The index of the centroid within the centroids vector
-    // represents the cluster label.
+        for (int i = 0; i < CNs->size(); i++)
+        {
+            y += -1.0 / poisson_distribution(x * CNs->get(i) * chr_counts->get(chromosome * N_sample_opt + i), counts->get(N_sample_opt * interval + i)) *
+                 poisson_distribution(x * CNs->get(i) * chr_counts->get(chromosome * N_sample_opt + i), counts->get(N_sample_opt * interval + i)) / x * (counts->get(N_sample_opt * interval + i) - x * CNs->get(i) * chr_counts->get(chromosome * N_sample_opt + i)) *
+                 (CN_factor((double)CNs->get(i)) + 2.0f * CN_offset((double)CNs->get(i)));
+        }
 
-    minDist.resize(points.size());
-    for (int i = 0; i < k; ++i) {
-        centroids.add(points.get(rand() % n));
+        gsl_vector_set(df, 0, y);
     }
-    centroids.sort();
 
-    for (int i = 0 ; i < minDist.size() ; i++) {
-        minDist.get(i).dist = std::numeric_limits<double>::max();
+    /* Compute both f and df together. */
+    void sum_poisson_fdf(const gsl_vector *x, void *params,
+                         double *f, gsl_vector *df)
+    {
+        *f = sum_poisson_f(x, params);
+        sum_poisson_df(x, params, df);
     }
 
-    for (int i = 0; i < epochs; ++i) {
-        // For each centroid, compute distance from centroid to each point
-        // and update point's cluster if necessary
-        for (int c = 0; c < centroids.size() ; ++c) {
-            for (int it = 0; it != points.size(); ++it) {
-                double p = points.get(it);
-                double dist = fabs(centroids.get(c) - p);
-                if (dist < minDist.get(it).dist) {
-                    minDist.get(it).dist = dist;
-                    minDist.get(it).cluster = c;
-                }
-            }
+    double calculateMean(const openfpm::vector<double> &data)
+    {
+        double sum = 0.0;
+        for (int i = 0; i < data.size(); i++)
+        {
+            sum += data.get(i);
         }
+        return sum / data.size();
+    }
 
-        nPoints.clear();
-        sumX.clear();
-        // Create vectors to keep track of data needed to compute means
-        for (int j = 0; j < k; ++j) {
-            nPoints.add(0);
-            sumX.add(0.0);
+    double calculateStandardDeviation(const openfpm::vector<double> &data)
+    {
+        double mean = calculateMean(data);
+        double sumSquaredDifferences = 0.0;
+
+        for (int i = 0; i < data.size(); i++)
+        {
+            double difference = data.get(i) - mean;
+            sumSquaredDifferences += difference * difference;
         }
 
-        // Iterate over points to append data to centroids
-        for (int it = 0; it < points.size() ; ++it) {
-            int clusterId = minDist.get(it).cluster;
-            nPoints.get(clusterId) += 1;
-            sumX.get(clusterId) += points.get(it);
+        double standardDev = std::sqrt(sumSquaredDifferences / (data.size() - 1));
 
-            minDist.get(it).dist = std::numeric_limits<double>::max();  // reset distance
-        }
-        // Compute the new centroids
-        for (int c = 0; c < centroids.size() ; ++c) {
-            centroids.get(c) = sumX.get(c) / nPoints.get(c);
-        }
+        return standardDev;
     }
 
-    // return the mean of the bigger cluster
+    openfpm::vector<double> centroids;
+    openfpm::vector<int> nPoints;
+    openfpm::vector<double> sumX;
 
-    int biggest_k = 0;
-    int b_c = 0;
-    for (int i = 0 ; i < k; i++) {
-        if (nPoints.get(i) >= biggest_k) {
-            biggest_k = nPoints.get(i);
-            b_c = i;
-        }
-    }
+    struct min_d
+    {
+        double dist;
+        int cluster;
+    };
 
-    return centroids.get(b_c);
-}
+    openfpm::vector<min_d> minDist;
 
-template<unsigned int N_int_opt, unsigned int N_sample_opt>
-void optimize_fast(std::ofstream & output,
-                    Box<N_sample_opt+N_int_opt,double> & domain, 
-                    double target,
-                    openfpm::vector<double> & sol,
-                    openfpm::vector<double> & confidence,
-                    openfpm::vector<int> & counts,
-                    openfpm::vector<int> & chr_count,
-                    openfpm::vector<openfpm::vector<double>> & window_noise,
-                    openfpm::vector<int> & window_noise_pointer,
-                    int interval,
-                    int chromosome,
-                    int n_intervals) {
-
-    constexpr int dim = N_int_opt + N_sample_opt;
-
-    sol.resize(N_int_opt + N_sample_opt);
-    confidence.resize(2*(N_int_opt + N_sample_opt));
-    openfpm::vector<int> CNs;
-    openfpm::vector<aggregate<float[6]>> CNs_lhood;
-
-    openfpm::vector<double> Eff_samples;
-
-    Eff_samples.resize(N_sample_opt);
-    CNs.resize(N_sample_opt);
-    CNs_lhood.resize(N_sample_opt);
-
-    // First we estimate the efficiency of the bait on CN=2
-    double val_prev = 0.0;
-
-    // more than N_sample_opt/2 samples must have depth higher than 30
-    int ns_big_30 = 0;
-    int chr_count_zero = 0;
-
-    // we calculate the best lamda for the sample
-    for (int j = 0 ; j < N_sample_opt ; j++) {
-        Eff_samples.get(j) = counts.get(interval*N_sample_opt + j) / 2.0 / chr_count.get(chromosome*N_sample_opt+j);
-        if (counts.get(interval*N_sample_opt + j) > 15) {
-            ns_big_30++;
-        }
-        if (chr_count.get(chromosome*N_sample_opt+j) == 0) {
-            chr_count_zero++;
-        }
-    }
+    double kmean_1d_clustering_mean_bigger(openfpm::vector<double> &points, int k, int epochs = 100)
+    {
+        int n = points.size();
 
-    if (ns_big_30 < N_sample_opt / 2 || chr_count_zero != 0) {
-        sol.get(0) = -1.0;
-        for (int i = 0 ; i < N_sample_opt ; i++) {
-            sol.get(i+1) = 2;
-        }
-        return;
-    }
+        centroids.clear();
+        nPoints.clear();
+        sumX.clear();
+        minDist.clear();
 
-    // Take the nearest N_sample_opt / 2
-    Eff_samples.sort();
+        // Randomly initialise centroids
+        // The index of the centroid within the centroids vector
+        // represents the cluster label.
 
-    // find the smallest in right-left NN distance
-    double distance = 10000000.0;
-    int best_eff = -1;
-    for (int i = 1 ; i < Eff_samples.size() - 1 ; i++) {
-        if (Eff_samples.get(i) < 0.0001) {continue;}
-        double distance_left = Eff_samples.get(i) - Eff_samples.get(i-1);
-        double distance_right = Eff_samples.get(i+1) - Eff_samples.get(i);
-        if (distance_right + distance_left < distance ) {
-            best_eff = i;
-            distance = distance_right + distance_left;
+        minDist.resize(points.size());
+        for (int i = 0; i < k; ++i)
+        {
+            centroids.add(points.get(rand() % n));
         }
-    }
+        centroids.sort();
 
-    // Calculate the efficency as average of the near N_samples_opt / 2
-/*    int left_pointer = best_eff - 1;
-    int right_pointer = best_eff + 1;
-    double accumulate = Eff_samples.get(best_eff);
-    for (int k = 0 ; k < N_sample_opt / 2; k++) {
-        if (Eff_samples.get(best_eff) - Eff_samples.get(left_pointer) < Eff_samples.get(right_pointer) - Eff_samples.get(best_eff)) {
-            accumulate += Eff_samples.get(left_pointer);
-            left_pointer -= 1;
-        } else {
-            accumulate += Eff_samples.get(right_pointer);
-            right_pointer += 1;
+        for (int i = 0; i < minDist.size(); i++)
+        {
+            minDist.get(i).dist = std::numeric_limits<double>::max();
         }
-    }*/
 
-//    accumulate /= right_pointer - left_pointer - 1;
+        for (int i = 0; i < epochs; ++i)
+        {
+            // For each centroid, compute distance from centroid to each point
+            // and update point's cluster if necessary
+            for (int c = 0; c < centroids.size(); ++c)
+            {
+                for (int it = 0; it != points.size(); ++it)
+                {
+                    double p = points.get(it);
+                    double dist = fabs(centroids.get(c) - p);
+                    if (dist < minDist.get(it).dist)
+                    {
+                        minDist.get(it).dist = dist;
+                        minDist.get(it).cluster = c;
+                    }
+                }
+            }
+
+            nPoints.clear();
+            sumX.clear();
+            // Create vectors to keep track of data needed to compute means
+            for (int j = 0; j < k; ++j)
+            {
+                nPoints.add(0);
+                sumX.add(0.0);
+            }
 
-    double accumulate = kmean_1d_clustering_mean_bigger(Eff_samples,2);
+            // Iterate over points to append data to centroids
+            for (int it = 0; it < points.size(); ++it)
+            {
+                int clusterId = minDist.get(it).cluster;
+                nPoints.get(clusterId) += 1;
+                sumX.get(clusterId) += points.get(it);
 
-    if (accumulate > 5.0) {
-        sol.get(0) = -1.0;
-        for (int i = 0 ; i < N_sample_opt ; i++) {
-            sol.get(i+1) = 2;
+                minDist.get(it).dist = std::numeric_limits<double>::max(); // reset distance
+            }
+            // Compute the new centroids
+            for (int c = 0; c < centroids.size(); ++c)
+            {
+                centroids.get(c) = sumX.get(c) / nPoints.get(c);
+            }
         }
-        return;
-    }
 
-    #ifndef NO_PRINT
-    std::cout << std::endl;
-    #endif
+        // return the mean of the bigger cluster
 
-    // using this efficency we find the best CN for all the samples
-    for (int j = 0 ; j < N_sample_opt ; j++) {
-        int best_CN = 0;
-        double best_pv = 5000.0;
-        for (int CN = 0 ; CN < 6 ; CN++) {
-            auto pv = poisson_distribution(chr_count.get(chromosome*N_sample_opt+j)*accumulate*CN,counts.get(interval*N_sample_opt + j));
-            pv = -std::log(pv)*CN_factor((double)CN) + 2.0f*CN_offset((double)CN);
-            if (pv < best_pv) {
-                best_pv = pv;
-                best_CN = CN;
+        int biggest_k = 0;
+        int b_c = 0;
+        for (int i = 0; i < k; i++)
+        {
+            if (nPoints.get(i) >= biggest_k)
+            {
+                biggest_k = nPoints.get(i);
+                b_c = i;
             }
         }
-        CNs.get(j) = best_CN;
-    }
-
-    gsl_vector * x = gsl_vector_alloc (1);
-    // while is unstable
-    for (int opt_s = 0 ; opt_s < 10 ; opt_s++) {
-        const gsl_multimin_fdfminimizer_type * T;
-        gsl_multimin_fdfminimizer *s;
 
-        // Finaly we optimize the efficency of the bait as summation of poisson
-        gsl_multimin_function_fdf poisson;
+        return centroids.get(b_c);
+    }
 
-        struct params_sum_poisson p;
-        p.N_sample_opt = N_sample_opt;
-        p.N_int_opt = N_int_opt;
+    template <unsigned int N_int_opt, unsigned int N_sample_opt>
+    void optimize_fast(std::ofstream &output,
+                       Box<N_sample_opt + N_int_opt, double> &domain,
+                       double target,
+                       openfpm::vector<double> &sol,
+                       openfpm::vector<double> &confidence,
+                       openfpm::vector<int> &counts,
+                       openfpm::vector<int> &chr_count,
+                       openfpm::vector<openfpm::vector<double>> &window_noise,
+                       openfpm::vector<int> &window_noise_pointer,
+                       int interval,
+                       int chromosome,
+                       int n_intervals)
+    {
 
-        p.CNs = &CNs;
-        p.chr_counts = &chr_count;
-        p.counts = &counts;
-        p.interval = interval;
-        p.chromosome = chromosome;
+        constexpr int dim = N_int_opt + N_sample_opt;
 
-        poisson.n = 1;  /* number of function components */
-        poisson.f = &sum_poisson_f;
-        poisson.df = &sum_poisson_df;
-        poisson.fdf = &sum_poisson_fdf;
-        poisson.params = (void *)&p;
+        sol.resize(N_int_opt + N_sample_opt);
+        confidence.resize(2 * (N_int_opt + N_sample_opt));
+        openfpm::vector<int> CNs;
+        openfpm::vector<aggregate<float[6]>> CNs_lhood;
 
-        gsl_vector_set (x, 0, accumulate);
+        openfpm::vector<double> Eff_samples;
 
-        T = gsl_multimin_fdfminimizer_conjugate_fr;
-        s = gsl_multimin_fdfminimizer_alloc (T, 1);
+        Eff_samples.resize(N_sample_opt);
+        CNs.resize(N_sample_opt);
+        CNs_lhood.resize(N_sample_opt);
 
-        gsl_multimin_fdfminimizer_set (s, &poisson, x, 0.01, 1e-4);
+        // First we estimate the efficiency of the bait on CN=2
+        double val_prev = 0.0;
 
-        int status = 0;
+        // more than N_sample_opt/2 samples must have depth higher than 30
+        int ns_big_30 = 0;
+        int chr_count_zero = 0;
 
-        int iter = 0;
-        do
+        // we calculate the best lamda for the sample
+        for (int j = 0; j < N_sample_opt; j++)
         {
-            iter++;
-            status = gsl_multimin_fdfminimizer_iterate (s);
-
-            if (status)
-                break;
+            Eff_samples.get(j) = counts.get(interval * N_sample_opt + j) / 2.0 / chr_count.get(chromosome * N_sample_opt + j);
+            if (counts.get(interval * N_sample_opt + j) > 15)
+            {
+                ns_big_30++;
+            }
+            if (chr_count.get(chromosome * N_sample_opt + j) == 0)
+            {
+                chr_count_zero++;
+            }
+        }
+
+        if (ns_big_30 < N_sample_opt / 2 || chr_count_zero != 0)
+        {
+            sol.get(0) = -1.0;
+            for (int i = 0; i < N_sample_opt; i++)
+            {
+                sol.get(i + 1) = 2;
+            }
+            return;
+        }
 
-            status = gsl_multimin_test_gradient (s->gradient, 1e-3);
+        // Take the nearest N_sample_opt / 2
+        Eff_samples.sort();
+
+        // find the smallest in right-left NN distance
+        double distance = 10000000.0;
+        int best_eff = -1;
+        for (int i = 1; i < Eff_samples.size() - 1; i++)
+        {
+            if (Eff_samples.get(i) < 0.0001)
+            {
+                continue;
+            }
+            double distance_left = Eff_samples.get(i) - Eff_samples.get(i - 1);
+            double distance_right = Eff_samples.get(i + 1) - Eff_samples.get(i);
+            if (distance_right + distance_left < distance)
+            {
+                best_eff = i;
+                distance = distance_right + distance_left;
+            }
         }
-        while (status == GSL_CONTINUE && iter < 100);
 
-        accumulate = gsl_vector_get (s->x, 0);
+        // Calculate the efficency as average of the near N_samples_opt / 2
+        /*    int left_pointer = best_eff - 1;
+            int right_pointer = best_eff + 1;
+            double accumulate = Eff_samples.get(best_eff);
+            for (int k = 0 ; k < N_sample_opt / 2; k++) {
+                if (Eff_samples.get(best_eff) - Eff_samples.get(left_pointer) < Eff_samples.get(right_pointer) - Eff_samples.get(best_eff)) {
+                    accumulate += Eff_samples.get(left_pointer);
+                    left_pointer -= 1;
+                } else {
+                    accumulate += Eff_samples.get(right_pointer);
+                    right_pointer += 1;
+                }
+            }*/
+
+        //    accumulate /= right_pointer - left_pointer - 1;
 
-        gsl_multimin_fdfminimizer_free (s);
+        double accumulate = kmean_1d_clustering_mean_bigger(Eff_samples, 2);
+
+        if (accumulate > 5.0)
+        {
+            sol.get(0) = -1.0;
+            for (int i = 0; i < N_sample_opt; i++)
+            {
+                sol.get(i + 1) = 2;
+            }
+            return;
+        }
+
+#ifndef NO_PRINT
+        std::cout << std::endl;
+#endif
 
-        bool is_stable = true;
         // using this efficency we find the best CN for all the samples
-        for (int j = 0 ; j < N_sample_opt ; j++) {
+        for (int j = 0; j < N_sample_opt; j++)
+        {
             int best_CN = 0;
             double best_pv = 5000.0;
-            for (int CN = 0 ; CN < 6 ; CN++) {
-                auto pv = poisson_distribution(chr_count.get(chromosome*N_sample_opt+j)*accumulate*CN,counts.get(interval*N_sample_opt + j));
-                pv = -std::log(pv)*CN_factor((double)CN) + 2.0f*CN_offset((double)CN);
-                CNs_lhood.get<0>(j)[CN] = pv;
-                if (pv < best_pv) {
+            for (int CN = 0; CN < 6; CN++)
+            {
+                auto pv = poisson_distribution(chr_count.get(chromosome * N_sample_opt + j) * accumulate * CN, counts.get(interval * N_sample_opt + j));
+                pv = -std::log(pv) * CN_factor((double)CN) + 2.0f * CN_offset((double)CN);
+                if (pv < best_pv)
+                {
                     best_pv = pv;
                     best_CN = CN;
                 }
             }
-            if (CNs.get(j) != best_CN) {
-                CNs.get(j) = best_CN;
-                is_stable = false;
-            }
+            CNs.get(j) = best_CN;
         }
 
-        if (is_stable == true) {break;}
-    }
+        gsl_vector *x = gsl_vector_alloc(1);
+        // while is unstable
+        for (int opt_s = 0; opt_s < 10; opt_s++)
+        {
+            const gsl_multimin_fdfminimizer_type *T;
+            gsl_multimin_fdfminimizer *s;
 
-    gsl_vector_free(x);
+            // Finaly we optimize the efficency of the bait as summation of poisson
+            gsl_multimin_function_fdf poisson;
 
-    output << interval << "\t";
-    for (int i = 0 ; i < N_sample_opt ; i++) {
-        output << CNs_lhood.get<0>(i)[0];
-        for (int j = 1 ; j < 6 ; j++) {
-            output << ":" << CNs_lhood.get<0>(i)[j];
-        }
-        output << "\t";
-    }
-    output << "\n";
-
-    sol.get(0) = accumulate;
-    confidence.get(0) = 0;
-    #ifndef NO_PRINT
-    std::cout << "CN_cont: ";
-    #endif
-    for (int i = 0 ; i < CNs.size() ; i++) {
-        sol.get(i+N_int_opt) = CNs.get(i);
-
-        // Confidence is calculated as the probability of the number CN=2, multiplied by the number of intervals
-        if (CNs.get(i) != 2) {
-            double p_CN = poisson_distribution(chr_count.get(chromosome*N_sample_opt+i)*accumulate*CNs.get(i),counts.get(interval*N_sample_opt + i));
-            double p_CN2 = poisson_distribution(chr_count.get(chromosome*N_sample_opt+i)*accumulate*2.0,counts.get(interval*N_sample_opt + i));
-            confidence.get(2*(i+N_int_opt)) = p_CN2 / (p_CN + p_CN2) * n_intervals;
-
-            confidence.get(2*(i+N_int_opt) + 1) = 0.0;
-            #ifndef NO_PRINT
-            std::cout << CN_cont << "(" << window_noise_pointer.get(i) << ")" << " ";
-            #endif
-        }
-        else {
-            double CN_cont = (double)counts.get(interval*N_sample_opt + i) / (double)chr_count.get(chromosome*N_sample_opt+i) / accumulate;
-            window_noise.get(i).get(window_noise_pointer.get(i)) = CN_cont;
-            #ifndef NO_PRINT
-            std::cout << CN_cont << "(" << window_noise_pointer.get(i) << ")" << " ";
-            #endif
-            double error = calculateStandardDeviation(window_noise.get(i));
-            confidence.get(2*(i+N_int_opt)) = 0.0;
-            confidence.get(2*(i+N_int_opt)+1) = 0.0;
-            window_noise_pointer.get(i) = (window_noise_pointer.get(i) + 1)%30;
-        }
-    }
-    #ifndef NO_PRINT
-    std::cout << std::endl;
-    #endif
-}
+            struct params_sum_poisson p;
+            p.N_sample_opt = N_sample_opt;
+            p.N_int_opt = N_int_opt;
 
+            p.CNs = &CNs;
+            p.chr_counts = &chr_count;
+            p.counts = &counts;
+            p.interval = interval;
+            p.chromosome = chromosome;
 
-void read_sample_depth(std::string bam_file, 
-                openfpm::vector<int> & base_count,  
-                openfpm::vector<int> & chr_count, 
-                openfpm::vector<aggregate<short int,int,int>> & intervals, 
-                int sample, 
-                int N_samples) {
+            poisson.n = 1; /* number of function components */
+            poisson.f = &sum_poisson_f;
+            poisson.df = &sum_poisson_df;
+            poisson.fdf = &sum_poisson_fdf;
+            poisson.params = (void *)&p;
 
+            gsl_vector_set(x, 0, accumulate);
 
-    // for all chromosomes
-    for (int i = 0 ; i < 25 ; i++) {
-        samFile *fp_in = hts_open(bam_file.c_str(),"r"); //open bam file
-        bam_hdr_t *bamHdr = sam_hdr_read(fp_in); //read header
-        bam1_t *aln = bam_init1(); //initialize an alignment
+            T = gsl_multimin_fdfminimizer_conjugate_fr;
+            s = gsl_multimin_fdfminimizer_alloc(T, 1);
 
-        openfpm::vector<openfpm::vector<int>> intervals_hist;
-        intervals_hist.resize(intervals.size());
-        bool empty = create_histogram(intervals_hist,intervals,i);
+            gsl_multimin_fdfminimizer_set(s, &poisson, x, 0.01, 1e-4);
 
-        if (empty == true)  {continue;}
+            int status = 0;
 
-        while(sam_read1(fp_in,bamHdr,aln) > 0){
-            
-            int32_t pos = aln->core.pos +1; //left most position of alignment in zero based coordianate (+1)
-            if (aln->core.tid == -1)
-            {continue;}
-            char *chr = bamHdr->target_name[aln->core.tid] ; //contig name (chromosome)
-            uint32_t len = aln->core.l_qseq; //length of the read.
-            int n_cigar = aln->core.n_cigar; // number of cigar operations
-            uint32_t * cigar = (uint32_t *)(aln->data + aln->core.l_qname);
+            int iter = 0;
+            do
+            {
+                iter++;
+                status = gsl_multimin_fdfminimizer_iterate(s);
 
-            short int chr_int = chr_to_chr_int(chr);
-            if (chr_int == -1)  {continue;}
-            if (chr_int != i) {continue;};
+                if (status)
+                    break;
 
-            chr_count.get(N_samples*chr_int + sample) += len;
+                status = gsl_multimin_test_gradient(s->gradient, 1e-3);
+            } while (status == GSL_CONTINUE && iter < 100);
 
-            int j = 0;
-            int interval = 0;
-            int interval_end = 0;            
+            accumulate = gsl_vector_get(s->x, 0);
 
-            for (int k = 0 ; k < n_cigar ;  k++) {
-                int op = bam_cigar_opchr(bam_cigar_op(cigar[k]));
-                int len = bam_cigar_oplen(cigar[k]);
-                find_interval(intervals,chr_int,pos,interval);
-                find_interval(intervals,chr_int,pos+len,interval_end);
-                if (op == 'M') {
-                    if (interval != -1) {
-                        add_to_interval_hist(intervals_hist,intervals,interval,sample,N_samples,pos,len);
-                    }
-                    if (interval_end != -1) {
-                        add_to_interval_hist(intervals_hist,intervals,interval_end,sample,N_samples,pos,len);
+            gsl_multimin_fdfminimizer_free(s);
+
+            bool is_stable = true;
+            // using this efficency we find the best CN for all the samples
+            for (int j = 0; j < N_sample_opt; j++)
+            {
+                int best_CN = 0;
+                double best_pv = 5000.0;
+                for (int CN = 0; CN < 6; CN++)
+                {
+                    auto pv = poisson_distribution(chr_count.get(chromosome * N_sample_opt + j) * accumulate * CN, counts.get(interval * N_sample_opt + j));
+                    pv = -std::log(pv) * CN_factor((double)CN) + 2.0f * CN_offset((double)CN);
+                    CNs_lhood.get<0>(j)[CN] = pv;
+                    if (pv < best_pv)
+                    {
+                        best_pv = pv;
+                        best_CN = CN;
                     }
                 }
-                else if (op == 'D' || op == 'N') {pos += len;}
-                else {
-                    pos += len;
+                if (CNs.get(j) != best_CN)
+                {
+                    CNs.get(j) = best_CN;
+                    is_stable = false;
                 }
             }
-        }
-        
-        bam_destroy1(aln);
-        sam_close(fp_in);
 
-        // Now reconstruct max depth for each interval
+            if (is_stable == true)
+            {
+                break;
+            }
+        }
 
-        for (int j = 0 ; j < intervals.size() ; j++) {
-            if (intervals.get<0>(j) != i) {continue;}
+        gsl_vector_free(x);
 
-            int max_depth = 0;
+        output << interval << "\t";
+        for (int i = 0; i < N_sample_opt; i++)
+        {
+            output << CNs_lhood.get<0>(i)[0];
+            for (int j = 1; j < 6; j++)
+            {
+                output << ":" << CNs_lhood.get<0>(i)[j];
+            }
+            output << "\t";
+        }
+        output << "\n";
 
-            for (int k = 0; k < intervals_hist.get(j).size() ; k++) {
-                if (intervals_hist.get(j).get(k) > max_depth) {
-                    max_depth = intervals_hist.get(j).get(k);
-                }
+        sol.get(0) = accumulate;
+        confidence.get(0) = 0;
+#ifndef NO_PRINT
+        std::cout << "CN_cont: ";
+#endif
+        for (int i = 0; i < CNs.size(); i++)
+        {
+            sol.get(i + N_int_opt) = CNs.get(i);
+
+            // Confidence is calculated as the probability of the number CN=2, multiplied by the number of intervals
+            if (CNs.get(i) != 2)
+            {
+                double p_CN = poisson_distribution(chr_count.get(chromosome * N_sample_opt + i) * accumulate * CNs.get(i), counts.get(interval * N_sample_opt + i));
+                double p_CN2 = poisson_distribution(chr_count.get(chromosome * N_sample_opt + i) * accumulate * 2.0, counts.get(interval * N_sample_opt + i));
+                confidence.get(2 * (i + N_int_opt)) = p_CN2 / (p_CN + p_CN2) * n_intervals;
+
+                confidence.get(2 * (i + N_int_opt) + 1) = 0.0;
+#ifndef NO_PRINT
+                std::cout << CN_cont << "(" << window_noise_pointer.get(i) << ")" << " ";
+#endif
+            }
+            else
+            {
+                double CN_cont = (double)counts.get(interval * N_sample_opt + i) / (double)chr_count.get(chromosome * N_sample_opt + i) / accumulate;
+                window_noise.get(i).get(window_noise_pointer.get(i)) = CN_cont;
+#ifndef NO_PRINT
+                std::cout << CN_cont << "(" << window_noise_pointer.get(i) << ")" << " ";
+#endif
+                double error = calculateStandardDeviation(window_noise.get(i));
+                confidence.get(2 * (i + N_int_opt)) = 0.0;
+                confidence.get(2 * (i + N_int_opt) + 1) = 0.0;
+                window_noise_pointer.get(i) = (window_noise_pointer.get(i) + 1) % 30;
             }
-            base_count.get(N_samples*j + sample) = max_depth;
         }
+#ifndef NO_PRINT
+        std::cout << std::endl;
+#endif
     }
-}
 
-void read_sample(std::string bam_file, 
-                openfpm::vector<int> & base_count,  
-                openfpm::vector<int> & chr_count, 
-                openfpm::vector<aggregate<short int,int,int>> & intervals, 
-                int sample, 
-                int N_samples,
-                int options = READ_NUM_BASES) {
-
-    if (options == READ_NUM_BASES) {
-        read_sample_num_bases(bam_file,base_count,chr_count,intervals,sample,N_samples);
-    } else {
-        read_sample_depth(bam_file,base_count,chr_count,intervals,sample,N_samples);
-    }
+    void read_sample_depth(std::string bam_file,
+                           openfpm::vector<int> &base_count,
+                           openfpm::vector<int> &chr_count,
+                           openfpm::vector<aggregate<short int, int, int>> &intervals,
+                           int sample,
+                           int N_samples)
+    {
 
-}
+        // for all chromosomes
+        for (int i = 0; i < 25; i++)
+        {
+            samFile *fp_in = hts_open(bam_file.c_str(), "r"); // open bam file
+            bam_hdr_t *bamHdr = sam_hdr_read(fp_in);          // read header
+            bam1_t *aln = bam_init1();                        // initialize an alignment
 
-void initialize_counts(openfpm::vector<int> & counts,
-                        openfpm::vector<int> & chr_counts,
-                        openfpm::vector<aggregate<short int,int,int>> & intervals,
-                        openfpm::vector<std::string> & files_bams,
-                        int N_samples,
-                        int N_chr) {
+            openfpm::vector<openfpm::vector<int>> intervals_hist;
+            intervals_hist.resize(intervals.size());
+            bool empty = create_histogram(intervals_hist, intervals, i);
 
-    counts.resize(N_samples*intervals.size());
-    chr_counts.resize(N_chr*N_samples);
+            if (empty == true)
+            {
+                continue;
+            }
 
-    for (int i = 0 ; i < files_bams.size() ; i++) {
-        std::cout << "READING: " << files_bams.get(i) << std::endl;
-        read_sample(files_bams.get(i),counts,chr_counts,intervals,i,N_samples);
-    }
+            while (sam_read1(fp_in, bamHdr, aln) > 0)
+            {
 
-    // count by depth
-    int count = 0;
-    for (int j = 0 ; j < intervals.size() ; j++) {
-        for (int i = 0 ; i < N_samples ; i++) {
-            counts.get(N_samples*j + i) /= intervals.get<2>(j) - intervals.get<1>(j);
+                int32_t pos = aln->core.pos + 1; // left most position of alignment in zero based coordianate (+1)
+                if (aln->core.tid == -1)
+                {
+                    continue;
+                }
+                char *chr = bamHdr->target_name[aln->core.tid]; // contig name (chromosome)
+                uint32_t len = aln->core.l_qseq;                // length of the read.
+                int n_cigar = aln->core.n_cigar;                // number of cigar operations
+                uint32_t *cigar = (uint32_t *)(aln->data + aln->core.l_qname);
+
+                short int chr_int = chr_to_chr_int(chr);
+                if (chr_int == -1)
+                {
+                    continue;
+                }
+                if (chr_int != i)
+                {
+                    continue;
+                };
+
+                chr_count.get(N_samples * chr_int + sample) += len;
+
+                int j = 0;
+                int interval = 0;
+                int interval_end = 0;
+
+                for (int k = 0; k < n_cigar; k++)
+                {
+                    int op = bam_cigar_opchr(bam_cigar_op(cigar[k]));
+                    int len = bam_cigar_oplen(cigar[k]);
+                    find_interval(intervals, chr_int, pos, interval);
+                    find_interval(intervals, chr_int, pos + len, interval_end);
+                    if (op == 'M')
+                    {
+                        if (interval != -1)
+                        {
+                            add_to_interval_hist(intervals_hist, intervals, interval, sample, N_samples, pos, len);
+                        }
+                        if (interval_end != -1)
+                        {
+                            add_to_interval_hist(intervals_hist, intervals, interval_end, sample, N_samples, pos, len);
+                        }
+                    }
+                    else if (op == 'D' || op == 'N')
+                    {
+                        pos += len;
+                    }
+                    else
+                    {
+                        pos += len;
+                    }
+                }
+            }
+
+            bam_destroy1(aln);
+            sam_close(fp_in);
+
+            // Now reconstruct max depth for each interval
+
+            for (int j = 0; j < intervals.size(); j++)
+            {
+                if (intervals.get<0>(j) != i)
+                {
+                    continue;
+                }
+
+                int max_depth = 0;
+
+                for (int k = 0; k < intervals_hist.get(j).size(); k++)
+                {
+                    if (intervals_hist.get(j).get(k) > max_depth)
+                    {
+                        max_depth = intervals_hist.get(j).get(k);
+                    }
+                }
+                base_count.get(N_samples * j + sample) = max_depth;
+            }
         }
     }
 
-    // Calculate the number of bases in the interval
+    void read_sample(std::string bam_file,
+                     openfpm::vector<int> &base_count,
+                     openfpm::vector<int> &chr_count,
+                     openfpm::vector<aggregate<short int, int, int>> &intervals,
+                     int sample,
+                     int N_samples,
+                     int options = READ_NUM_BASES)
+    {
 
-    int n_bases_chr[] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
-    for (int i = 0 ; i < intervals.size() ; i++) {
-        n_bases_chr[intervals.get<0>(i)] += intervals.get<2>(i) - intervals.get<1>(i);
+        if (options == READ_NUM_BASES)
+        {
+            read_sample_num_bases(bam_file, base_count, chr_count, intervals, sample, N_samples);
+        }
+        else
+        {
+            read_sample_depth(bam_file, base_count, chr_count, intervals, sample, N_samples);
+        }
     }
 
-    //int chromosome = 4;
-    // Divide chromosome to get max_count
+    void initialize_counts(openfpm::vector<int> &counts,
+                           openfpm::vector<int> &chr_counts,
+                           openfpm::vector<aggregate<short int, int, int>> &intervals,
+                           openfpm::vector<std::string> &files_bams,
+                           int N_samples,
+                           int N_chr)
+    {
+
+        counts.resize(N_samples * intervals.size());
+        chr_counts.resize(N_chr * N_samples);
 
-    for (int c = 0 ; c < N_chr ; c++) {
-        std::cout << "NBASES: " << n_bases_chr[c] << std::endl; 
-        for (int j = 0 ; j < N_samples ; j++) {
-            chr_counts.get(c*N_samples+j)/=(double)n_bases_chr[c];
+        for (int i = 0; i < files_bams.size(); i++)
+        {
+            std::cout << "READING: " << files_bams.get(i) << std::endl;
+            read_sample(files_bams.get(i), counts, chr_counts, intervals, i, N_samples);
+        }
+
+        // count by depth
+        int count = 0;
+        for (int j = 0; j < intervals.size(); j++)
+        {
+            for (int i = 0; i < N_samples; i++)
+            {
+                counts.get(N_samples * j + i) /= intervals.get<2>(j) - intervals.get<1>(j);
+            }
         }
-    }
-}
 
-template<unsigned int N_sample_opt, unsigned int N_int_opt>
-void initialize_counts_chr_counts_int(openfpm::vector<int> & chr_counts_int,
-                                        openfpm::vector<int> & counts,
-                                        openfpm::vector<aggregate<float[N_sample_opt+2]>> & solutions,
-                                        openfpm::vector<aggregate<short int,int,int>> & intervals) {
-    int N_samples = N_sample_opt;
+        // Calculate the number of bases in the interval
 
-    // Tranform count to absolute count
-    // count by depth
-    int count = 0;
-    for (int j = 0 ; j < intervals.size() ; j++) {
-        for (int i = 0 ; i < N_samples ; i++) {
-            counts.get(N_samples*j + i) *= (intervals.get<2>(j) - intervals.get<1>(j));
+        int n_bases_chr[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+        for (int i = 0; i < intervals.size(); i++)
+        {
+            n_bases_chr[intervals.get<0>(i)] += intervals.get<2>(i) - intervals.get<1>(i);
         }
-    }
 
+        // int chromosome = 4;
+        //  Divide chromosome to get max_count
 
-    chr_counts_int.resize(N_samples*intervals.size());
+        for (int c = 0; c < N_chr; c++)
+        {
+            std::cout << "NBASES: " << n_bases_chr[c] << std::endl;
+            for (int j = 0; j < N_samples; j++)
+            {
+                chr_counts.get(c * N_samples + j) /= (double)n_bases_chr[c];
+            }
+        }
+    }
 
-    for (int j = 0 ; j < intervals.size() ; j++) {
+    template <unsigned int N_sample_opt, unsigned int N_int_opt>
+    void initialize_counts_chr_counts_int(openfpm::vector<int> &chr_counts_int,
+                                          openfpm::vector<int> &counts,
+                                          openfpm::vector<aggregate<float[N_sample_opt + 2]>> &solutions,
+                                          openfpm::vector<aggregate<short int, int, int>> &intervals)
+    {
+        int N_samples = N_sample_opt;
 
-        if (j == 215684) {
-            int debug = 0;
-            debug++;
+        // Tranform count to absolute count
+        // count by depth
+        int count = 0;
+        for (int j = 0; j < intervals.size(); j++)
+        {
+            for (int i = 0; i < N_samples; i++)
+            {
+                counts.get(N_samples * j + i) *= (intervals.get<2>(j) - intervals.get<1>(j));
+            }
         }
 
-        for (int i = 0 ; i < N_samples ; i++) {
-            int loc_chr_count = 0;
-            double norm = 0.0;
-            int n_bases = 0.0;
-            int chromosome = intervals.get<0>(j);
+        chr_counts_int.resize(N_samples * intervals.size());
 
-            int n_backward_interval = 0;
-            int backward_pointer = 1;
+        for (int j = 0; j < intervals.size(); j++)
+        {
 
-            while (n_backward_interval < 2 && j - backward_pointer >= 0) {
-                bool valid = true;
-                for (int k = 0 ; k < N_sample_opt ; k++) {
-                    valid &= (solutions.template get<0>(j-backward_pointer)[k+1] == 2);
-                }
-                if (intervals.get<0>(j-backward_pointer) == chromosome && valid) {
-                    n_backward_interval++;
-                    loc_chr_count += counts.get(N_samples*(j-backward_pointer) + i) * 0.5 / n_backward_interval;
-                    norm += 0.50 / n_backward_interval;
-                    n_bases += (intervals.get<2>(j-backward_pointer) - intervals.get<1>(j-backward_pointer))*0.5;
-                }
-                backward_pointer++;
+            if (j == 215684)
+            {
+                int debug = 0;
+                debug++;
             }
 
-            int n_forward_interval = 0;
-            int forward_pointer = 1;
+            for (int i = 0; i < N_samples; i++)
+            {
+                int loc_chr_count = 0;
+                double norm = 0.0;
+                int n_bases = 0.0;
+                int chromosome = intervals.get<0>(j);
 
-            while (n_forward_interval < 2 && j + forward_pointer < intervals.size()) {
-                bool valid = true;
-                for (int k = 0 ; k < N_sample_opt ; k++) {
-                    valid &= (solutions.template get<0>(j+forward_pointer)[k+1] == 2);
+                int n_backward_interval = 0;
+                int backward_pointer = 1;
+
+                while (n_backward_interval < 2 && j - backward_pointer >= 0)
+                {
+                    bool valid = true;
+                    for (int k = 0; k < N_sample_opt; k++)
+                    {
+                        valid &= (solutions.template get<0>(j - backward_pointer)[k + 1] == 2);
+                    }
+                    if (intervals.get<0>(j - backward_pointer) == chromosome && valid)
+                    {
+                        n_backward_interval++;
+                        loc_chr_count += counts.get(N_samples * (j - backward_pointer) + i) * 0.5 / n_backward_interval;
+                        norm += 0.50 / n_backward_interval;
+                        n_bases += (intervals.get<2>(j - backward_pointer) - intervals.get<1>(j - backward_pointer)) * 0.5;
+                    }
+                    backward_pointer++;
                 }
-                if (intervals.get<0>(j+forward_pointer) == chromosome && valid) {
-                    n_forward_interval++;
-                    loc_chr_count += counts.get(N_samples*(j+forward_pointer) + i) * 0.5 / n_forward_interval;
-                    norm += 0.50 / n_forward_interval;
-                    n_bases += (intervals.get<2>(j+forward_pointer) - intervals.get<1>(j+forward_pointer))*0.5 / n_forward_interval;
+
+                int n_forward_interval = 0;
+                int forward_pointer = 1;
+
+                while (n_forward_interval < 2 && j + forward_pointer < intervals.size())
+                {
+                    bool valid = true;
+                    for (int k = 0; k < N_sample_opt; k++)
+                    {
+                        valid &= (solutions.template get<0>(j + forward_pointer)[k + 1] == 2);
+                    }
+                    if (intervals.get<0>(j + forward_pointer) == chromosome && valid)
+                    {
+                        n_forward_interval++;
+                        loc_chr_count += counts.get(N_samples * (j + forward_pointer) + i) * 0.5 / n_forward_interval;
+                        norm += 0.50 / n_forward_interval;
+                        n_bases += (intervals.get<2>(j + forward_pointer) - intervals.get<1>(j + forward_pointer)) * 0.5 / n_forward_interval;
+                    }
+                    forward_pointer++;
                 }
-                forward_pointer++;
+                // Normalization 0.5+0.5+0.25+0.25
+                loc_chr_count /= norm;
+                chr_counts_int.get(j * N_samples + i) = (double)loc_chr_count / n_bases;
             }
-            // Normalization 0.5+0.5+0.25+0.25
-            loc_chr_count /= norm;
-            chr_counts_int.get(j*N_samples + i) = (double)loc_chr_count / n_bases;
         }
-    }
 
-    // Retransform count
-    for (int j = 0 ; j < intervals.size() ; j++) {
-        for (int i = 0 ; i < N_samples ; i++) {
-            counts.get(N_samples*j + i) /= (intervals.get<2>(j) - intervals.get<1>(j));
+        // Retransform count
+        for (int j = 0; j < intervals.size(); j++)
+        {
+            for (int i = 0; i < N_samples; i++)
+            {
+                counts.get(N_samples * j + i) /= (intervals.get<2>(j) - intervals.get<1>(j));
+            }
         }
     }
-}
 
-std::ofstream create_call_tsv_file_with_header(std::string name,
-                                                openfpm::vector<std::string> & files_bams) {
-    std::ofstream fout;
+    std::ofstream create_call_tsv_file_with_header(std::string name,
+                                                   openfpm::vector<std::string> &files_bams)
+    {
+        std::ofstream fout;
 
-    auto & v_cl = create_vcluster();
+        auto &v_cl = create_vcluster();
 
-    if (v_cl.rank() == 0) {
-        // Open a TSV file for writing
-        fout.open(name);
-        if (!fout.is_open()) {
-            std::cerr << "Failed to open the file for writing.\n";
-            return fout;
-        }
-        fout << "N" << '\t' << "chromosome" << '\t' << "start" << '\t' << "stop";
-        for (int j = 0 ; j < files_bams.size() ; j++) {
-            fout << '\t' << basename(files_bams.get(j));
+        if (v_cl.rank() == 0)
+        {
+            // Open a TSV file for writing
+            fout.open(name);
+            if (!fout.is_open())
+            {
+                std::cerr << "Failed to open the file for writing.\n";
+                return fout;
+            }
+            fout << "N" << '\t' << "chromosome" << '\t' << "start" << '\t' << "stop";
+            for (int j = 0; j < files_bams.size(); j++)
+            {
+                fout << '\t' << basename(files_bams.get(j));
+            }
+            fout << '\t' << "value" << '\t' << "CALL" << std::endl;
         }
-        fout << '\t' << "value" << '\t' << "CALL" << std::endl;
-    }
 
-    return fout;
-}
+        return fout;
+    }
 
-std::ofstream create_call_CN_prob(std::string name,
-                                                openfpm::vector<std::string> & files_bams) {
-    std::ofstream fout;
+    std::ofstream create_call_CN_prob(std::string name,
+                                      openfpm::vector<std::string> &files_bams)
+    {
+        std::ofstream fout;
 
-    auto & v_cl = create_vcluster();
+        auto &v_cl = create_vcluster();
 
-    if (v_cl.rank() == 0) {
-        // Open a TSV file for writing
-        fout.open(name);
-        if (!fout.is_open()) {
-            std::cerr << "Failed to open the file for writing.\n";
-            return fout;
-        }
-        fout << "N" << '\t' << "chromosome" << '\t' << "start" << '\t' << "stop";
-        for (int j = 0 ; j < files_bams.size() ; j++) {
-            fout << '\t' << basename(files_bams.get(j));
+        if (v_cl.rank() == 0)
+        {
+            // Open a TSV file for writing
+            fout.open(name);
+            if (!fout.is_open())
+            {
+                std::cerr << "Failed to open the file for writing.\n";
+                return fout;
+            }
+            fout << "N" << '\t' << "chromosome" << '\t' << "start" << '\t' << "stop";
+            for (int j = 0; j < files_bams.size(); j++)
+            {
+                fout << '\t' << basename(files_bams.get(j));
+            }
         }
-    }
-
-    return fout;
-}
 
-template<unsigned int N_int_opt, unsigned int N_sample_opt>
-void initialize_domain(Box<N_int_opt+N_sample_opt,double> & domain) {
-	for (size_t i = 0 ; i < N_int_opt ; i++)
-	{
-		domain.setLow(i,0.0);
-		domain.setHigh(i,1.0);
-	}
+        return fout;
+    }
 
-    for (size_t i = N_int_opt ; i < N_int_opt + N_sample_opt ; i++) 
+    template <unsigned int N_int_opt, unsigned int N_sample_opt>
+    void initialize_domain(Box<N_int_opt + N_sample_opt, double> &domain)
     {
-        domain.setLow(i,0.0);
-        domain.setHigh(i,6.0);
+        for (size_t i = 0; i < N_int_opt; i++)
+        {
+            domain.setLow(i, 0.0);
+            domain.setHigh(i, 1.0);
+        }
+
+        for (size_t i = N_int_opt; i < N_int_opt + N_sample_opt; i++)
+        {
+            domain.setLow(i, 0.0);
+            domain.setHigh(i, 6.0);
+        }
     }
-}
 
-template<unsigned int N_int_opt, unsigned int N_sample_opt>
-int call_single_interval_mean_depth(openfpm::vector<aggregate<short int,int,int>> & intervals,
-                                    openfpm::vector<std::string> & files_bams,
-                                    openfpm::vector<int> & counts,
-                                    openfpm::vector<aggregate<float[N_sample_opt+2]>> & solutions,
-                                    openfpm::vector<aggregate<float[N_sample_opt]>> & confidence){
-    auto & v_cl = create_vcluster();
+    template <unsigned int N_int_opt, unsigned int N_sample_opt>
+    int call_single_interval_mean_depth(openfpm::vector<aggregate<short int, int, int>> &intervals,
+                                        openfpm::vector<std::string> &files_bams,
+                                        openfpm::vector<int> &counts,
+                                        openfpm::vector<aggregate<float[N_sample_opt + 2]>> &solutions,
+                                        openfpm::vector<aggregate<float[N_sample_opt]>> &confidence)
+    {
+        auto &v_cl = create_vcluster();
 
-    constexpr int dim = N_sample_opt + N_int_opt;
-    Box<dim,double> domain;
+        constexpr int dim = N_sample_opt + N_int_opt;
+        Box<dim, double> domain;
 
-    initialize_domain<N_int_opt,N_sample_opt>(domain);
+        initialize_domain<N_int_opt, N_sample_opt>(domain);
 
-    int N_samples = N_sample_opt;
-    int N_chr = 24;
+        int N_samples = N_sample_opt;
+        int N_chr = 24;
 
-    openfpm::vector<int> chr_counts;
+        openfpm::vector<int> chr_counts;
 
-    #ifndef SKIP_LOAD
+#ifndef SKIP_LOAD
 
-    initialize_counts(counts,chr_counts,intervals,files_bams,N_samples,N_chr);
+        initialize_counts(counts, chr_counts, intervals, files_bams, N_samples, N_chr);
 
-    counts.save("counts_vector");
-    chr_counts.save("chr_counts_vector");
-    intervals.save("intervals_vector");
+        counts.save("counts_vector");
+        chr_counts.save("chr_counts_vector");
+        intervals.save("intervals_vector");
 
-    #endif
+#endif
 
-    #ifdef SKIP_LOAD
+#ifdef SKIP_LOAD
 
-    counts.load("counts_vector");
-    chr_counts.load("chr_counts_vector");
-    intervals.load("intervals_vector");
+        counts.load("counts_vector");
+        chr_counts.load("chr_counts_vector");
+        intervals.load("intervals_vector");
 
-    #endif
+#endif
 
-    solutions.resize(intervals.size());
-    confidence.resize(intervals.size());
+        solutions.resize(intervals.size());
+        confidence.resize(intervals.size());
 
-    if (v_cl.rank() == 0) {
-        std::cout << "CALLING ON EVERY INTERVALS BY MEAN DEPTH" << std::endl;
-    }
+        if (v_cl.rank() == 0)
+        {
+            std::cout << "CALLING ON EVERY INTERVALS BY MEAN DEPTH" << std::endl;
+        }
 
-    if (v_cl.rank() == 0) {
+        if (v_cl.rank() == 0)
+        {
 
-        for (int j = 0 ; j < N_chr ; j++) {
-            std::cout << "chr " << j << "  "; 
-            for (int i = 0 ; i < N_samples ; i++) {
-                std::cout << "  " << chr_counts.get(N_samples*j + i);
+            for (int j = 0; j < N_chr; j++)
+            {
+                std::cout << "chr " << j << "  ";
+                for (int i = 0; i < N_samples; i++)
+                {
+                    std::cout << "  " << chr_counts.get(N_samples * j + i);
+                }
+                std::cout << std::endl;
             }
-            std::cout << std::endl;
         }
-    }
 
-    int n_interval_to_process = 0;
-    for (int i = 0 ; i < intervals.size() ; i++) {
-        bool is_zero =  true;
-        for (int j = 0 ; j < N_samples; j++) {
-            if (counts.get(N_samples*i + j) != 0) {
-                is_zero = false;
+        int n_interval_to_process = 0;
+        for (int i = 0; i < intervals.size(); i++)
+        {
+            bool is_zero = true;
+            for (int j = 0; j < N_samples; j++)
+            {
+                if (counts.get(N_samples * i + j) != 0)
+                {
+                    is_zero = false;
+                }
             }
+            if (is_zero == true)
+            {
+                continue;
+            }
+            n_interval_to_process++;
         }
-        if (is_zero == true)    {continue;}
-        n_interval_to_process++;
-    }
 
-    std::ofstream fout = create_call_tsv_file_with_header("calls.tsv",files_bams);
-    std::ofstream fout_CN_prob = create_call_CN_prob("calls_CN_probs.tsv",files_bams);
+        std::ofstream fout = create_call_tsv_file_with_header("calls.tsv", files_bams);
+        std::ofstream fout_CN_prob = create_call_CN_prob("calls_CN_probs.tsv", files_bams);
 
-    openfpm::vector<openfpm::vector<double>> window_noise;
-    openfpm::vector<int> window_noise_pointer;
-    window_noise.resize(N_sample_opt);
-    window_noise_pointer.resize(N_sample_opt);
-    for (int i = 0 ; i < N_sample_opt; i++) {
-        window_noise.get(i).resize(30);
-        window_noise_pointer.get(i) = 0;
-    }
-    int interval_processed = 0;
-    for (int i = 0 ; i < intervals.size() ; i++) {
-        if (v_cl.rank() == 0) {
-            #ifndef NO_PRINT
-            std::cout << "---------------------------------------------------------------------------------------------------" << std::endl;
-            #endif
+        openfpm::vector<openfpm::vector<double>> window_noise;
+        openfpm::vector<int> window_noise_pointer;
+        window_noise.resize(N_sample_opt);
+        window_noise_pointer.resize(N_sample_opt);
+        for (int i = 0; i < N_sample_opt; i++)
+        {
+            window_noise.get(i).resize(30);
+            window_noise_pointer.get(i) = 0;
         }
-        float reg = 2000;
-        int selected_interval = i;
-        double fishing_left = 0.5;
-        double fishing_right = 0.5;
+        int interval_processed = 0;
+        for (int i = 0; i < intervals.size(); i++)
+        {
+            if (v_cl.rank() == 0)
+            {
+#ifndef NO_PRINT
+                std::cout << "---------------------------------------------------------------------------------------------------" << std::endl;
+#endif
+            }
+            float reg = 2000;
+            int selected_interval = i;
+            double fishing_left = 0.5;
+            double fishing_right = 0.5;
 
-        int chromosome = intervals.template get<0>(i);
+            int chromosome = intervals.template get<0>(i);
 
-        auto lamb_eval = [&](Eigen::VectorXd & vars){
-            return model_function<true,dim,N_int_opt,N_sample_opt>(selected_interval,vars,domain,chr_counts,counts,chromosome,reg);
-        };
+            auto lamb_eval = [&](Eigen::VectorXd &vars)
+            {
+                return model_function<true, dim, N_int_opt, N_sample_opt>(selected_interval, vars, domain, chr_counts, counts, chromosome, reg);
+            };
 
-        auto lamb = [&](Eigen::VectorXd & vars){
-            return model_function<false,dim,N_int_opt,N_sample_opt>(selected_interval,vars,domain,chr_counts,counts,chromosome,reg);
-        };
+            auto lamb = [&](Eigen::VectorXd &vars)
+            {
+                return model_function<false, dim, N_int_opt, N_sample_opt>(selected_interval, vars, domain, chr_counts, counts, chromosome, reg);
+            };
 
-        // Check there is data
+            // Check there is data
 
-        bool is_zero =  true;
-        for (int j = 0 ; j < N_samples; j++) {
-            if (counts.get(N_samples*i + j) != 0) {
-                is_zero = false;
+            bool is_zero = true;
+            for (int j = 0; j < N_samples; j++)
+            {
+                if (counts.get(N_samples * i + j) != 0)
+                {
+                    is_zero = false;
+                }
+            }
+            if (is_zero == true)
+            {
+                continue;
             }
-        }
-        if (is_zero == true)    {continue;}
 
-        openfpm::vector<double> sol;
-        openfpm::vector<double> confidence;
-        if (v_cl.rank() == 0) {
-            #ifndef NO_PRINT
-            std::cout << "Processing interval: " << interval_processed << "/" << n_interval_to_process << std::endl;
-            std::cout << "Chromosome: " << intervals.get<0>(i)+1 << " start: " << intervals.get<1>(i) << " stop: " << intervals.get<2>(i) << std::endl;
-            #endif
-        }
-        if (v_cl.rank() == 0) {
-            int chromosome = intervals.template get<0>(i);
-            if (i == 110000) {
-                int debug = 0;
-                debug++;
+            openfpm::vector<double> sol;
+            openfpm::vector<double> confidence;
+            if (v_cl.rank() == 0)
+            {
+#ifndef NO_PRINT
+                std::cout << "Processing interval: " << interval_processed << "/" << n_interval_to_process << std::endl;
+                std::cout << "Chromosome: " << intervals.get<0>(i) + 1 << " start: " << intervals.get<1>(i) << " stop: " << intervals.get<2>(i) << std::endl;
+#endif
+            }
+            if (v_cl.rank() == 0)
+            {
+                int chromosome = intervals.template get<0>(i);
+                if (i == 110000)
+                {
+                    int debug = 0;
+                    debug++;
+                }
+                optimize_fast<N_int_opt, N_sample_opt>(fout_CN_prob, domain, 0.0, sol, confidence, counts, chr_counts, window_noise, window_noise_pointer, i, chromosome, intervals.size());
+#ifndef NO_PRINT
+                for (int k = 0; k < sol.size(); k++)
+                {
+                    std::cout << sol.get(k) << '\t';
+                }
+#endif
+                Eigen::VectorXd vars;
+                vars.resize(sol.size());
+                for (int s = 0; s < sol.size(); s++)
+                {
+                    vars(s) = sol.get(s);
+                }
+#ifndef NO_PRINT
+                if (vars(0) > 0.0)
+                {
+                    std::cout << "  f: " << lamb(vars) << std::endl;
+                }
+                else
+                {
+                    std::cout << "  f: " << "TOO LOO QUALITY FOR CALL " << std::endl;
+                }
+                std::cout << std::endl;
+#endif
             }
-            optimize_fast<N_int_opt,N_sample_opt>(fout_CN_prob,domain,0.0,sol,confidence,counts,chr_counts,window_noise,window_noise_pointer,i,chromosome,intervals.size());
-            #ifndef NO_PRINT
-            for (int k = 0 ; k < sol.size() ; k++) {
-                std::cout << sol.get(k) << '\t';
+            // optimize(domain,0.0,sol,lamb);
+            if (v_cl.rank() == 0)
+            {
+#ifndef NO_PRINT
+                std::cout << std::endl;
+#endif
+            }
+            interval_processed++;
+            bool is_call = false;
+            fout << i << '\t' << intervals.get<0>(i) + 1 << '\t' << intervals.get<1>(i) << '\t' << intervals.get<2>(i);
+            for (int k = 0; k < sol.size(); k++)
+            {
+                solutions.template get<0>(i)[k] = sol.get(k);
+                if (k != 0 && std::round(solutions.template get<0>(i)[k]) != 2)
+                {
+                    is_call = true;
+                }
+                if (v_cl.rank() == 0)
+                {
+                    fout << '\t' << solutions.template get<0>(i)[k];
+                }
             }
-            #endif
             Eigen::VectorXd vars;
             vars.resize(sol.size());
-            for (int s = 0 ; s < sol.size() ; s++) {
+            for (int s = 0; s < sol.size(); s++)
+            {
                 vars(s) = sol.get(s);
             }
-            #ifndef NO_PRINT
-            if (vars(0) > 0.0) {
-                std::cout << "  f: " << lamb(vars) << std::endl;
-            } else {
-                std::cout << "  f: " << "TOO LOO QUALITY FOR CALL " << std::endl;
-            }
-            std::cout << std::endl;
-            #endif
-        }
-        //optimize(domain,0.0,sol,lamb);
-        if (v_cl.rank() == 0) {
-            #ifndef NO_PRINT
-            std::cout << std::endl;
-            #endif
-        }
-        interval_processed++;
-        bool is_call = false;
-        fout << i << '\t' << intervals.get<0>(i)+1 << '\t' <<  intervals.get<1>(i) << '\t' << intervals.get<2>(i);
-        for (int k = 0 ; k < sol.size() ; k++) {
-            solutions.template get<0>(i)[k] = sol.get(k);
-            if (k != 0 && std::round(solutions.template get<0>(i)[k]) != 2) {
-                is_call = true;
-            }
-            if (v_cl.rank() == 0)
-            {fout << '\t' << solutions.template get<0>(i)[k];}
-        }
-        Eigen::VectorXd vars;
-        vars.resize(sol.size());
-        for (int s = 0 ; s < sol.size() ; s++) {
-            vars(s) = sol.get(s);
-        }
 
-        // Print confidence
-        if (v_cl.rank() == 0) {
-            #ifndef NO_PRINT
-            std::cout << "CONFIDENCE: ";
-            for (int i = N_int_opt ; i < N_int_opt + N_sample_opt ; i++) {
-                std::cout << confidence.get(2*i) << "(" << confidence.get(2*i+1) << ")" << " ";
+            // Print confidence
+            if (v_cl.rank() == 0)
+            {
+#ifndef NO_PRINT
+                std::cout << "CONFIDENCE: ";
+                for (int i = N_int_opt; i < N_int_opt + N_sample_opt; i++)
+                {
+                    std::cout << confidence.get(2 * i) << "(" << confidence.get(2 * i + 1) << ")" << " ";
+                }
+                std::cout << std::endl;
+#endif
             }
-            std::cout << std::endl;
-            #endif
-        }
 
-        if (v_cl.rank() == 0) {
-            if (sol.get(0) >= 0.0)
-            {fout << '\t' << lamb(vars) << '\t' << i;}
-            else
-            {fout << '\t' << "NO QUALITY" << '\t' << i;}
-        }
-        if (v_cl.rank() == 0) {
-            if (is_call == true) {
-                #ifndef NO_PRINT
-                std::cout << "----------------------------------------------------------------------------------------" << std::endl;
-                std::cout << "-----------------------------------CALL-------------------------------------------------" << std::endl;
-                std::cout << "----------------------------------------------------------------------------------------" << std::endl;
-                #endif
-                fout << '\t' << "CALL" << std::endl;
-            }
-            else {
-                fout << '\t' << "." << std::endl;
-                #ifndef NO_PRINT
-                std::cout << std::endl;
-                #endif
+            if (v_cl.rank() == 0)
+            {
+                if (sol.get(0) >= 0.0)
+                {
+                    fout << '\t' << lamb(vars) << '\t' << i;
+                }
+                else
+                {
+                    fout << '\t' << "NO QUALITY" << '\t' << i;
+                }
             }
-            for (int j = 0 ; j < N_sample_opt ; j++) {
-                #ifndef NO_PRINT
-                std::cout << basename(files_bams.get(j)) << " " << solutions.template get<0>(i)[1+j] << " ";
-                #endif
+            if (v_cl.rank() == 0)
+            {
+                if (is_call == true)
+                {
+#ifndef NO_PRINT
+                    std::cout << "----------------------------------------------------------------------------------------" << std::endl;
+                    std::cout << "-----------------------------------CALL-------------------------------------------------" << std::endl;
+                    std::cout << "----------------------------------------------------------------------------------------" << std::endl;
+#endif
+                    fout << '\t' << "CALL" << std::endl;
+                }
+                else
+                {
+                    fout << '\t' << "." << std::endl;
+#ifndef NO_PRINT
+                    std::cout << std::endl;
+#endif
+                }
+                for (int j = 0; j < N_sample_opt; j++)
+                {
+#ifndef NO_PRINT
+                    std::cout << basename(files_bams.get(j)) << " " << solutions.template get<0>(i)[1 + j] << " ";
+#endif
+                }
             }
+            fout << std::flush;
         }
-        fout << std::flush;
+
+        return 0;
     }
 
-    return 0;
-}
+    template <unsigned int N_int_opt, unsigned int N_sample_opt>
+    int call_single_interval_mean_depth_local(openfpm::vector<aggregate<short int, int, int>> &intervals,
+                                              openfpm::vector<std::string> &files_bams,
+                                              openfpm::vector<int> &counts,
+                                              openfpm::vector<aggregate<float[N_sample_opt + 2]>> &solutions,
+                                              openfpm::vector<aggregate<float[N_sample_opt + 2]>> &solutions_out,
+                                              openfpm::vector<aggregate<float[N_sample_opt]>> &confidence)
+    {
+        openfpm::vector<int> chr_counts;
+        solutions_out.resize(intervals.size());
+        confidence.resize(intervals.size());
 
-template<unsigned int N_int_opt, unsigned int N_sample_opt>
-int call_single_interval_mean_depth_local(openfpm::vector<aggregate<short int,int,int>> & intervals,
-                                    openfpm::vector<std::string> & files_bams,
-                                    openfpm::vector<int> & counts,
-                                    openfpm::vector<aggregate<float[N_sample_opt+2]>> & solutions,
-                                    openfpm::vector<aggregate<float[N_sample_opt+2]>> & solutions_out,
-                                    openfpm::vector<aggregate<float[N_sample_opt]>> & confidence){
-    openfpm::vector<int> chr_counts;
-    solutions_out.resize(intervals.size());
-    confidence.resize(intervals.size());
+        constexpr int dim = N_sample_opt + N_int_opt;
 
-    constexpr int dim = N_sample_opt + N_int_opt;
+        int N_samples = N_sample_opt;
+        int N_chr = 24;
+        chr_counts.resize(N_chr * N_samples);
+        openfpm::vector<int> chr_counts_int;
 
-    int N_samples = N_sample_opt;
-    int N_chr = 24;
-    chr_counts.resize(N_chr*N_samples);
-    openfpm::vector<int> chr_counts_int;
+        initialize_counts_chr_counts_int<N_sample_opt, N_int_opt>(chr_counts_int, counts, solutions, intervals);
 
-    initialize_counts_chr_counts_int<N_sample_opt,N_int_opt>(chr_counts_int,counts,solutions,intervals);
-    
-    Box<dim,double> domain;
+        Box<dim, double> domain;
 
-    initialize_domain<N_int_opt,N_sample_opt>(domain);
+        initialize_domain<N_int_opt, N_sample_opt>(domain);
 
-    auto & v_cl = create_vcluster();
+        auto &v_cl = create_vcluster();
 
-    if (v_cl.rank() == 0) {
-        std::cout << "CALLING ON EVERY INTERVALS BY MEAN DEPTH LOCAL" << std::endl;
-    }
+        if (v_cl.rank() == 0)
+        {
+            std::cout << "CALLING ON EVERY INTERVALS BY MEAN DEPTH LOCAL" << std::endl;
+        }
 
-    std::ofstream fout = create_call_tsv_file_with_header("calls_loc.tsv",files_bams);
-    std::ofstream fout_CN_prob = create_call_CN_prob("calls_CN_probs_loc.tsv",files_bams);
+        std::ofstream fout = create_call_tsv_file_with_header("calls_loc.tsv", files_bams);
+        std::ofstream fout_CN_prob = create_call_CN_prob("calls_CN_probs_loc.tsv", files_bams);
 
-    openfpm::vector<openfpm::vector<double>> window_noise;
-    openfpm::vector<int> window_noise_pointer;
-    window_noise.resize(N_sample_opt);
-    window_noise_pointer.resize(N_sample_opt);
-    for (int i = 0 ; i < N_sample_opt; i++) {
-        window_noise.get(i).resize(30);
-        window_noise_pointer.get(i) = 0;
-    }
-    int interval_processed = 0;
-    for (int i = 0 ; i < intervals.size() ; i++) {
-        if (v_cl.rank() == 0) {
-            #ifndef NO_PRINT
-            std::cout << "---------------------------------------------------------------------------------------------------" << std::endl;
-            #endif
+        openfpm::vector<openfpm::vector<double>> window_noise;
+        openfpm::vector<int> window_noise_pointer;
+        window_noise.resize(N_sample_opt);
+        window_noise_pointer.resize(N_sample_opt);
+        for (int i = 0; i < N_sample_opt; i++)
+        {
+            window_noise.get(i).resize(30);
+            window_noise_pointer.get(i) = 0;
         }
-        float reg = 2000;
-        int selected_interval = i;
-        double fishing_left = 0.5;
-        double fishing_right = 0.5;
+        int interval_processed = 0;
+        for (int i = 0; i < intervals.size(); i++)
+        {
+            if (v_cl.rank() == 0)
+            {
+#ifndef NO_PRINT
+                std::cout << "---------------------------------------------------------------------------------------------------" << std::endl;
+#endif
+            }
+            float reg = 2000;
+            int selected_interval = i;
+            double fishing_left = 0.5;
+            double fishing_right = 0.5;
 
-        int chromosome = intervals.template get<0>(i);
+            int chromosome = intervals.template get<0>(i);
 
-        // Check there is data
+            // Check there is data
 
-        bool is_zero =  true;
-        for (int j = 0 ; j < N_samples; j++) {
-            if (counts.get(N_samples*i + j) != 0) {
-                is_zero = false;
+            bool is_zero = true;
+            for (int j = 0; j < N_samples; j++)
+            {
+                if (counts.get(N_samples * i + j) != 0)
+                {
+                    is_zero = false;
+                }
+            }
+            if (is_zero == true)
+            {
+                continue;
             }
-        }
-        if (is_zero == true)    {continue;}
-
-        auto lamb = [&](Eigen::VectorXd & vars){
-            return model_function<false,dim,N_int_opt,N_sample_opt>(selected_interval,vars,domain,chr_counts,counts,chromosome,reg);
-        };
 
-        openfpm::vector<double> sol;
-        openfpm::vector<double> confidence;
-        if (v_cl.rank() == 0) {
-            #ifndef NO_PRINT
-            std::cout << "Processing interval: " << interval_processed << std::endl;
-            std::cout << "Chromosome: " << intervals.get<0>(i)+1 << " start: " << intervals.get<1>(i) << " stop: " << intervals.get<2>(i) << std::endl;
-            #endif
-        }
-        if (v_cl.rank() == 0) {
-            int chromosome = intervals.template get<0>(i);
+            auto lamb = [&](Eigen::VectorXd &vars)
+            {
+                return model_function<false, dim, N_int_opt, N_sample_opt>(selected_interval, vars, domain, chr_counts, counts, chromosome, reg);
+            };
 
-            // set chr_count_loc
-            for (int j = 0 ; j < N_sample_opt ; j++) {
-                chr_counts.get(chromosome*N_sample_opt + j) = chr_counts_int.get(N_sample_opt*i+j);
+            openfpm::vector<double> sol;
+            openfpm::vector<double> confidence;
+            if (v_cl.rank() == 0)
+            {
+#ifndef NO_PRINT
+                std::cout << "Processing interval: " << interval_processed << std::endl;
+                std::cout << "Chromosome: " << intervals.get<0>(i) + 1 << " start: " << intervals.get<1>(i) << " stop: " << intervals.get<2>(i) << std::endl;
+#endif
             }
-            if (i == 53295) {
-                int debug = 0;
-                debug++;
+            if (v_cl.rank() == 0)
+            {
+                int chromosome = intervals.template get<0>(i);
+
+                // set chr_count_loc
+                for (int j = 0; j < N_sample_opt; j++)
+                {
+                    chr_counts.get(chromosome * N_sample_opt + j) = chr_counts_int.get(N_sample_opt * i + j);
+                }
+                if (i == 53295)
+                {
+                    int debug = 0;
+                    debug++;
+                }
+                optimize_fast<N_int_opt, N_sample_opt>(fout_CN_prob, domain, 0.0, sol, confidence, counts, chr_counts, window_noise, window_noise_pointer, i, chromosome, intervals.size());
+                for (int k = 0; k < sol.size(); k++)
+                {
+#ifndef NO_PRINT
+                    std::cout << sol.get(k) << '\t';
+#endif
+                }
+                Eigen::VectorXd vars;
+                vars.resize(sol.size());
+                for (int s = 0; s < sol.size(); s++)
+                {
+                    vars(s) = sol.get(s);
+                }
+#ifndef NO_PRINT
+                if (vars(0) > 0.0)
+                {
+                    std::cout << "  f: " << lamb(vars) << std::endl;
+                }
+                else
+                {
+                    std::cout << "  f: " << "TOO LOO QUALITY FOR CALL " << std::endl;
+                }
+                std::cout << std::endl;
+#endif
             }
-            optimize_fast<N_int_opt,N_sample_opt>(fout_CN_prob,domain,0.0,sol,confidence,counts,chr_counts,window_noise,window_noise_pointer,i,chromosome,intervals.size());
-            for (int k = 0 ; k < sol.size() ; k++) {
-                #ifndef NO_PRINT
-                std::cout << sol.get(k) << '\t';
-                #endif
+            v_cl.barrier();
+            // optimize(domain,0.0,sol,lamb);
+            if (v_cl.rank() == 0)
+            {
+#ifndef NO_PRINT
+                std::cout << std::endl;
+#endif
+            }
+            interval_processed++;
+            bool is_call = false;
+            fout << intervals.get<0>(i) + 1 << '\t' << intervals.get<1>(i) << '\t' << intervals.get<2>(i);
+            for (int k = 0; k < sol.size(); k++)
+            {
+                solutions_out.template get<0>(i)[k] = sol.get(k);
+                if (k != 0 && std::round(solutions_out.template get<0>(i)[k]) != 2)
+                {
+                    is_call = true;
+                }
+                if (v_cl.rank() == 0)
+                {
+                    fout << '\t' << solutions_out.template get<0>(i)[k];
+                }
             }
             Eigen::VectorXd vars;
             vars.resize(sol.size());
-            for (int s = 0 ; s < sol.size() ; s++) {
+            for (int s = 0; s < sol.size(); s++)
+            {
                 vars(s) = sol.get(s);
             }
-            #ifndef NO_PRINT
-            if (vars(0) > 0.0) {
-                std::cout << "  f: " << lamb(vars) << std::endl;
-            } else {
-                std::cout << "  f: " << "TOO LOO QUALITY FOR CALL " << std::endl;
-            }
-            std::cout << std::endl;
-            #endif
-        }
-        v_cl.barrier();
-        //optimize(domain,0.0,sol,lamb);
-        if (v_cl.rank() == 0) {
-            #ifndef NO_PRINT
-            std::cout << std::endl;
-            #endif
-        }
-        interval_processed++;
-        bool is_call = false;
-        fout << intervals.get<0>(i)+1 << '\t' <<  intervals.get<1>(i) << '\t' << intervals.get<2>(i);
-        for (int k = 0 ; k < sol.size() ; k++) {
-            solutions_out.template get<0>(i)[k] = sol.get(k);
-            if (k != 0 && std::round(solutions_out.template get<0>(i)[k]) != 2) {
-                is_call = true;
-            }
-            if (v_cl.rank() == 0)
-            {fout << '\t' << solutions_out.template get<0>(i)[k];}
-        }
-        Eigen::VectorXd vars;
-        vars.resize(sol.size());
-        for (int s = 0 ; s < sol.size() ; s++) {
-            vars(s) = sol.get(s);
-        }
 
-        // Print confidence
-        if (v_cl.rank() == 0) {
-            #ifndef NO_PRINT
-            std::cout << "CONFIDENCE: ";
-            for (int i = N_int_opt ; i < N_int_opt + N_sample_opt ; i++) {
-                std::cout << confidence.get(2*i) << "(" << confidence.get(2*i+1) << ")" << " ";
+            // Print confidence
+            if (v_cl.rank() == 0)
+            {
+#ifndef NO_PRINT
+                std::cout << "CONFIDENCE: ";
+                for (int i = N_int_opt; i < N_int_opt + N_sample_opt; i++)
+                {
+                    std::cout << confidence.get(2 * i) << "(" << confidence.get(2 * i + 1) << ")" << " ";
+                }
+                std::cout << std::endl;
+#endif
             }
-            std::cout << std::endl;
-            #endif
-        }
 
-        if (v_cl.rank() == 0) {
-            if (sol.get(0) >= 0.0)
-            {fout << '\t' << lamb(vars) << '\t' << i;}
-            else
-            {fout << '\t' << "NO QUALITY" << '\t' << i;}
-        }
-        if (v_cl.rank() == 0) {
-            if (is_call == true) {
-                #ifndef NO_PRINT
-                std::cout << "----------------------------------------------------------------------------------------" << std::endl;
-                std::cout << "-----------------------------------CALL-------------------------------------------------" << std::endl;
-                std::cout << "----------------------------------------------------------------------------------------" << std::endl;
-                #endif
-                fout << '\t' << "CALL" << std::endl;
-            }
-            else {
-                fout << '\t' << "." << std::endl;
-                #ifndef NO_PRINT
-                std::cout << std::endl;
-                #endif
+            if (v_cl.rank() == 0)
+            {
+                if (sol.get(0) >= 0.0)
+                {
+                    fout << '\t' << lamb(vars) << '\t' << i;
+                }
+                else
+                {
+                    fout << '\t' << "NO QUALITY" << '\t' << i;
+                }
             }
-            #ifndef NO_PRINT
-            for (int j = 0 ; j < N_sample_opt ; j++) {
-                std::cout << basename(files_bams.get(j)) << " " << solutions_out.template get<0>(i)[1+j] << " ";
+            if (v_cl.rank() == 0)
+            {
+                if (is_call == true)
+                {
+#ifndef NO_PRINT
+                    std::cout << "----------------------------------------------------------------------------------------" << std::endl;
+                    std::cout << "-----------------------------------CALL-------------------------------------------------" << std::endl;
+                    std::cout << "----------------------------------------------------------------------------------------" << std::endl;
+#endif
+                    fout << '\t' << "CALL" << std::endl;
+                }
+                else
+                {
+                    fout << '\t' << "." << std::endl;
+#ifndef NO_PRINT
+                    std::cout << std::endl;
+#endif
+                }
+#ifndef NO_PRINT
+                for (int j = 0; j < N_sample_opt; j++)
+                {
+                    std::cout << basename(files_bams.get(j)) << " " << solutions_out.template get<0>(i)[1 + j] << " ";
+                }
+#endif
             }
-            #endif
+            fout << std::flush;
         }
-        fout << std::flush;
-    }
 
-    return 0;
-}
-
-
-std::vector<std::string> split(const std::string& input, const std::string& delimiter) {
-    std::vector<std::string> tokens;
-    size_t start = 0;
-    size_t end = input.find(delimiter);
-
-    while (end != std::string::npos) {
-        tokens.push_back(input.substr(start, end - start));
-        start = end + delimiter.length();
-        end = input.find(delimiter, start);
+        return 0;
     }
 
-    // Add the last token (or the only token if there's no delimiter)
-    tokens.push_back(input.substr(start));
+    std::vector<std::string> split(const std::string &input, const std::string &delimiter)
+    {
+        std::vector<std::string> tokens;
+        size_t start = 0;
+        size_t end = input.find(delimiter);
 
-    return tokens;
-}
+        while (end != std::string::npos)
+        {
+            tokens.push_back(input.substr(start, end - start));
+            start = end + delimiter.length();
+            end = input.find(delimiter, start);
+        }
 
-bool startsWith(const std::string& str, const std::string& prefix) {
-    if (str.length() < prefix.length()) {
-        return false;
-    }
-    return str.substr(0, prefix.length()) == prefix;
-}
+        // Add the last token (or the only token if there's no delimiter)
+        tokens.push_back(input.substr(start));
 
-void read_processed_intervals(std::string bed_f, openfpm::vector<aggregate<short int,int, int>> & intervals, openfpm::vector<float> & values, openfpm::vector<aggregate<float[16]>> & solutions) {
-    std::ifstream procIntervals(bed_f.c_str());
+        return tokens;
+    }
 
-    if (!procIntervals.is_open()) {
-        std::cerr << "Error: Unable to open the BED file." << std::endl;
-        return;
+    bool startsWith(const std::string &str, const std::string &prefix)
+    {
+        if (str.length() < prefix.length())
+        {
+            return false;
+        }
+        return str.substr(0, prefix.length()) == prefix;
     }
 
-    std::string line;
+    void read_processed_intervals(std::string bed_f, openfpm::vector<aggregate<short int, int, int>> &intervals, openfpm::vector<float> &values, openfpm::vector<aggregate<float[16]>> &solutions)
+    {
+        std::ifstream procIntervals(bed_f.c_str());
 
-    int next = 0;
+        if (!procIntervals.is_open())
+        {
+            std::cerr << "Error: Unable to open the BED file." << std::endl;
+            return;
+        }
 
-    char str[256];
+        std::string line;
 
-    while (std::getline(procIntervals, line)) {
-        if (line[0] == 0) {continue;}
-        if (line[0] == '-') {continue;}
+        int next = 0;
 
-        int chr_int;
-        int start;
-        int stop;
+        char str[256];
 
-        if (startsWith(line,"Chromosome:")) {
-            std::string sstart = "start:";
-            std::vector<std::string> v = split(line,sstart);
-            std::string schr = "Chromosome:";
-            std::vector<std::string> v2 = split(v[0],schr);
-            std::string sstop = "stop:";
-            std::vector<std::string> v3 = split(v[1],sstop);
+        while (std::getline(procIntervals, line))
+        {
+            if (line[0] == 0)
+            {
+                continue;
+            }
+            if (line[0] == '-')
+            {
+                continue;
+            }
 
-            chr_int = std::atoi(v2[1].c_str())-1;
-            start = std::atoi(v3[0].c_str());
-            stop = std::atoi(v3[1].c_str());
+            int chr_int;
+            int start;
+            int stop;
+
+            if (startsWith(line, "Chromosome:"))
+            {
+                std::string sstart = "start:";
+                std::vector<std::string> v = split(line, sstart);
+                std::string schr = "Chromosome:";
+                std::vector<std::string> v2 = split(v[0], schr);
+                std::string sstop = "stop:";
+                std::vector<std::string> v3 = split(v[1], sstop);
+
+                chr_int = std::atoi(v2[1].c_str()) - 1;
+                start = std::atoi(v3[0].c_str());
+                stop = std::atoi(v3[1].c_str());
+
+                intervals.add();
+                intervals.last().get<0>() = chr_int;
+                intervals.last().get<1>() = start;
+                intervals.last().get<2>() = stop;
+            }
 
-            intervals.add();
-            intervals.last().get<0>() = chr_int;
-            intervals.last().get<1>() = start;
-            intervals.last().get<2>() = stop;
-        }
+            if (startsWith(line, "Best solution:"))
+            {
+                std::vector<std::string> v = split(line, "solution:");
+                std::vector<std::string> v3 = split(v[1], "with");
+                float value = std::atof(v3[0].c_str());
+                values.add(value);
+            }
 
-        if (startsWith(line,"Best solution:")) {
-            std::vector<std::string> v = split(line,"solution:");
-            std::vector<std::string> v3 = split(v[1],"with");
-            float value = std::atof(v3[0].c_str());
-            values.add(value);
-        }
+            if (next == 1)
+            {
+                next = -1;
+                std::istringstream iss(line);
 
-        if (next == 1)
-        {
-            next = -1;
-            std::istringstream iss(line);
+                solutions.add();
 
-            solutions.add();
-    
-            int i = 0;
-            while (iss) {
-                iss >> solutions.last().get<0>()[i];
-                i++;
+                int i = 0;
+                while (iss)
+                {
+                    iss >> solutions.last().get<0>()[i];
+                    i++;
+                }
+            }
+            if (startsWith(line, "at"))
+            {
+                next = 1;
             }
         }
-        if (startsWith(line,"at")) {
-            next = 1;
-        }
+
+        procIntervals.close();
     }
 
-    procIntervals.close();
-}
+    struct BreakPoint
+    {
+        short int chr;
+        int pos;
+        int count;
+        int depth = 0;
+        int operation = 0;
 
+        BreakPoint() {}
 
+        BreakPoint(const short int &chr, const int &pos, const int &count)
+            : chr(chr), pos(pos), count(count)
+        {
+        }
 
-struct BreakPoint {
-    short int chr;
-    int pos;
-    int count;
-    int depth = 0;
-    int operation = 0;
+        bool operator<(const BreakPoint &b) const
+        {
+            if (chr < b.chr)
+                return true;
+            if (chr > b.chr)
+                return false;
+            if (pos < b.pos)
+                return true;
 
-    BreakPoint() {}
+            return false;
+        }
+    };
 
-    BreakPoint(const short int & chr, const int & pos, const int & count) 
-    :chr(chr),pos(pos),count(count)
-    {}
+    void break_intervals(openfpm::vector<aggregate<short int, int, int>> &intervals, openfpm::vector<aggregate<short int, int, int, int, int>> &breaks)
+    {
+        int j = 0;
 
-    bool operator<(const BreakPoint & b) const {
-        if (chr < b.chr) return true;
-        if (chr > b.chr) return false;
-        if (pos < b.pos) return true;
+        if (breaks.size() == 0)
+        {
+            return;
+        }
 
-        return false;
-    }
-};
+        openfpm::vector<openfpm::vector<aggregate<short int, int, int>>> intervals_tmp;
+        intervals_tmp.resize(intervals.size());
 
-void break_intervals(openfpm::vector<aggregate<short int,int,int>> & intervals, openfpm::vector<aggregate<short int, int, int, int, int>> & breaks) {
-	int j = 0;
+        for (int i = 0; i < intervals.size(); i++)
+        {
+            intervals_tmp.get(i).add(intervals.get(i));
+        }
 
-    if (breaks.size() == 0) {return;}
+        for (int i = 0; i < intervals.size() && j < breaks.size();)
+        {
 
-    openfpm::vector<openfpm::vector<aggregate<short int,int,int>>> intervals_tmp;
-    intervals_tmp.resize(intervals.size());
+            short int chrom_b = breaks.template get<0>(j);
+            int start_b = breaks.template get<1>(j);
 
-    for (int i = 0 ; i < intervals.size() ; i++) {
-        intervals_tmp.get(i).add(intervals.get(i));
-    }
+            short int chrom_i = intervals.template get<0>(i);
+            int start_i = intervals.template get<1>(i);
+            int stop_i = intervals.template get<2>(i);
 
-	for (int i = 0 ; i < intervals.size() && j < breaks.size() ; ) {
+            if (chrom_b > chrom_i)
+            {
+                i++;
+                continue;
+            }
 
-        short int chrom_b = breaks.template get<0>(j);
-        int start_b = breaks.template get<1>(j);
+            if (chrom_i > chrom_b)
+            {
+                j++;
+                continue;
+            }
 
-        short int chrom_i = intervals.template get<0>(i);
-        int start_i = intervals.template get<1>(i);
-        int stop_i = intervals.template get<2>(i);
+            if (start_b >= stop_i)
+            {
+                i++;
+                continue;
+            }
 
-        if (chrom_b > chrom_i) {
-            i++;
-            continue;
-        }
+            if (start_b <= start_i)
+            {
+                j++;
+                continue;
+            }
 
-        if (chrom_i > chrom_b) {
+            // if the breakpoint is 50 bases near to the start or stop of the interval skip it
+            // if (fabs(start_i - start_b) <= 50)  {j++ ; continue;}
+            // if (fabs(start_b - stop_i) <= 50)   {j++; continue;}
+
+            int last = intervals_tmp.get(i).size() - 1;
+            short int chrom_b_last = intervals_tmp.get(i).get<0>(last);
+            int start_i_last = intervals_tmp.get(i).get<1>(last);
+            int stop_i_last = intervals_tmp.get(i).get<2>(last);
+            intervals_tmp.get(i).remove(last);
+            intervals_tmp.get(i).add();
+            intervals_tmp.get(i).get<0>(last) = chrom_b_last;
+            intervals_tmp.get(i).get<1>(last) = start_i_last;
+            intervals_tmp.get(i).get<2>(last) = start_b;
+            intervals_tmp.get(i).add();
+            intervals_tmp.get(i).get<0>(last + 1) = chrom_b;
+            intervals_tmp.get(i).get<1>(last + 1) = start_b;
+            intervals_tmp.get(i).get<2>(last + 1) = stop_i_last;
             j++;
-            continue;
         }
 
-        if (start_b >= stop_i) {
-            i++;
-            continue;
-        }
+        intervals.clear();
 
-        if (start_b <= start_i) {
-            j++;
-            continue;
+        for (int i = 0; i < intervals_tmp.size(); i++)
+        {
+            for (int j = 0; j < intervals_tmp.get(i).size(); j++)
+            {
+                intervals.add(intervals_tmp.get(i).get(j));
+            }
         }
+    }
 
-        // if the breakpoint is 50 bases near to the start or stop of the interval skip it
-        //if (fabs(start_i - start_b) <= 50)  {j++ ; continue;}
-        //if (fabs(start_b - stop_i) <= 50)   {j++; continue;}
-
-        int last = intervals_tmp.get(i).size() - 1;
-        short int chrom_b_last = intervals_tmp.get(i).get<0>(last);
-        int start_i_last = intervals_tmp.get(i).get<1>(last);
-        int stop_i_last = intervals_tmp.get(i).get<2>(last);
-        intervals_tmp.get(i).remove(last);
-        intervals_tmp.get(i).add();
-        intervals_tmp.get(i).get<0>(last) = chrom_b_last;
-        intervals_tmp.get(i).get<1>(last) = start_i_last;
-        intervals_tmp.get(i).get<2>(last) = start_b;
-        intervals_tmp.get(i).add();
-        intervals_tmp.get(i).get<0>(last+1) = chrom_b;
-        intervals_tmp.get(i).get<1>(last+1) = start_b;
-        intervals_tmp.get(i).get<2>(last+1) = stop_i_last;
-        j++;
-	}
+    void find_breakpoint(openfpm::vector<BreakPoint> &brk, short int chrom_t, int start_t, int stop_t, int &b1, int &b2)
+    {
+        int i = 0;
+        int end = brk.size() - 1;
 
+        while (end != i)
+        {
+            int mid = (end - i) / 2 + i;
+            short int mid_chromosome = brk.get(mid).chr;
+            int mid_pos = brk.get(mid).pos;
+
+            if (chrom_t < mid_chromosome)
+            {
+                end = mid - 1;
+                i = (end > i) ? i : end;
+                continue;
+            }
+            if (chrom_t > mid_chromosome)
+            {
+                i = mid + 1;
+                end = (end > i) ? end : i;
+                continue;
+            }
 
-    intervals.clear();
+            if (start_t > mid_pos)
+            {
+                i = mid + 1;
+                end = (end > i) ? end : i;
+                continue;
+            }
+            if (start_t < mid_pos)
+            {
+                end = mid;
+                ;
+                continue;
+            }
 
-    for (int i = 0 ; i < intervals_tmp.size() ; i++) {
-        for (int j = 0 ; j < intervals_tmp.get(i).size() ; j++ ) {
-            intervals.add(intervals_tmp.get(i).get(j));
+            break;
         }
-    }
-}
 
+        b1 = i;
 
-void find_breakpoint(openfpm::vector<BreakPoint> & brk, short int chrom_t, int start_t , int stop_t, int & b1, int & b2) {
-    int i = 0;
-    int end = brk.size() - 1;
+        i = 0;
+        end = brk.size() - 1;
 
-    while (end != i) {
-        int mid = (end - i) / 2 + i;
-        short int mid_chromosome = brk.get(mid).chr;
-        int mid_pos = brk.get(mid).pos;
+        while (end != i)
+        {
+            int mid = (end - i) / 2 + i;
+            short int mid_chromosome = brk.get(mid).chr;
+            int mid_pos = brk.get(mid).pos;
+
+            if (chrom_t < mid_chromosome)
+            {
+                end = mid - 1;
+                i = (end > i) ? i : end;
+                continue;
+            }
+            if (chrom_t > mid_chromosome)
+            {
+                i = mid + 1;
+                (end > i) ? end : i;
+                continue;
+            }
 
-        if (chrom_t < mid_chromosome) {end = mid-1; i = (end > i)?i:end ;continue;}
-        if (chrom_t > mid_chromosome) {i = mid+1; end = (end > i)?end:i ;continue;}
+            if (stop_t > mid_pos)
+            {
+                i = mid + 1;
+                end = (end > i) ? end : i;
+                continue;
+            }
+            if (stop_t < mid_pos)
+            {
+                end = mid;
+                continue;
+            }
 
-        if (start_t > mid_pos) {i = mid+1; end = (end > i)?end:i ;continue;}
-        if (start_t < mid_pos) {end = mid; ;continue;}
+            break;
+        }
 
-        break;
+        b2 = i;
     }
 
-    b1 = i;
+    template <typename T, typename U>
+    struct PairHash
+    {
+        std::size_t operator()(const std::pair<T, U> &p) const
+        {
+            // Combine the two integers into a single hash value
+            std::size_t h1 = std::hash<T>{}(p.first);
+            std::size_t h2 = std::hash<U>{}(p.second);
+            return h1 ^ h2; // You can choose a different combining function if needed
+        }
+    };
 
-    i = 0;
-    end = brk.size() - 1;
+    void read_break_points(std::string &bam_file,
+                           openfpm::vector<aggregate<short int, int, int, int, int>> &break_points_out,
+                           int N_chr,
+                           openfpm::vector<int> &chr_ins)
+    {
 
-    while (end != i) {
-        int mid = (end - i) / 2 + i;
-        short int mid_chromosome = brk.get(mid).chr;
-        int mid_pos = brk.get(mid).pos;
+        std::unordered_map<std::pair<short int, int>, int, PairHash<short, int>> break_points;
+        openfpm::vector<BreakPoint> brk;
 
-        if (chrom_t < mid_chromosome) {end = mid-1; i = (end > i)?i:end ;continue;}
-        if (chrom_t > mid_chromosome) {i = mid+1; (end > i)?end:i; continue;}
+        std::cout << "READING Breakpoint for: " << bam_file << std::endl;
 
-        if (stop_t > mid_pos) {i = mid + 1; end = (end > i)?end:i ; continue;}
-        if (stop_t < mid_pos) {end = mid; continue;}
+        openfpm::vector<openfpm::vector<int>> chr_ins_tmp;
+        chr_ins.resize(N_chr);
+        chr_ins_tmp.resize(N_chr);
+        for (int i = 0; i < N_chr; i++)
+        {
+            chr_ins_tmp.get(i).reserve(33554432);
+        }
 
-        break;
-    }
+        // Read the presence of break points
 
-    b2 = i;
-}
+        int actual_chr = -1;
 
-template <typename T, typename U>
-struct PairHash {
-    std::size_t operator () (const std::pair<T, U> &p) const {
-        // Combine the two integers into a single hash value
-        std::size_t h1 = std::hash<T>{}(p.first);
-        std::size_t h2 = std::hash<U>{}(p.second);
-        return h1 ^ h2; // You can choose a different combining function if needed
-    }
-};
+        {
+            samFile *fp_in = hts_open(bam_file.c_str(), "r"); // open bam file
+            bam_hdr_t *bamHdr = sam_hdr_read(fp_in);          // read header
+            bam1_t *aln = bam_init1();                        // initialize an alignment
 
-void read_break_points(std::string & bam_file, 
-                        openfpm::vector<aggregate<short int,int,int, int, int>> & break_points_out,
-                        int N_chr,
-                        openfpm::vector<int> & chr_ins) {
+            while (sam_read1(fp_in, bamHdr, aln) > 0)
+            {
 
-    std::unordered_map<std::pair<short int, int>,int, PairHash<short,int>> break_points;
-    openfpm::vector<BreakPoint> brk;
+                int32_t pos = aln->core.pos + 1; // left most position of alignment in zero based coordianate (+1)
+                if (aln->core.tid == -1)
+                {
+                    continue;
+                }
+                char *chr = bamHdr->target_name[aln->core.tid]; // contig name (chromosome)
+                uint32_t len = aln->core.l_qseq;                // length of the read.
+                int n_cigar = aln->core.n_cigar;                // number of cigar operations
+                uint32_t *cigar = (uint32_t *)(aln->data + aln->core.l_qname);
 
-    std::cout << "READING Breakpoint for: " << bam_file << std::endl;
+                // if (aln->core.qual < 20) {continue;}
 
-    openfpm::vector<openfpm::vector<int>> chr_ins_tmp;
-    chr_ins.resize(N_chr);
-    chr_ins_tmp.resize(N_chr);
-    for (int i = 0 ; i < N_chr ; i++) {
-        chr_ins_tmp.get(i).reserve(33554432);
-    }
+                short int chr_int = chr_to_chr_int(chr);
+                if (chr_int == -1)
+                {
+                    continue;
+                }
 
-    // Read the presence of break points
+                if (abs(aln->core.isize) > 0)
+                {
+                    chr_ins_tmp.get(chr_int).add(abs(aln->core.isize));
+                }
 
-    int actual_chr = -1;
+                if (chr_int > actual_chr)
+                {
+                    actual_chr = chr_int;
+                    std::cout << "Reading chromosome: " << actual_chr + 1 << std::endl;
+                }
 
-    {
-    samFile *fp_in = hts_open(bam_file.c_str(),"r"); //open bam file
-    bam_hdr_t *bamHdr = sam_hdr_read(fp_in); //read header
-    bam1_t *aln = bam_init1(); //initialize an alignment
-
-    while(sam_read1(fp_in,bamHdr,aln) > 0){
-		
-        int32_t pos = aln->core.pos +1; //left most position of alignment in zero based coordianate (+1)
-        if (aln->core.tid == -1)
-        {continue;}
-        char *chr = bamHdr->target_name[aln->core.tid]; //contig name (chromosome)
-        uint32_t len = aln->core.l_qseq; //length of the read.
-        int n_cigar = aln->core.n_cigar; // number of cigar operations
-        uint32_t * cigar = (uint32_t *)(aln->data + aln->core.l_qname);
+                for (int k = 0; k < n_cigar; k++)
+                {
+                    int op = bam_cigar_opchr(bam_cigar_op(cigar[k]));
+                    int len = bam_cigar_oplen(cigar[k]);
+                    if (op == 'S')
+                    {
+                        break_points[std::make_pair(chr_int, pos)] += 1;
+                        pos += len;
+                    }
+                    else if (op == 'D')
+                    {
+                        if (len < 50)
+                        {
+                            continue;
+                        }
+                        break_points[std::make_pair(chr_int, pos)] += 1;
+                        break_points[std::make_pair(chr_int, pos + len)] += 1;
+                        pos += len;
+                    }
+                    else if (op == 'I')
+                    {
+                        if (len < 50)
+                        {
+                            continue;
+                        }
+                        break_points[std::make_pair(chr_int, pos)] += 1;
+                        break_points[std::make_pair(chr_int, pos + len)] += 1;
+                        pos += len;
+                    }
+                    else
+                    {
+                        pos += len;
+                    }
+                }
+            }
 
-        //if (aln->core.qual < 20) {continue;}
+            bam_destroy1(aln);
+            sam_close(fp_in);
+        }
 
-        short int chr_int = chr_to_chr_int(chr);
-        if (chr_int == -1)  {continue;}
+        // sort all insert size eliminate the outliers (potential deletions)
+        for (int i = 0; i < N_chr; i++)
+        {
+            chr_ins_tmp.get(i).sort();
+            int percent10 = chr_ins_tmp.get(i).size() * 0.10;
+            int percent90 = chr_ins_tmp.get(i).size() * 0.90;
+
+            size_t tot_insert = 0;
+            int n_insert = 0;
+            // Average
+            for (int j = percent10; j < percent90; j++)
+            {
+                tot_insert += chr_ins_tmp.get(i).get(j);
+                n_insert++;
+            }
 
-        if (abs(aln->core.isize) > 0) {
-            chr_ins_tmp.get(chr_int).add(abs(aln->core.isize));
+            chr_ins.get(i) = tot_insert / n_insert;
         }
 
-        if (chr_int > actual_chr) {
-            actual_chr = chr_int;
-            std::cout << "Reading chromosome: " << actual_chr+1 << std::endl;
-        }
+        std::cout << "SORTING BREAKPOINT" << std::endl;
 
-        for (int k = 0 ; k < n_cigar ;  k++) {
-            int op = bam_cigar_opchr(bam_cigar_op(cigar[k]));
-            int len = bam_cigar_oplen(cigar[k]);
-            if (op == 'S') {
-                break_points[std::make_pair(chr_int, pos)] += 1;
-                pos += len;
-            } else if (op == 'D') {
-                if (len < 50) {continue;}
-                break_points[std::make_pair(chr_int, pos)] += 1;
-                break_points[std::make_pair(chr_int, pos+len)] += 1;
-                pos += len;
-            } else if (op == 'I') {
-                if (len < 50) {continue;}
-                break_points[std::make_pair(chr_int, pos)] += 1;
-                break_points[std::make_pair(chr_int, pos+len)] += 1;
-                pos += len;
-            }
-            else {
-                pos += len;
+        for (auto it = break_points.begin(); it != break_points.end(); ++it)
+        {
+            if ((*it).second < 3)
+            {
+                continue;
             }
+            brk.add(BreakPoint((*it).first.first, (*it).first.second, (*it).second));
         }
-	}
-	
-	bam_destroy1(aln);
-	sam_close(fp_in);
-    }
 
-    // sort all insert size eliminate the outliers (potential deletions)
-    for (int i = 0 ; i < N_chr ; i++) {
-        chr_ins_tmp.get(i).sort();
-        int percent10 = chr_ins_tmp.get(i).size() * 0.10;
-        int percent90 = chr_ins_tmp.get(i).size() * 0.90;
+        brk.sort();
 
-        size_t tot_insert = 0;
-        int n_insert = 0;
-        // Average
-        for (int j = percent10 ; j < percent90 ; j++) {
-            tot_insert += chr_ins_tmp.get(i).get(j);
-            n_insert++;
-        }
-
-        chr_ins.get(i) = tot_insert / n_insert;
-    }
+        actual_chr = -1;
+        std::cout << "CALCULATING Breakpoint depth: " << bam_file << std::endl;
 
-    std::cout << "SORTING BREAKPOINT" << std::endl;
+        {
+            // Calculate the depth on the break point
 
-    for (auto it = break_points.begin() ; it != break_points.end() ; ++it) {
-        if ((*it).second < 3) {continue;}
-        brk.add(BreakPoint((*it).first.first,(*it).first.second,(*it).second));
-    }
+            samFile *fp_in = hts_open(bam_file.c_str(), "r"); // open bam file
+            bam_hdr_t *bamHdr = sam_hdr_read(fp_in);          // read header
+            bam1_t *aln = bam_init1();                        // initialize an alignment
 
-    brk.sort();
+            while (sam_read1(fp_in, bamHdr, aln) > 0)
+            {
 
-    actual_chr = -1;
-    std::cout << "CALCULATING Breakpoint depth: " << bam_file << std::endl;
+                int32_t pos = aln->core.pos + 1; // left most position of alignment in zero based coordianate (+1)
+                if (aln->core.tid == -1)
+                {
+                    continue;
+                }
+                char *chr = bamHdr->target_name[aln->core.tid]; // contig name (chromosome)
+                uint32_t len = aln->core.l_qseq;                // length of the read.
+                int n_cigar = aln->core.n_cigar;                // number of cigar operations
+                uint32_t *cigar = (uint32_t *)(aln->data + aln->core.l_qname);
 
-    {
-    // Calculate the depth on the break point
-
-    samFile *fp_in = hts_open(bam_file.c_str(),"r"); //open bam file
-    bam_hdr_t *bamHdr = sam_hdr_read(fp_in); //read header
-    bam1_t *aln = bam_init1(); //initialize an alignment
-
-    while(sam_read1(fp_in,bamHdr,aln) > 0){
-		
-        int32_t pos = aln->core.pos +1; //left most position of alignment in zero based coordianate (+1)
-        if (aln->core.tid == -1)
-        {continue;}
-        char *chr = bamHdr->target_name[aln->core.tid] ; //contig name (chromosome)
-        uint32_t len = aln->core.l_qseq; //length of the read.
-        int n_cigar = aln->core.n_cigar; // number of cigar operations
-        uint32_t * cigar = (uint32_t *)(aln->data + aln->core.l_qname);
+                short int chr_int = chr_to_chr_int(chr);
+                if (chr_int == -1)
+                {
+                    continue;
+                }
 
-        short int chr_int = chr_to_chr_int(chr);
-        if (chr_int == -1)  {continue;}
+                if (chr_int > actual_chr)
+                {
+                    actual_chr = chr_int;
+                    std::cout << "Reading chromosome: " << actual_chr + 1 << std::endl;
+                }
 
-        if (chr_int > actual_chr) {
-            actual_chr = chr_int;
-            std::cout << "Reading chromosome: " << actual_chr+1 << std::endl;
-        }
-		
-        // Fill depth
-        for (int k = 0 ; k < n_cigar ;  k++) {
-            int op = bam_cigar_opchr(bam_cigar_op(cigar[k]));
-            int len = bam_cigar_oplen(cigar[k]);
-            if (op == 'M') {
-                int b1 = 0;
-                int b2 = 0;
-                find_breakpoint(brk,chr_int,pos,pos+len,b1,b2);
-                for (int i = b1 ; i < b2 ; i++) {
-                    brk.get(i).depth++;    
+                // Fill depth
+                for (int k = 0; k < n_cigar; k++)
+                {
+                    int op = bam_cigar_opchr(bam_cigar_op(cigar[k]));
+                    int len = bam_cigar_oplen(cigar[k]);
+                    if (op == 'M')
+                    {
+                        int b1 = 0;
+                        int b2 = 0;
+                        find_breakpoint(brk, chr_int, pos, pos + len, b1, b2);
+                        for (int i = b1; i < b2; i++)
+                        {
+                            brk.get(i).depth++;
+                        }
+                    }
+                    else
+                    {
+                        pos += len;
+                    }
                 }
             }
-            else {
-                pos += len;
-            }
+
+            bam_destroy1(aln);
+            sam_close(fp_in);
         }
-	}
-	
-	bam_destroy1(aln);
-	sam_close(fp_in);
-    }
 
-    // valid break are all points
+        // valid break are all points
 
-    // Copy to the output
+        // Copy to the output
 
-    openfpm::vector<int> remove_list;
-    do {
-        remove_list.clear();
-        for (int i = 0 ; i < brk.size() ; i++) {
-            int k = i-10;
-            k = (k < 0)?0:k;
+        openfpm::vector<int> remove_list;
+        do
+        {
+            remove_list.clear();
+            for (int i = 0; i < brk.size(); i++)
+            {
+                int k = i - 10;
+                k = (k < 0) ? 0 : k;
 
-            for (; k < brk.size() && fabs(brk.get(i).pos - brk.get(k).pos) < 100 ; k++) {
-                if (k == i) {continue;}
-                if (brk.get(i).count < brk.get(k).count) {
-                    remove_list.add(i);
-                    break;
+                for (; k < brk.size() && fabs(brk.get(i).pos - brk.get(k).pos) < 100; k++)
+                {
+                    if (k == i)
+                    {
+                        continue;
+                    }
+                    if (brk.get(i).count < brk.get(k).count)
+                    {
+                        remove_list.add(i);
+                        break;
+                    }
                 }
             }
-        }
-
-        brk.remove(remove_list);
-    } while (remove_list.size() != 0);
 
+            brk.remove(remove_list);
+        } while (remove_list.size() != 0);
 
-    openfpm::vector<int> id_to_remove;
-    // Filter breakpoints by depth
-    for (int i = 0 ; i < brk.size() ; ++i) {
-        if (brk.get(i).depth*0.1 >= 3 && brk.get(i).depth*0.1 > brk.get(i).count) {
-            id_to_remove.add(i);
+        openfpm::vector<int> id_to_remove;
+        // Filter breakpoints by depth
+        for (int i = 0; i < brk.size(); ++i)
+        {
+            if (brk.get(i).depth * 0.1 >= 3 && brk.get(i).depth * 0.1 > brk.get(i).count)
+            {
+                id_to_remove.add(i);
+            }
         }
-    }
-    brk.remove(id_to_remove);
-
-    // Add events to brk
+        brk.remove(id_to_remove);
 
-    {
-    samFile *fp_in = hts_open(bam_file.c_str(),"r"); //open bam file
-    bam_hdr_t *bamHdr = sam_hdr_read(fp_in); //read header
-    bam1_t *aln = bam_init1(); //initialize an alignment
-
-    while(sam_read1(fp_in,bamHdr,aln) > 0){
-		
-        int32_t pos = aln->core.pos +1; //left most position of alignment in zero based coordianate (+1)
-        if (aln->core.tid == -1)
-        {continue;}
-        char *chr = bamHdr->target_name[aln->core.tid] ; //contig name (chromosome)
-        uint32_t len = aln->core.l_qseq; //length of the read.
-        int n_cigar = aln->core.n_cigar; // number of cigar operations
-        uint32_t * cigar = (uint32_t *)(aln->data + aln->core.l_qname);
+        // Add events to brk
 
-        if (aln->core.qual < 20) {continue;}
+        {
+            samFile *fp_in = hts_open(bam_file.c_str(), "r"); // open bam file
+            bam_hdr_t *bamHdr = sam_hdr_read(fp_in);          // read header
+            bam1_t *aln = bam_init1();                        // initialize an alignment
 
-        short int chr_int = chr_to_chr_int(chr);
-        if (chr_int == -1)  {continue;}
-		
-        if (chr_int > actual_chr) {
-            actual_chr = chr_int;
-            std::cout << "Reading chromosome: " << actual_chr+1 << std::endl;
-        }
+            while (sam_read1(fp_in, bamHdr, aln) > 0)
+            {
 
-        for (int k = 0 ; k < n_cigar ;  k++) {
-            int op = bam_cigar_opchr(bam_cigar_op(cigar[k]));
-            int len = bam_cigar_oplen(cigar[k]);
-            if (op == 'S') {
-                if (len < 50) {continue;}
-                // find breakpoints
-                int b1 = 0;
-                int b2 = 0;
-                find_breakpoint(brk,chr_int,pos,pos+len+10,b1,b2);
-                for (int i = b1 ; i < b2 ; i++) {
-                    brk.get(i).operation = 1;
-                }
-                pos += len;
-            } else if (op == 'D') {
-                if (len < 50) {continue;}
-                // find breakpoints
-                int b1 = 0;
-                int b2 = 0;
-                find_breakpoint(brk,chr_int,pos,pos+len+10,b1,b2);
-                for (int i = b1 ; i < b2 ; i++) {
-                    brk.get(i).operation = 1;
+                int32_t pos = aln->core.pos + 1; // left most position of alignment in zero based coordianate (+1)
+                if (aln->core.tid == -1)
+                {
+                    continue;
                 }
-                pos += len;
-            } else if (op == 'I') {
-                if (len < 50) {continue;}
-                pos += len;
-            }
-            else {
-                pos += len;
-            }
-        }
-	}
-	
-	bam_destroy1(aln);
-	sam_close(fp_in);
-    }
+                char *chr = bamHdr->target_name[aln->core.tid]; // contig name (chromosome)
+                uint32_t len = aln->core.l_qseq;                // length of the read.
+                int n_cigar = aln->core.n_cigar;                // number of cigar operations
+                uint32_t *cigar = (uint32_t *)(aln->data + aln->core.l_qname);
 
-    for (int i = 0 ; i < brk.size() ; i++) {
-        break_points_out.add();
-        break_points_out.last().get<0>() = brk.get(i).chr;
-        break_points_out.last().get<1>() = brk.get(i).pos;
-        break_points_out.last().get<2>() = brk.get(i).count;
-        break_points_out.last().get<3>() = brk.get(i).depth;
-        break_points_out.last().get<4>() = brk.get(i).operation;
-    }
-}
+                if (aln->core.qual < 20)
+                {
+                    continue;
+                }
 
-unsigned char get_bits_from_base_char(char base) {
-    if (base == 'A') return 0x00;
-    if (base == 'C') return 0x01;
-    if (base == 'T') return 0x02;
-    if (base == 'G') return 0x03;
-    if (base == 'N') return 0x04;
+                short int chr_int = chr_to_chr_int(chr);
+                if (chr_int == -1)
+                {
+                    continue;
+                }
 
-    std::cout << "ERROR BASE" << std::endl;
-    return 0xFF;
-}
+                if (chr_int > actual_chr)
+                {
+                    actual_chr = chr_int;
+                    std::cout << "Reading chromosome: " << actual_chr + 1 << std::endl;
+                }
 
-void read_fasta(const std::string & filename, openfpm::vector<openfpm::vector<char>> & chr_sequences) {
-    std::cout << "Read reference file: " << filename << std::endl;
-
-    seqan3::sequence_file_input fin{filename.c_str()};
-
-    using record_type = decltype(fin)::record_type;
-
-    int chr_int = 0;
-
-    // You can use a for loop:
-    for (auto & record : fin)
-    {
-        //std::cout << record << std::endl;
-        std::cout << record.id() << std::endl;
-        auto & seq = record.sequence();
-        chr_sequences.add();
-        auto & last_sequence = chr_sequences.last();
-        last_sequence.resize(seq.size() / 2 + seq.size() % 2);
-        for (int j = 0 ; j < seq.size() ; j+=2) {
-            char bases2 = 0;
-
-            if (chr_int == 0 && j == 4356168) {
-                int debug = 0;
-                debug++;
+                for (int k = 0; k < n_cigar; k++)
+                {
+                    int op = bam_cigar_opchr(bam_cigar_op(cigar[k]));
+                    int len = bam_cigar_oplen(cigar[k]);
+                    if (op == 'S')
+                    {
+                        if (len < 50)
+                        {
+                            continue;
+                        }
+                        // find breakpoints
+                        int b1 = 0;
+                        int b2 = 0;
+                        find_breakpoint(brk, chr_int, pos, pos + len + 10, b1, b2);
+                        for (int i = b1; i < b2; i++)
+                        {
+                            brk.get(i).operation = 1;
+                        }
+                        pos += len;
+                    }
+                    else if (op == 'D')
+                    {
+                        if (len < 50)
+                        {
+                            continue;
+                        }
+                        // find breakpoints
+                        int b1 = 0;
+                        int b2 = 0;
+                        find_breakpoint(brk, chr_int, pos, pos + len + 10, b1, b2);
+                        for (int i = b1; i < b2; i++)
+                        {
+                            brk.get(i).operation = 1;
+                        }
+                        pos += len;
+                    }
+                    else if (op == 'I')
+                    {
+                        if (len < 50)
+                        {
+                            continue;
+                        }
+                        pos += len;
+                    }
+                    else
+                    {
+                        pos += len;
+                    }
+                }
             }
 
-            char base = seqan3::to_char(seq[j]);
-            bases2 |= (base == 'A')?0x00:bases2;
-            bases2 |= (base == 'C')?0x01:bases2;
-            bases2 |= (base == 'T')?0x02:bases2;
-            bases2 |= (base == 'G')?0x03:bases2;
-            bases2 |= (base == 'N')?0x04:bases2;
-
-            base = seqan3::to_char(seq[j+1]);
-            bases2 |= (base == 'A')?0x00:bases2;
-            bases2 |= (base == 'C')?0x10:bases2;
-            bases2 |= (base == 'T')?0x20:bases2;
-            bases2 |= (base == 'G')?0x30:bases2;
-            bases2 |= (base == 'N')?0x40:bases2;
-
-            last_sequence.get(j / 2) = bases2;
+            bam_destroy1(aln);
+            sam_close(fp_in);
         }
-        chr_int++;
-    }
-}
 
-struct call_vcf {
-    short int chromosome;
-    int start;
-    int stop;
-    int CN;
-    int num_region;
-    int precise_start;
-    int precise_stop;
-    float quality;
-    openfpm::vector<float> efficiency;
-    openfpm::vector<float> residual;
-};
-
-void read_CNV_hypothesys(const std::string & filename, openfpm::vector<call_vcf> & cnvs_to_test) {
-    // Initialize VCF header and writer
-    htsFile* vcfFile = hts_open(filename.c_str(), "r");
-    if (vcfFile == nullptr) {
-        std::cerr << "Error: Cannot open output VCF file" << std::endl;
-        return;
+        for (int i = 0; i < brk.size(); i++)
+        {
+            break_points_out.add();
+            break_points_out.last().get<0>() = brk.get(i).chr;
+            break_points_out.last().get<1>() = brk.get(i).pos;
+            break_points_out.last().get<2>() = brk.get(i).count;
+            break_points_out.last().get<3>() = brk.get(i).depth;
+            break_points_out.last().get<4>() = brk.get(i).operation;
+        }
     }
 
-    // Read and print VCF records
-    bcf_hdr_t* header = bcf_hdr_read(vcfFile);
-    bcf1_t* record = bcf_init();
+    unsigned char get_bits_from_base_char(char base)
+    {
+        if (base == 'A')
+            return 0x00;
+        if (base == 'C')
+            return 0x01;
+        if (base == 'T')
+            return 0x02;
+        if (base == 'G')
+            return 0x03;
+        if (base == 'N')
+            return 0x04;
 
-    while (bcf_read(vcfFile, header, record) == 0) {
-        bcf_unpack(record, BCF_UN_ALL);
+        std::cout << "ERROR BASE" << std::endl;
+        return 0xFF;
+    }
 
-        for (int i = 1; i < record->n_allele; ++i) {
-            if (strcmp(record->d.allele[i],"<DEL>") == 0) {
-                struct call_vcf vcfc;
+    void read_fasta(const std::string &filename, openfpm::vector<openfpm::vector<char>> &chr_sequences)
+    {
+        std::cout << "Read reference file: " << filename << std::endl;
 
-                vcfc.chromosome = chr_to_chr_int(bcf_hdr_id2name(header, record->rid));
-                vcfc.start = record->pos; // Convert to 0 based index
-                vcfc.stop = record->pos + record->rlen;
-                vcfc.CN = 1;
+        seqan3::sequence_file_input fin{filename.c_str()};
 
-                cnvs_to_test.add(vcfc);
-            }
+        using record_type = decltype(fin)::record_type;
 
-            if (strcmp(record->d.allele[i],"<DUP>") == 0) {
-                struct call_vcf vcfc;
+        int chr_int = 0;
 
-                vcfc.chromosome = chr_to_chr_int(bcf_hdr_id2name(header, record->rid));
-                vcfc.start = record->pos; // Convert to 0 based index
-                vcfc.stop = record->pos + record->rlen;
-                vcfc.CN = 3;
+        // You can use a for loop:
+        for (auto &record : fin)
+        {
+            // std::cout << record << std::endl;
+            std::cout << record.id() << std::endl;
+            auto &seq = record.sequence();
+            chr_sequences.add();
+            auto &last_sequence = chr_sequences.last();
+            last_sequence.resize(seq.size() / 2 + seq.size() % 2);
+            for (int j = 0; j < seq.size(); j += 2)
+            {
+                char bases2 = 0;
+
+                if (chr_int == 0 && j == 4356168)
+                {
+                    int debug = 0;
+                    debug++;
+                }
 
-                cnvs_to_test.add(vcfc);
+                char base = seqan3::to_char(seq[j]);
+                bases2 |= (base == 'A') ? 0x00 : bases2;
+                bases2 |= (base == 'C') ? 0x01 : bases2;
+                bases2 |= (base == 'T') ? 0x02 : bases2;
+                bases2 |= (base == 'G') ? 0x03 : bases2;
+                bases2 |= (base == 'N') ? 0x04 : bases2;
+
+                base = seqan3::to_char(seq[j + 1]);
+                bases2 |= (base == 'A') ? 0x00 : bases2;
+                bases2 |= (base == 'C') ? 0x10 : bases2;
+                bases2 |= (base == 'T') ? 0x20 : bases2;
+                bases2 |= (base == 'G') ? 0x30 : bases2;
+                bases2 |= (base == 'N') ? 0x40 : bases2;
+
+                last_sequence.get(j / 2) = bases2;
             }
+            chr_int++;
         }
     }
 
-    // Clean up
-    bcf_hdr_destroy(header);
-    bcf_destroy(record);
-    bcf_close(vcfFile);
-}
-
-struct CNV_event_link {
-    int call_id;
-    int padding_left;
-    int padding_right;
-    int pos_seed;
-    char path;
-};
-
-
-void print_bases_size_t(size_t bases) {
-    for (int i = 0 ; i < 32 ; i++) {
-        if ((bases & 0x03) == 0) {std::cout << 'A';}
-        if ((bases & 0x03) == 1) {std::cout << 'C';}
-        if ((bases & 0x03) == 2) {std::cout << 'T';}
-        if ((bases & 0x03) == 3) {std::cout << 'G';}
-        bases = bases >> 2;
-    }
-    std::cout << std::endl;
-}
+    struct call_vcf
+    {
+        short int chromosome;
+        int start;
+        int stop;
+        int CN;
+        int num_region;
+        int precise_start;
+        int precise_stop;
+        float quality;
+        openfpm::vector<float> efficiency;
+        openfpm::vector<float> residual;
+    };
+
+    void read_CNV_hypothesys(const std::string &filename, openfpm::vector<call_vcf> &cnvs_to_test)
+    {
+        // Initialize VCF header and writer
+        htsFile *vcfFile = hts_open(filename.c_str(), "r");
+        if (vcfFile == nullptr)
+        {
+            std::cerr << "Error: Cannot open output VCF file" << std::endl;
+            return;
+        }
 
-void print_1_base_right(char base) {
-    base = base >> 4;
+        // Read and print VCF records
+        bcf_hdr_t *header = bcf_hdr_read(vcfFile);
+        bcf1_t *record = bcf_init();
 
-    if ((base & 0x03) == 0) {std::cout << 'A';}
-    if ((base & 0x03) == 1) {std::cout << 'C';}
-    if ((base & 0x03) == 2) {std::cout << 'T';}
-    if ((base & 0x03) == 3) {std::cout << 'G';}
-}
+        while (bcf_read(vcfFile, header, record) == 0)
+        {
+            bcf_unpack(record, BCF_UN_ALL);
 
-void print_1_base_left(char base) {
-    base = base & 0x3;
+            for (int i = 1; i < record->n_allele; ++i)
+            {
+                if (strcmp(record->d.allele[i], "<DEL>") == 0)
+                {
+                    struct call_vcf vcfc;
 
-    if ((base & 0x03) == 0) {std::cout << 'A';}
-    if ((base & 0x03) == 1) {std::cout << 'C';}
-    if ((base & 0x03) == 2) {std::cout << 'T';}
-    if ((base & 0x03) == 3) {std::cout << 'G';}
-}
+                    vcfc.chromosome = chr_to_chr_int(bcf_hdr_id2name(header, record->rid));
+                    vcfc.start = record->pos; // Convert to 0 based index
+                    vcfc.stop = record->pos + record->rlen;
+                    vcfc.CN = 1;
 
-void print_2_bases(char base) {
-    print_1_base_left(base);
-    print_1_base_right(base);
-}
+                    cnvs_to_test.add(vcfc);
+                }
 
-char get_base_from_reference(openfpm::vector<openfpm::vector<char>> & reference, short int chr, int pos) {
-    int pos_r = pos / 2;
-    int pos_rest = pos % 2;
+                if (strcmp(record->d.allele[i], "<DUP>") == 0)
+                {
+                    struct call_vcf vcfc;
 
-    char base_bit = (reference.get(chr).get(pos_r) >> pos_rest*4) & 0x7;
+                    vcfc.chromosome = chr_to_chr_int(bcf_hdr_id2name(header, record->rid));
+                    vcfc.start = record->pos; // Convert to 0 based index
+                    vcfc.stop = record->pos + record->rlen;
+                    vcfc.CN = 3;
 
-    if (base_bit == 0)  return 'A';
-    if (base_bit == 1)  return 'C';
-    if (base_bit == 2)  return 'T';
-    if (base_bit & 0x4) return 'N';
+                    cnvs_to_test.add(vcfc);
+                }
+            }
+        }
 
-    return 'G';
-}
+        // Clean up
+        bcf_hdr_destroy(header);
+        bcf_destroy(record);
+        bcf_close(vcfFile);
+    }
 
-void collect_reads_for_call_evidence_forward(std::string & bam_file, 
-                                    tsl::hopscotch_map<size_t, openfpm::vector<CNV_event_link>> & map,
-                                    openfpm::vector<call_vcf> & calls,
-                                    Sample_call_related_relevant_read_type & seqs,
-                                    openfpm::vector<openfpm::vector<char>> & reference,
-                                    int padding,
-                                    int sub_len) {
+    struct CNV_event_link
+    {
+        int call_id;
+        int padding_left;
+        int padding_right;
+        int pos_seed;
+        char path;
+    };
+
+    void print_bases_size_t(size_t bases)
+    {
+        for (int i = 0; i < 32; i++)
+        {
+            if ((bases & 0x03) == 0)
+            {
+                std::cout << 'A';
+            }
+            if ((bases & 0x03) == 1)
+            {
+                std::cout << 'C';
+            }
+            if ((bases & 0x03) == 2)
+            {
+                std::cout << 'T';
+            }
+            if ((bases & 0x03) == 3)
+            {
+                std::cout << 'G';
+            }
+            bases = bases >> 2;
+        }
+        std::cout << std::endl;
+    }
 
-   int n_reads = 0;
+    void print_1_base_right(char base)
+    {
+        base = base >> 4;
 
-    char seq1[16384];
-    char seq2[16384];
-    char seq3[16384];
+        if ((base & 0x03) == 0)
+        {
+            std::cout << 'A';
+        }
+        if ((base & 0x03) == 1)
+        {
+            std::cout << 'C';
+        }
+        if ((base & 0x03) == 2)
+        {
+            std::cout << 'T';
+        }
+        if ((base & 0x03) == 3)
+        {
+            std::cout << 'G';
+        }
+    }
 
-    int actual_chr = -1;
+    void print_1_base_left(char base)
+    {
+        base = base & 0x3;
 
-    samFile *fp_in = hts_open(bam_file.c_str(),"r"); //open bam file
+        if ((base & 0x03) == 0)
+        {
+            std::cout << 'A';
+        }
+        if ((base & 0x03) == 1)
+        {
+            std::cout << 'C';
+        }
+        if ((base & 0x03) == 2)
+        {
+            std::cout << 'T';
+        }
+        if ((base & 0x03) == 3)
+        {
+            std::cout << 'G';
+        }
+    }
 
-    if (fp_in == 0x0) {
-        std::cerr << __FILE__ << ":" << __LINE__ << " Error opening the file " << bam_file << std::endl;
-        return;
+    void print_2_bases(char base)
+    {
+        print_1_base_left(base);
+        print_1_base_right(base);
     }
 
-    bam_hdr_t *bamHdr = sam_hdr_read(fp_in); //read header
-    bam1_t *aln = bam_init1(); //initialize an alignment
+    char get_base_from_reference(openfpm::vector<openfpm::vector<char>> &reference, short int chr, int pos)
+    {
+        int pos_r = pos / 2;
+        int pos_rest = pos % 2;
+
+        char base_bit = (reference.get(chr).get(pos_r) >> pos_rest * 4) & 0x7;
+
+        if (base_bit == 0)
+            return 'A';
+        if (base_bit == 1)
+            return 'C';
+        if (base_bit == 2)
+            return 'T';
+        if (base_bit & 0x4)
+            return 'N';
+
+        return 'G';
+    }
+
+    void collect_reads_for_call_evidence_forward(std::string &bam_file,
+                                                 tsl::hopscotch_map<size_t, openfpm::vector<CNV_event_link>> &map,
+                                                 openfpm::vector<call_vcf> &calls,
+                                                 Sample_call_related_relevant_read_type &seqs,
+                                                 openfpm::vector<openfpm::vector<char>> &reference,
+                                                 int padding,
+                                                 int sub_len)
+    {
 
-    while(sam_read1(fp_in,bamHdr,aln) > 0){
-		
-        int32_t pos = aln->core.pos +1; //left most position of alignment in zero based coordianate (+1)
-        if (aln->core.tid == -1)
-        {continue;}
-        char *chr = bamHdr->target_name[aln->core.tid] ; //contig name (chromosome)
-        uint32_t len = aln->core.l_qseq; //length of the read.
-        int n_cigar = aln->core.n_cigar; // number of cigar operations
-        uint32_t * cigar = (uint32_t *)(aln->data + aln->core.l_qname);
-        char * read_name = (char *)&aln->data[0];
+        int n_reads = 0;
 
-        uint8_t *q = bam_get_seq(aln); //quality string
-        uint32_t q2 = aln->core.qual ;
-        auto flag = aln->core.flag;
+        char seq1[16384];
+        char seq2[16384];
+        char seq3[16384];
 
-        if ((flag & 0x20) == 0)
-        {
-            continue;
-        }
+        int actual_chr = -1;
 
-        short int chr_int = chr_to_chr_int(chr);
-        if (chr_int == -1)  {continue;}
+        samFile *fp_in = hts_open(bam_file.c_str(), "r"); // open bam file
 
-        if (chr_int > actual_chr) {
-            actual_chr = chr_int;
-            std::cout << "Reading forward chromosome: " << actual_chr+1 << std::endl;
+        if (fp_in == 0x0)
+        {
+            std::cerr << __FILE__ << ":" << __LINE__ << " Error opening the file " << bam_file << std::endl;
+            return;
         }
 
-        size_t bases_seq = 0;
-        for (int i = 0 ; i < len ; i++) {
-            bases_seq = bases_seq << 2;
-            char base = seq_nt16_str[bam_seqi(q,i)];
-            bases_seq |= (base == 'A')?0x00:0x00;
-            bases_seq |= (base == 'C')?0x01:0x00;
-            bases_seq |= (base == 'T')?0x02:0x00;
-            bases_seq |= (base == 'G')?0x03:0x00;
-
-            if (i >= 31) {
-                auto fnd = map.find(bases_seq);
-                if (fnd != map.end())
-                {
-                    //std::cout << "FOUND PATTERN " << bam_get_qname(aln) << std::endl;
-
-                    // This seed can be associated to multiple calls, go across all of them
-                    for (int v = 0 ; v < fnd->second.size() ; v++) {
-                        int cid = fnd->second.get(v).call_id;
-                        //std::cout << calls.get(cid).chromosome << " START: " << calls.get(cid).start << " STOP: " << calls.get(cid).stop << " CN: " << calls.get(cid).CN << std::endl;
-
-                        //print_bases_size_t(bases_seq);
-
-                        // Check the pattern
-                        if (fnd->second.get(v).path == 0) {
-                            // check the reference
-                            std::cout << calls.get(cid).start << " " << fnd->second.get(v).padding_left << " " << i << std::endl;
-                            // This is the start of the read given by the seed position
-                            int start = calls.get(cid).start + fnd->second.get(v).padding_left-i-1;
-                            int start_call;
-
-                            // check if the start is inside the call
-                            if (start < calls.get(cid).stop &&
-                                start > calls.get(cid).start ) {
-                                    start_call = calls.get(cid).start -(calls.get(cid).stop - start);
-                            }
-                            else {
-                                start_call = start;
-                            }
-
+        bam_hdr_t *bamHdr = sam_hdr_read(fp_in); // read header
+        bam1_t *aln = bam_init1();               // initialize an alignment
 
-                            int seed_pos = i-31;
-                            int call_distance_from_start = calls.get(cid).start - start;
-
-                            n_reads++;
+        while (sam_read1(fp_in, bamHdr, aln) > 0)
+        {
 
-                            if (n_reads % 1000 == 0) {std::cout << "READS to SAVE " << n_reads << " " << chr_int << ":" << pos << std::endl;}
+            int32_t pos = aln->core.pos + 1; // left most position of alignment in zero based coordianate (+1)
+            if (aln->core.tid == -1)
+            {
+                continue;
+            }
+            char *chr = bamHdr->target_name[aln->core.tid]; // contig name (chromosome)
+            uint32_t len = aln->core.l_qseq;                // length of the read.
+            int n_cigar = aln->core.n_cigar;                // number of cigar operations
+            uint32_t *cigar = (uint32_t *)(aln->data + aln->core.l_qname);
+            char *read_name = (char *)&aln->data[0];
+
+            uint8_t *q = bam_get_seq(aln); // quality string
+            uint32_t q2 = aln->core.qual;
+            auto flag = aln->core.flag;
+
+            if ((flag & 0x20) == 0)
+            {
+                continue;
+            }
 
-                            // Smith–Waterman algorithm to compare the read with the reference
-                            // and the read with the reference with the deletion performed
+            short int chr_int = chr_to_chr_int(chr);
+            if (chr_int == -1)
+            {
+                continue;
+            }
 
-                            for (int j = 0 ; j < len ; j++) {
-                                seq2[j] = seq_nt16_str[bam_seqi(q,j)];
-                                seq1[j] = get_base_from_reference(reference,calls.get(cid).chromosome,start+j);
-                            }
+            if (chr_int > actual_chr)
+            {
+                actual_chr = chr_int;
+                std::cout << "Reading forward chromosome: " << actual_chr + 1 << std::endl;
+            }
 
-                            seq1[len] = 0;
-                            seq2[len] = 0;
+            size_t bases_seq = 0;
+            for (int i = 0; i < len; i++)
+            {
+                bases_seq = bases_seq << 2;
+                char base = seq_nt16_str[bam_seqi(q, i)];
+                bases_seq |= (base == 'A') ? 0x00 : 0x00;
+                bases_seq |= (base == 'C') ? 0x01 : 0x00;
+                bases_seq |= (base == 'T') ? 0x02 : 0x00;
+                bases_seq |= (base == 'G') ? 0x03 : 0x00;
+
+                if (i >= 31)
+                {
+                    auto fnd = map.find(bases_seq);
+                    if (fnd != map.end())
+                    {
+                        // std::cout << "FOUND PATTERN " << bam_get_qname(aln) << std::endl;
+
+                        // This seed can be associated to multiple calls, go across all of them
+                        for (int v = 0; v < fnd->second.size(); v++)
+                        {
+                            int cid = fnd->second.get(v).call_id;
+                            // std::cout << calls.get(cid).chromosome << " START: " << calls.get(cid).start << " STOP: " << calls.get(cid).stop << " CN: " << calls.get(cid).CN << std::endl;
+
+                            // print_bases_size_t(bases_seq);
+
+                            // Check the pattern
+                            if (fnd->second.get(v).path == 0)
+                            {
+                                // check the reference
+                                std::cout << calls.get(cid).start << " " << fnd->second.get(v).padding_left << " " << i << std::endl;
+                                // This is the start of the read given by the seed position
+                                int start = calls.get(cid).start + fnd->second.get(v).padding_left - i - 1;
+                                int start_call;
+
+                                // check if the start is inside the call
+                                if (start < calls.get(cid).stop &&
+                                    start > calls.get(cid).start)
+                                {
+                                    start_call = calls.get(cid).start - (calls.get(cid).stop - start);
+                                }
+                                else
+                                {
+                                    start_call = start;
+                                }
 
-                            SequentialImplementation sw1(seq2,seq1,1,0,-1);
-                            sw1.runAlgorithm();
+                                int seed_pos = i - 31;
+                                int call_distance_from_start = calls.get(cid).start - start;
 
+                                n_reads++;
 
-                            int k = 0;
-                            int s = 0;
-                          for (int k = -padding ; k <= padding ; k++) {
-                              for (int s = -padding ; s <= padding ; s++) {
+                                if (n_reads % 1000 == 0)
+                                {
+                                    std::cout << "READS to SAVE " << n_reads << " " << chr_int << ":" << pos << std::endl;
+                                }
 
+                                // Smith–Waterman algorithm to compare the read with the reference
+                                // and the read with the reference with the deletion performed
 
-                                    int base_jump = calls.get(cid).start+k - start_call;
-                                    for (int j = 0 ; j < len ; j++) {                    
-                                        if (start_call + j < calls.get(cid).start+k) {
-                                            seq3[j] = get_base_from_reference(reference,calls.get(cid).chromosome,start_call+j);
-                                        } else {
-                                            seq3[j] = get_base_from_reference(reference,calls.get(cid).chromosome,calls.get(cid).stop+s+j-base_jump);
-                                        }
-                                    }
+                                for (int j = 0; j < len; j++)
+                                {
+                                    seq2[j] = seq_nt16_str[bam_seqi(q, j)];
+                                    seq1[j] = get_base_from_reference(reference, calls.get(cid).chromosome, start + j);
+                                }
 
-                                    seq3[len] = 0;
+                                seq1[len] = 0;
+                                seq2[len] = 0;
 
-                                    SequentialImplementation sw2(seq2,seq3,1,0,-1);
-                                    sw2.runAlgorithm();
+                                SequentialImplementation sw1(seq2, seq1, 1, 0, -1);
+                                sw1.runAlgorithm();
 
-                                    int best_sw1 = 0;
+                                int k = 0;
+                                int s = 0;
+                                for (int k = -padding; k <= padding; k++)
+                                {
+                                    for (int s = -padding; s <= padding; s++)
                                     {
-                                        auto & results = sw1.getResults();
-
-                                        for(size_t j=0;j<results[0].size();j++){
-                                            // std::cout << "Match " << j+1 << " [Score: " << results[0][j].score << ", Start: " << results[0][j].start << ", Stop: " << results[0][j].stop << "]" << endl;
-                                            // std::cout << "	D: " << results[0][j].result_pair.d << endl;
-                                            // std::cout << "	Q: " << results[0][j].result_pair.q << endl;
-                                            // std::cout << "SCORE: " <<  results[0][j].score << std::endl;
-                                            if (results[0][j].score > best_sw1) {
-                                                best_sw1 = results[0][j].score;
+
+                                        int base_jump = calls.get(cid).start + k - start_call;
+                                        for (int j = 0; j < len; j++)
+                                        {
+                                            if (start_call + j < calls.get(cid).start + k)
+                                            {
+                                                seq3[j] = get_base_from_reference(reference, calls.get(cid).chromosome, start_call + j);
+                                            }
+                                            else
+                                            {
+                                                seq3[j] = get_base_from_reference(reference, calls.get(cid).chromosome, calls.get(cid).stop + s + j - base_jump);
                                             }
                                         }
-                                    }
 
-                                    int best_sw2 = 0;
-                                    {
-                                        auto & results = sw2.getResults();
-
-                                        for(size_t j=0;j<results[0].size();j++){
-                                            // std::cout << "Match " << j+1 << " [Score: " << results[0][j].score << ", Start: " << results[0][j].start << ", Stop: " << results[0][j].stop << "]" << endl;
-                                            // std::cout << "	D: " << results[0][j].result_pair.d << endl;
-                                            // std::cout << "	Q: " << results[0][j].result_pair.q << endl;
-                                            // std::cout << "SCORE: " << results[0][j].score << std::endl;
-                                            if (results[0][j].score > best_sw2) {
-                                                best_sw2 = results[0][j].score;
+                                        seq3[len] = 0;
+
+                                        SequentialImplementation sw2(seq2, seq3, 1, 0, -1);
+                                        sw2.runAlgorithm();
+
+                                        int best_sw1 = 0;
+                                        {
+                                            auto &results = sw1.getResults();
+
+                                            for (size_t j = 0; j < results[0].size(); j++)
+                                            {
+                                                // std::cout << "Match " << j+1 << " [Score: " << results[0][j].score << ", Start: " << results[0][j].start << ", Stop: " << results[0][j].stop << "]" << endl;
+                                                // std::cout << "	D: " << results[0][j].result_pair.d << endl;
+                                                // std::cout << "	Q: " << results[0][j].result_pair.q << endl;
+                                                // std::cout << "SCORE: " <<  results[0][j].score << std::endl;
+                                                if (results[0][j].score > best_sw1)
+                                                {
+                                                    best_sw1 = results[0][j].score;
+                                                }
                                             }
                                         }
-                                    }
 
-                                    if (best_sw1 >= len-sub_len || best_sw2 >= len-sub_len) {
-                                        seqs.get<0>(cid).add();
-                                        int last = seqs.get<0>(cid).size() - 1;
-                                        seqs.get<0>(cid).get<0>(last).resize(len);
-                                        for (int s = 0 ; s < len ; s++) {
-                                            seqs.get<0>(cid).get<0>(last).template get<0>(s) = seq2[s];
+                                        int best_sw2 = 0;
+                                        {
+                                            auto &results = sw2.getResults();
+
+                                            for (size_t j = 0; j < results[0].size(); j++)
+                                            {
+                                                // std::cout << "Match " << j+1 << " [Score: " << results[0][j].score << ", Start: " << results[0][j].start << ", Stop: " << results[0][j].stop << "]" << endl;
+                                                // std::cout << "	D: " << results[0][j].result_pair.d << endl;
+                                                // std::cout << "	Q: " << results[0][j].result_pair.q << endl;
+                                                // std::cout << "SCORE: " << results[0][j].score << std::endl;
+                                                if (results[0][j].score > best_sw2)
+                                                {
+                                                    best_sw2 = results[0][j].score;
+                                                }
+                                            }
                                         }
 
-                                        if (seqs.get<0>(cid).get<0>(last).size() < aln->core.l_qname) {
-                                            seqs.get<0>(cid).get<0>(last).resize(aln->core.l_qname+1);
-                                        }
-                                        for (int s = 0 ; s < aln->core.l_qname ; s++) {
-                                            seqs.get<0>(cid).get<0>(last).template get<1>(s) = read_name[s];
-                                            seqs.get<0>(cid).get<0>(last).template get<2>(s) = read_name[s];
-                                        }
-                                        seqs.get<0>(cid).get<0>(last).template get<1>(aln->core.l_qname) = 0; 
-                                        seqs.get<0>(cid).get<0>(last).template get<2>(aln->core.l_qname) = 0;
+                                        if (best_sw1 >= len - sub_len || best_sw2 >= len - sub_len)
+                                        {
+                                            seqs.get<0>(cid).add();
+                                            int last = seqs.get<0>(cid).size() - 1;
+                                            seqs.get<0>(cid).get<0>(last).resize(len);
+                                            for (int s = 0; s < len; s++)
+                                            {
+                                                seqs.get<0>(cid).get<0>(last).template get<0>(s) = seq2[s];
+                                            }
+
+                                            if (seqs.get<0>(cid).get<0>(last).size() < aln->core.l_qname)
+                                            {
+                                                seqs.get<0>(cid).get<0>(last).resize(aln->core.l_qname + 1);
+                                            }
+                                            for (int s = 0; s < aln->core.l_qname; s++)
+                                            {
+                                                seqs.get<0>(cid).get<0>(last).template get<1>(s) = read_name[s];
+                                                seqs.get<0>(cid).get<0>(last).template get<2>(s) = read_name[s];
+                                            }
+                                            seqs.get<0>(cid).get<0>(last).template get<1>(aln->core.l_qname) = 0;
+                                            seqs.get<0>(cid).get<0>(last).template get<2>(aln->core.l_qname) = 0;
+
+                                            seqs.get<0>(cid).get<1>(last) = chr_int;
+                                            seqs.get<0>(cid).get<2>(last) = start;
+                                            seqs.get<0>(cid).get<3>(last) = flag;
+                                            seqs.get<0>(cid).get<4>(last) = seed_pos;
 
-                                        seqs.get<0>(cid).get<1>(last) = chr_int;
-                                        seqs.get<0>(cid).get<2>(last) = start;
-                                        seqs.get<0>(cid).get<3>(last) = flag;
-                                        seqs.get<0>(cid).get<4>(last) = seed_pos;
+                                            std::cout << "READ: " << read_name << "  " << seq2 << "   seed " << bases_seq << " SEQBASES: " << string_from_32bases_pattern(bases_seq) << " pos " << seed_pos << std::endl;
 
-                                        std::cout << "READ: " << read_name << "  " << seq2 << "   seed " << bases_seq << " SEQBASES: " << string_from_32bases_pattern(bases_seq) << " pos " << seed_pos << std::endl;
-                                        
-                                        goto found_read;
+                                            goto found_read;
+                                        }
                                     }
                                 }
-                            }
 
                             found_read:;
+                            }
                         }
-                    }
 
-                    break;
+                        break;
+                    }
                 }
             }
         }
 
-	}
-	
-	bam_destroy1(aln);
-	sam_close(fp_in);
-
-}
+        bam_destroy1(aln);
+        sam_close(fp_in);
+    }
 
-void collect_reads_for_call_evidence_reverse(std::string & bam_file, 
-                                    Sample_call_related_relevant_read_type & seqs, 
-                                    int num_calls) {
+    void collect_reads_for_call_evidence_reverse(std::string &bam_file,
+                                                 Sample_call_related_relevant_read_type &seqs,
+                                                 int num_calls)
+    {
 
-    int actual_chr = -1;
+        int actual_chr = -1;
 
-    samFile *fp_in = hts_open(bam_file.c_str(),"r"); //open bam file
+        samFile *fp_in = hts_open(bam_file.c_str(), "r"); // open bam file
 
-    if (fp_in == 0x0) {
-        std::cerr << __FILE__ << ":" << __LINE__ << " Error opening the file " << bam_file << std::endl;
-        return;
-    }
+        if (fp_in == 0x0)
+        {
+            std::cerr << __FILE__ << ":" << __LINE__ << " Error opening the file " << bam_file << std::endl;
+            return;
+        }
 
-    bam_hdr_t *bamHdr = sam_hdr_read(fp_in); //read header
-    bam1_t *aln = bam_init1(); //initialize an alignment
-    char * read_name = (char *)&aln->data[0];
+        bam_hdr_t *bamHdr = sam_hdr_read(fp_in); // read header
+        bam1_t *aln = bam_init1();               // initialize an alignment
+        char *read_name = (char *)&aln->data[0];
 
-    // Remove duplicate sequences
+        // Remove duplicate sequences
 
-    tsl::hopscotch_map<std::string, size_t> map_reads;
+        tsl::hopscotch_map<std::string, size_t> map_reads;
 
-    for (int i = 0 ; i < seqs.size() ; i++) {
-        map_reads.clear();
-        for (int j = 0 ; j < seqs.get<0>(i).size() ; j++) {
-            std::string str;
-            int k = 0;
-            while (seqs.get<0>(i).get<0>(j).get<1>(k) != 0) {
-                str.push_back(seqs.get<0>(i).get<0>(j).get<1>(k));
-                k++;
-            }
+        for (int i = 0; i < seqs.size(); i++)
+        {
+            map_reads.clear();
+            for (int j = 0; j < seqs.get<0>(i).size(); j++)
+            {
+                std::string str;
+                int k = 0;
+                while (seqs.get<0>(i).get<0>(j).get<1>(k) != 0)
+                {
+                    str.push_back(seqs.get<0>(i).get<0>(j).get<1>(k));
+                    k++;
+                }
 
-            if (map_reads.find(str) != map_reads.end()) {
-                // found
-                seqs.get<0>(i).remove(j);
-            }
-            else {
-                map_reads[str] = 1;
+                if (map_reads.find(str) != map_reads.end())
+                {
+                    // found
+                    seqs.get<0>(i).remove(j);
+                }
+                else
+                {
+                    map_reads[str] = 1;
+                }
             }
         }
-    }
 
-    openfpm::vector<openfpm::vector<size_t>> read_to_calls;
-    read_to_calls.resize(num_calls);
+        openfpm::vector<openfpm::vector<size_t>> read_to_calls;
+        read_to_calls.resize(num_calls);
 
-    map_reads.clear();
+        map_reads.clear();
 
-    for (int i = 0 ; i < seqs.size() ; i++) {
-        for (int j = 0 ; j < seqs.get<0>(i).size() ; j++) {
-            std::string str;
-            int k = 0;
-            while (seqs.get<0>(i).get<0>(j).get<1>(k) != 0) {
-                str.push_back(seqs.get<0>(i).get<0>(j).get<1>(k));
-                k++;
-            }
+        for (int i = 0; i < seqs.size(); i++)
+        {
+            for (int j = 0; j < seqs.get<0>(i).size(); j++)
+            {
+                std::string str;
+                int k = 0;
+                while (seqs.get<0>(i).get<0>(j).get<1>(k) != 0)
+                {
+                    str.push_back(seqs.get<0>(i).get<0>(j).get<1>(k));
+                    k++;
+                }
 
-            // if the entry str in map_reads already exists it means that the read has been selected by two calls
+                // if the entry str in map_reads already exists it means that the read has been selected by two calls
 
-            if (map_reads.find(str) != map_reads.end()) {
-                // found
-                size_t id = map_reads[str];
+                if (map_reads.find(str) != map_reads.end())
+                {
+                    // found
+                    size_t id = map_reads[str];
 
-                read_to_calls.get(id).add(((size_t)i << 32) + j);
-            }
-            else {
-                read_to_calls.add();
-                read_to_calls.last().add(((size_t)i << 32) + j);
+                    read_to_calls.get(id).add(((size_t)i << 32) + j);
+                }
+                else
+                {
+                    read_to_calls.add();
+                    read_to_calls.last().add(((size_t)i << 32) + j);
 
-                map_reads[str] = read_to_calls.size()-1;
+                    map_reads[str] = read_to_calls.size() - 1;
+                }
             }
         }
-    }
 
-    while(sam_read1(fp_in,bamHdr,aln) > 0){
-		
-        int32_t pos = aln->core.pos +1; //left most position of alignment in zero based coordianate (+1)
-        if (aln->core.tid == -1)
-        {continue;}
-        char *chr = bamHdr->target_name[aln->core.tid] ; //contig name (chromosome)
-        uint32_t len = aln->core.l_qseq; //length of the read.
-        int n_cigar = aln->core.n_cigar; // number of cigar operations
-        uint32_t * cigar = (uint32_t *)(aln->data + aln->core.l_qname);
-        char * read_name = (char *)&aln->data[0];
-        auto flag = aln->core.flag;
+        while (sam_read1(fp_in, bamHdr, aln) > 0)
+        {
 
-        uint8_t *q = bam_get_seq(aln); //quality string
-        uint32_t q2 = aln->core.qual;
+            int32_t pos = aln->core.pos + 1; // left most position of alignment in zero based coordianate (+1)
+            if (aln->core.tid == -1)
+            {
+                continue;
+            }
+            char *chr = bamHdr->target_name[aln->core.tid]; // contig name (chromosome)
+            uint32_t len = aln->core.l_qseq;                // length of the read.
+            int n_cigar = aln->core.n_cigar;                // number of cigar operations
+            uint32_t *cigar = (uint32_t *)(aln->data + aln->core.l_qname);
+            char *read_name = (char *)&aln->data[0];
+            auto flag = aln->core.flag;
 
-        short int chr_int = chr_to_chr_int(chr);
-        if (chr_int == -1)  {continue;}
+            uint8_t *q = bam_get_seq(aln); // quality string
+            uint32_t q2 = aln->core.qual;
 
-        std::string str(read_name);
-        auto it = map_reads.find(str);
-        if (map_reads.find(str) != map_reads.end()) {
-            // found
+            short int chr_int = chr_to_chr_int(chr);
+            if (chr_int == -1)
+            {
+                continue;
+            }
 
-            int id = it->second;
+            std::string str(read_name);
+            auto it = map_reads.find(str);
+            if (map_reads.find(str) != map_reads.end())
+            {
+                // found
 
-            for (int v = 0 ; v < read_to_calls.get(id).size() ; v++) {
-                int j = read_to_calls.get(id).get(v) & 0xffffffff;
-                int i = read_to_calls.get(id).get(v) >> 32;
+                int id = it->second;
 
-                if ((flag & 0x20) == 0) {
-                    if (seqs.get<0>(i).get<0>(j).size() < len) {
-                        int old_len = seqs.get<0>(i).get<0>(j).size();
-                        seqs.get<0>(i).get<0>(j).resize(len);
-                        seqs.get<0>(i).get<0>(j).get<0>(old_len) = -1;
-                    }
+                for (int v = 0; v < read_to_calls.get(id).size(); v++)
+                {
+                    int j = read_to_calls.get(id).get(v) & 0xffffffff;
+                    int i = read_to_calls.get(id).get(v) >> 32;
+
+                    if ((flag & 0x20) == 0)
+                    {
+                        if (seqs.get<0>(i).get<0>(j).size() < len)
+                        {
+                            int old_len = seqs.get<0>(i).get<0>(j).size();
+                            seqs.get<0>(i).get<0>(j).resize(len);
+                            seqs.get<0>(i).get<0>(j).get<0>(old_len) = -1;
+                        }
 
-                    for (int k = 0 ; k < len ; k++) {
-                        seqs.get<0>(i).get<0>(j).get<1>(k) = seq_nt16_str[bam_seqi(q,k)];
+                        for (int k = 0; k < len; k++)
+                        {
+                            seqs.get<0>(i).get<0>(j).get<1>(k) = seq_nt16_str[bam_seqi(q, k)];
+                        }
                     }
                 }
             }
-        }
 
-        if (chr_int > actual_chr) {
-            actual_chr = chr_int;
-            std::cout << "Reading reverse chromosome: " << actual_chr+1 << std::endl;
+            if (chr_int > actual_chr)
+            {
+                actual_chr = chr_int;
+                std::cout << "Reading reverse chromosome: " << actual_chr + 1 << std::endl;
+            }
         }
-	}
-	
-	bam_destroy1(aln);
-	sam_close(fp_in);
-
-}
-
-void collect_reads_for_call_evidence(std::string & bam_file, 
-                                    tsl::hopscotch_map<size_t, openfpm::vector<CNV_event_link>> & map,
-                                    openfpm::vector<call_vcf> & calls/**/,
-                                    Sample_call_related_relevant_read_type & seqs,
-                                    openfpm::vector<openfpm::vector<char>> & reference,
-                                    int padding,
-                                    int sub_len = 3) {
-    
-    // now we check all the read if they have a matching patterns
-    seqs.resize(calls.size());
-
-    collect_reads_for_call_evidence_forward(bam_file,map,calls,seqs,reference,padding,sub_len);
-    collect_reads_for_call_evidence_reverse(bam_file,seqs,calls.size());
-
-    //
-    std::cout << "COMPLETED " << bam_file << std::endl;
-}
 
-int get_32bases_pattern(int chrom,
-                         int start,
-                         openfpm::vector<openfpm::vector<char>> & chr_sequences,
-                         size_t & seed) {
-
-    // Store the patterns related to the reference
-    int chr = chrom;
-    int pos = start / 2;
-    int pos_rest = (start % 2)*2;
-
-    size_t bases_pattern = 0;
-
-    int loop_size = 16;
-    auto & seq = chr_sequences.get(chr);
-    if (pos_rest != 0) {
-        char base_bit = seq.get(pos) >> 4;
-        if (base_bit == 4) {return -1;}
-        bases_pattern |= base_bit;
-        loop_size = 15;
+        bam_destroy1(aln);
+        sam_close(fp_in);
     }
 
-    int k = 0;
-    for ( ; k < loop_size ; k++) {
-        bases_pattern = bases_pattern << 2;
-        char base_bit = seq.get(pos + k + (pos_rest != 0)) & 0x7;
-        if (base_bit == 4) {return -1;}
-        bases_pattern |= ((size_t)base_bit);
-        base_bit = seq.get(pos + k + (pos_rest != 0)) >> 4;
-        bases_pattern = bases_pattern << 2;
-        if (base_bit == 4) {return -1;}
-        bases_pattern |= ((size_t)base_bit);
-    }
+    void collect_reads_for_call_evidence(std::string &bam_file,
+                                         tsl::hopscotch_map<size_t, openfpm::vector<CNV_event_link>> &map,
+                                         openfpm::vector<call_vcf> &calls /**/,
+                                         Sample_call_related_relevant_read_type &seqs,
+                                         openfpm::vector<openfpm::vector<char>> &reference,
+                                         int padding,
+                                         int sub_len = 3)
+    {
 
-    if (pos_rest != 0) {
-        bases_pattern = bases_pattern << 2;
-        char base_bit = seq.get(pos + k + 1) & 0x7;
-        if (base_bit == 4) {return -1;}
-        bases_pattern |= ((size_t)base_bit);
-    }
+        // now we check all the read if they have a matching patterns
+        seqs.resize(calls.size());
 
-    seed = bases_pattern;
-    return 0;
-}
+        collect_reads_for_call_evidence_forward(bam_file, map, calls, seqs, reference, padding, sub_len);
+        collect_reads_for_call_evidence_reverse(bam_file, seqs, calls.size());
 
-size_t convert_to_bit_pattern(const char * bases) {
-    size_t bases_pattern = 0;
-    for (int k = 0 ; k < 32 ; k++) {
-        bases_pattern = bases_pattern << 2;
-        char base_bit;
-        if (bases[k] == 'A') {base_bit = 0x00;}
-        else if (bases[k] == 'C') {base_bit = 0x01;}
-        else if (bases[k] == 'T') {base_bit = 0x02;}
-        else if (bases[k] == 'G') {base_bit = 0x03;}
-        bases_pattern |= ((size_t)base_bit);
+        //
+        std::cout << "COMPLETED " << bam_file << std::endl;
     }
 
-    return bases_pattern;
-}
+    int get_32bases_pattern(int chrom,
+                            int start,
+                            openfpm::vector<openfpm::vector<char>> &chr_sequences,
+                            size_t &seed)
+    {
 
-int get_Nbases_pattern(int chrom,
-                         int start,
-                         openfpm::vector<openfpm::vector<char>> & chr_sequences,
-                         int N,
-                         size_t & seed) {
-
-    // Store the patterns related to the reference
-    int chr = chrom;
-    int pos = start / 2;
-    int pos_rest = (start % 2)*2;
-
-    size_t bases_pattern = seed;
-
-    int n = 0;
-    int loop_size = std::ceil((float)N / 2);
-    auto & seq = chr_sequences.get(chr);
-    if (pos_rest != 0) {
-        bases_pattern = bases_pattern << 2;
-        char base_bit = seq.get(pos) >> 4;
-        if (base_bit == 4) {return -1;}
-        bases_pattern |= base_bit;
-        if (N % 2 == 1) {loop_size--;}
-        n++;
-    }
+        // Store the patterns related to the reference
+        int chr = chrom;
+        int pos = start / 2;
+        int pos_rest = (start % 2) * 2;
 
-    int k = 0;
-    for ( ; k < loop_size && n < N ; k++ ) {
-        bases_pattern = bases_pattern << 2;
-        char base_bit = seq.get(pos + k + (pos_rest != 0)) & 0x7;
-        if (base_bit == 4) {return -1;}
-        bases_pattern |= ((size_t)base_bit);
-        n++;
-        if (n >= N) {break;}
-        base_bit = seq.get(pos + k + (pos_rest != 0)) >> 4;
-        bases_pattern = bases_pattern << 2;
-        if (base_bit == 4) {return -1;}
-        bases_pattern |= ((size_t)base_bit);
-        n++;
-    }
+        size_t bases_pattern = 0;
 
-    seed = bases_pattern;
-    return 0;
-}
+        int loop_size = 16;
+        auto &seq = chr_sequences.get(chr);
+        if (pos_rest != 0)
+        {
+            char base_bit = seq.get(pos) >> 4;
+            if (base_bit == 4)
+            {
+                return -1;
+            }
+            bases_pattern |= base_bit;
+            loop_size = 15;
+        }
 
-int get_32bases_pattern_with_gap(int chrom,
-                         int start,
-                         openfpm::vector<openfpm::vector<char>> & chr_sequences,
-                         int start_gap,
-                         int end_gap,
-                         size_t & seed) {
+        int k = 0;
+        for (; k < loop_size; k++)
+        {
+            bases_pattern = bases_pattern << 2;
+            char base_bit = seq.get(pos + k + (pos_rest != 0)) & 0x7;
+            if (base_bit == 4)
+            {
+                return -1;
+            }
+            bases_pattern |= ((size_t)base_bit);
+            base_bit = seq.get(pos + k + (pos_rest != 0)) >> 4;
+            bases_pattern = bases_pattern << 2;
+            if (base_bit == 4)
+            {
+                return -1;
+            }
+            bases_pattern |= ((size_t)base_bit);
+        }
 
-    seed = 0;
+        if (pos_rest != 0)
+        {
+            bases_pattern = bases_pattern << 2;
+            char base_bit = seq.get(pos + k + 1) & 0x7;
+            if (base_bit == 4)
+            {
+                return -1;
+            }
+            bases_pattern |= ((size_t)base_bit);
+        }
 
-    if (start_gap - start >= 32) {
-        get_32bases_pattern(chrom,start,chr_sequences,seed);
+        seed = bases_pattern;
+        return 0;
     }
 
-    get_Nbases_pattern(chrom,start,chr_sequences,start_gap-start,seed);
-    get_Nbases_pattern(chrom,end_gap,chr_sequences,32-(start_gap-start),seed);
-
-    return 0;
-}
+    size_t convert_to_bit_pattern(const char *bases)
+    {
+        size_t bases_pattern = 0;
+        for (int k = 0; k < 32; k++)
+        {
+            bases_pattern = bases_pattern << 2;
+            char base_bit;
+            if (bases[k] == 'A')
+            {
+                base_bit = 0x00;
+            }
+            else if (bases[k] == 'C')
+            {
+                base_bit = 0x01;
+            }
+            else if (bases[k] == 'T')
+            {
+                base_bit = 0x02;
+            }
+            else if (bases[k] == 'G')
+            {
+                base_bit = 0x03;
+            }
+            bases_pattern |= ((size_t)base_bit);
+        }
 
-size_t add_32bases_pattern(int chrom,
-                        int start,
-                        openfpm::vector<openfpm::vector<char>> & chr_sequences,
-                        tsl::hopscotch_map<size_t, openfpm::vector<CNV_event_link>> & map,
-                        int call_id,
-                        int padding_left,
-                        int padding_right) {
-
-    size_t bases_pattern;
-    int ret = get_32bases_pattern(chrom,start,chr_sequences,bases_pattern);
-    if (ret != 0) return -1;
-
-    openfpm::vector<CNV_event_link> & calls = map[bases_pattern];
-
-    struct CNV_event_link cel;
-    cel.call_id = call_id;
-    cel.padding_left = padding_left;
-    cel.padding_right = padding_right;
-    cel.path = 0x0;
-    cel.pos_seed = start;
-    calls.add(cel);
-
-    return bases_pattern;
-}
+        return bases_pattern;
+    }
 
-size_t create_seed_variation_from_variant(int chrom, 
-                                            int rec_pos, 
-                                            int start, 
-                                            size_t bases_pattern, 
-                                            const char * ref, 
-                                            const char * alt,
-                                            openfpm::vector<openfpm::vector<char>> & chr_sequences) {
-    int pos_inv = 31-(rec_pos - start);
-    int pos = rec_pos - start;
+    int get_Nbases_pattern(int chrom,
+                           int start,
+                           openfpm::vector<openfpm::vector<char>> &chr_sequences,
+                           int N,
+                           size_t &seed)
+    {
 
-    // delete the base in bases_pattern
+        // Store the patterns related to the reference
+        int chr = chrom;
+        int pos = start / 2;
+        int pos_rest = (start % 2) * 2;
 
-    int n_ref = std::strlen(ref);
+        size_t bases_pattern = seed;
 
-    // add the new base
+        int n = 0;
+        int loop_size = std::ceil((float)N / 2);
+        auto &seq = chr_sequences.get(chr);
+        if (pos_rest != 0)
+        {
+            bases_pattern = bases_pattern << 2;
+            char base_bit = seq.get(pos) >> 4;
+            if (base_bit == 4)
+            {
+                return -1;
+            }
+            bases_pattern |= base_bit;
+            if (N % 2 == 1)
+            {
+                loop_size--;
+            }
+            n++;
+        }
 
-    int n_alt = std::strlen(alt);
+        int k = 0;
+        for (; k < loop_size && n < N; k++)
+        {
+            bases_pattern = bases_pattern << 2;
+            char base_bit = seq.get(pos + k + (pos_rest != 0)) & 0x7;
+            if (base_bit == 4)
+            {
+                return -1;
+            }
+            bases_pattern |= ((size_t)base_bit);
+            n++;
+            if (n >= N)
+            {
+                break;
+            }
+            base_bit = seq.get(pos + k + (pos_rest != 0)) >> 4;
+            bases_pattern = bases_pattern << 2;
+            if (base_bit == 4)
+            {
+                return -1;
+            }
+            bases_pattern |= ((size_t)base_bit);
+            n++;
+        }
 
-    size_t bases_pattern_hole = bases_pattern;
-    int k = (ref[0] == alt[0])?1:0;
-    for ( ; k < n_ref && (pos_inv-k) >= 0 ; k++) {
-        bases_pattern_hole &= ~((size_t)0x3 << ((pos_inv-k)*2));
+        seed = bases_pattern;
+        return 0;
     }
 
-    if (n_ref - n_alt != 0)
+    int get_32bases_pattern_with_gap(int chrom,
+                                     int start,
+                                     openfpm::vector<openfpm::vector<char>> &chr_sequences,
+                                     int start_gap,
+                                     int end_gap,
+                                     size_t &seed)
     {
-        size_t bases_pattern_2;
-        int ret = get_32bases_pattern(chrom,rec_pos+n_ref - n_alt + 1,chr_sequences,bases_pattern_2);
-        bases_pattern_2 = bases_pattern_2 >> (pos+n_alt)*2;
 
-        // nullify the bases
-        for (int k = pos+(ref[0] == alt[0]) ; k < 32 ; k++) {
-            bases_pattern_hole &= ~((size_t)0x3 << ((31-k)*2));
+        seed = 0;
+
+        if (start_gap - start >= 32)
+        {
+            get_32bases_pattern(chrom, start, chr_sequences, seed);
         }
 
-        // merge bases_pattern and bases_pattern_2
-        bases_pattern_hole |= bases_pattern_2;
-    }
+        get_Nbases_pattern(chrom, start, chr_sequences, start_gap - start, seed);
+        get_Nbases_pattern(chrom, end_gap, chr_sequences, 32 - (start_gap - start), seed);
 
-    size_t bases_pattern_alt;
-    for (int s = 0 ; s < n_alt ; s++) {
-        char base = alt[0];
-        size_t base_bit = 0;
-        if (base == 'A')
-        {base_bit = 0x00;}
-        else if (base == 'C')
-        {base_bit = 0x01;}
-        else if (base == 'T')
-        {base_bit = 0x02;}
-        else if (base == 'G')
-        {base_bit = 0x03;}
-
-        bases_pattern_alt = bases_pattern_hole | (base_bit << ((pos_inv-s)*2));
+        return 0;
     }
 
-    return bases_pattern_alt;
-}
-
-struct variant {
-    int pos;
-    std::string ref;
-    std::string alt;
-    float freq;
-};
-
-size_t add_32bases_pattern_with_variability(int chrom,
-                        int start,
-                        openfpm::vector<openfpm::vector<char>> & chr_sequences,
-                        tsl::hopscotch_map<size_t, openfpm::vector<CNV_event_link>> & map,
-                        const char * database,
-                        int call_id,
-                        int padding_left,
-                        int padding_right) {
-
-    size_t bases_pattern;
-    int ret = get_32bases_pattern(chrom,start,chr_sequences,bases_pattern);
-    if (ret != 0) return -1;
-
-    openfpm::vector<CNV_event_link> & calls = map[bases_pattern];
-
-    struct CNV_event_link cel;
-    cel.call_id = call_id;
-    cel.padding_left = padding_left;
-    cel.padding_right = padding_right;
-    cel.path = 0x0;
-    cel.pos_seed = start;
-    calls.add(cel);
-
-    std::string str;
-    if (chrom == 23) {
-        str += std::to_string("X") + ":" + std::to_string(start+1) + "-" + std::to_string(start+32+1);
-    } else if (chrom == 24) {
-        str += std::to_string("MT") + ":" + std::to_string(start+1) + "-" + std::to_string(start+32+1);
-    } else {
-        str += std::to_string(chrom+1) + ":" + std::to_string(start+1) + "-" + std::to_string(start+32+1);
-    }
+    size_t add_32bases_pattern(int chrom,
+                               int start,
+                               openfpm::vector<openfpm::vector<char>> &chr_sequences,
+                               tsl::hopscotch_map<size_t, openfpm::vector<CNV_event_link>> &map,
+                               int call_id,
+                               int padding_left,
+                               int padding_right)
+    {
 
-    bcf_srs_t *sr = bcf_sr_init();
+        size_t bases_pattern;
+        int ret = get_32bases_pattern(chrom, start, chr_sequences, bases_pattern);
+        if (ret != 0)
+            return -1;
 
-    bcf_sr_set_opt(sr, BCF_SR_REQUIRE_IDX);
-    bcf_sr_set_regions(sr,str.c_str(),false);
-    bcf_sr_add_reader(sr,database);
+        openfpm::vector<CNV_event_link> &calls = map[bases_pattern];
 
-    // get the header of the vcf file
-    bcf_hdr_t *hdr = bcf_sr_get_header(sr,0);
+        struct CNV_event_link cel;
+        cel.call_id = call_id;
+        cel.padding_left = padding_left;
+        cel.padding_right = padding_right;
+        cel.path = 0x0;
+        cel.pos_seed = start;
+        calls.add(cel);
 
-    openfpm::vector<variant> variants;
+        return bases_pattern;
+    }
 
-    while ( bcf_sr_next_line(sr) )
+    size_t create_seed_variation_from_variant(int chrom,
+                                              int rec_pos,
+                                              int start,
+                                              size_t bases_pattern,
+                                              const char *ref,
+                                              const char *alt,
+                                              openfpm::vector<openfpm::vector<char>> &chr_sequences)
     {
-        for (int i=0; i<sr->nreaders; i++)
-        {
-            if ( !bcf_sr_has_line(sr,i) ) continue;
-            bcf1_t *rec = bcf_sr_get_line(sr, i);
-            if (rec->pos >= start && rec->pos < start+32) { 
+        int pos_inv = 31 - (rec_pos - start);
+        int pos = rec_pos - start;
 
-                for (int j=1; j<rec->n_allele; j++)
-                {
-                    variants.add();
+        // delete the base in bases_pattern
 
-                    variants.last().pos = rec->pos;
-                    variants.last().ref = std::string(rec->d.allele[0]);
-                    variants.last().alt = std::string(rec->d.allele[j]);
+        int n_ref = std::strlen(ref);
 
-                    int n_float = 1;
-                    void * ptr[1];
-                    ptr[0] = &variants.last().freq;
+        // add the new base
 
-                    // Get the frequency from AF in info of rec
-                    int err = bcf_get_info_float(hdr, rec, "AF",ptr,&n_float);
-                }
-            }
-        }
-    }
-
-    bcf_sr_destroy(sr);
-
-    // Go across the group of variants
-
-    int n_bits = ((variants.size() < 16)?variants.size():16);
-    int n_var_groups = 2 << (n_bits-1);
-
-    for (short int i = 1 ; i < n_var_groups ; i++) {
-        double freq = 1.0;
-
-        int n_indel = 0;
-        int n_snv = 0;
-
-        for (int j = 0 ; j < n_bits ; j++) {
-            if ((i >> j) & 0x1) {
-                if (variants.get(j).freq == 0.0) {
-                    freq *= 1e-9;
-                } else {
-                    freq *= variants.get(j).freq;
-                }
+        int n_alt = std::strlen(alt);
 
-                if (variants.get(j).ref.size() == 1 && variants.get(j).alt.size() == 1) {
-                    n_snv++;
-                }
-                else {
-                    n_indel++;
-                }
-            }
+        size_t bases_pattern_hole = bases_pattern;
+        int k = (ref[0] == alt[0]) ? 1 : 0;
+        for (; k < n_ref && (pos_inv - k) >= 0; k++)
+        {
+            bases_pattern_hole &= ~((size_t)0x3 << ((pos_inv - k) * 2));
         }
 
-        if (n_indel > 1) {continue;}
-        if (n_indel == 1 && n_snv != 0) {continue;}
-
-        if (freq >= 1e-9) {
-            // construct the seed (indels are single)
+        if (n_ref - n_alt != 0)
+        {
+            size_t bases_pattern_2;
+            int ret = get_32bases_pattern(chrom, rec_pos + n_ref - n_alt + 1, chr_sequences, bases_pattern_2);
+            bases_pattern_2 = bases_pattern_2 >> (pos + n_alt) * 2;
+
+            // nullify the bases
+            for (int k = pos + (ref[0] == alt[0]); k < 32; k++)
+            {
+                bases_pattern_hole &= ~((size_t)0x3 << ((31 - k) * 2));
+            }
 
-            size_t bases_pattern_alt = bases_pattern;
+            // merge bases_pattern and bases_pattern_2
+            bases_pattern_hole |= bases_pattern_2;
+        }
 
-            for (int j = 0 ; j < n_bits ; j++) {
-                if ((i >> j) & 0x1) {
-                    bases_pattern_alt = create_seed_variation_from_variant(chrom,
-                                                                            variants.get(j).pos,
-                                                                            start,
-                                                                            bases_pattern_alt,
-                                                                            variants.get(j).ref.c_str(),
-                                                                            variants.get(j).alt.c_str(),
-                                                                            chr_sequences);
-                }
+        size_t bases_pattern_alt;
+        for (int s = 0; s < n_alt; s++)
+        {
+            char base = alt[0];
+            size_t base_bit = 0;
+            if (base == 'A')
+            {
+                base_bit = 0x00;
+            }
+            else if (base == 'C')
+            {
+                base_bit = 0x01;
+            }
+            else if (base == 'T')
+            {
+                base_bit = 0x02;
+            }
+            else if (base == 'G')
+            {
+                base_bit = 0x03;
             }
 
-            
-            openfpm::vector<CNV_event_link> & calls = map[bases_pattern_alt];
-
-            struct CNV_event_link cel;
-            cel.call_id = call_id;
-            cel.padding_left = padding_left;
-            cel.padding_right = padding_right;
-            cel.path = 0x0;
-            cel.pos_seed = start;
-            calls.add(cel);
+            bases_pattern_alt = bases_pattern_hole | (base_bit << ((pos_inv - s) * 2));
         }
+
+        return bases_pattern_alt;
     }
 
-    return bases_pattern;
-}
+    struct variant
+    {
+        int pos;
+        std::string ref;
+        std::string alt;
+        float freq;
+    };
+
+    size_t add_32bases_pattern_with_variability(int chrom,
+                                                int start,
+                                                openfpm::vector<openfpm::vector<char>> &chr_sequences,
+                                                tsl::hopscotch_map<size_t, openfpm::vector<CNV_event_link>> &map,
+                                                const char *database,
+                                                int call_id,
+                                                int padding_left,
+                                                int padding_right)
+    {
 
-void add_32bases_pattern_with_variability_range_shift(int chrom,
-                        int start,
-                        int stop,
-                        int shift,
-                        openfpm::vector<openfpm::vector<char>> & chr_sequences,
-                        tsl::hopscotch_map<size_t, openfpm::vector<CNV_event_link>> & map,
-                        const char * database,
-                        int call_id,
-                        int padding_left,
-                        int padding_right) {
-
-    for (int i = start ; i <= stop ; i+= shift) {
-        add_32bases_pattern_with_variability(chrom,i,chr_sequences,map,database,call_id,padding_left+(i-start),padding_right);
-    }
-}
+        size_t bases_pattern;
+        int ret = get_32bases_pattern(chrom, start, chr_sequences, bases_pattern);
+        if (ret != 0)
+            return -1;
 
-size_t add_32bases_pattern_with_gap(int chrom,
-                        int start,
-                        openfpm::vector<openfpm::vector<char>> & chr_sequences,
-                        tsl::hopscotch_map<size_t, openfpm::vector<CNV_event_link>> & map,
-                        int start_gap,
-                        int end_gap,
-                        int call_id,
-                        int padding_left,
-                        int padding_right) {
-
-    size_t bases_pattern;
-    int ret = get_32bases_pattern_with_gap(chrom,start,chr_sequences,start_gap,end_gap,bases_pattern);
-    if (ret != 0) return -1;
-
-    openfpm::vector<CNV_event_link> & calls = map[bases_pattern];
-
-    struct CNV_event_link cel;
-    cel.call_id = call_id;
-    cel.padding_left = padding_left;
-    cel.padding_right = padding_right;
-    cel.path = 0x0;
-    cel.pos_seed = start;
-    calls.add(cel);
-
-    return bases_pattern;
-}
+        openfpm::vector<CNV_event_link> &calls = map[bases_pattern];
 
-void get_sequence(openfpm::vector<openfpm::vector<char>> & reference, short int chr , int start, int stop, int p2, int p3, char * seq) {
-    if (p2 == -1) {
-        for (int i = start ; i < stop ; i++) {
-            seq[i-start] = get_base_from_reference(reference,chr,i);
+        struct CNV_event_link cel;
+        cel.call_id = call_id;
+        cel.padding_left = padding_left;
+        cel.padding_right = padding_right;
+        cel.path = 0x0;
+        cel.pos_seed = start;
+        calls.add(cel);
+
+        std::string str;
+        if (chrom == 23)
+        {
+            str += std::to_string("X") + ":" + std::to_string(start + 1) + "-" + std::to_string(start + 32 + 1);
         }
-        seq[stop-start] = 0;
-    } else {
-        for (int i = start ; i < p2 ; i++) {
-            seq[i-start] = get_base_from_reference(reference,chr,i);
+        else if (chrom == 24)
+        {
+            str += std::to_string("MT") + ":" + std::to_string(start + 1) + "-" + std::to_string(start + 32 + 1);
         }
-
-        for (int i = p3 ; i < stop ; i++) {
-            seq[i-p3 + (p2 - start)] = get_base_from_reference(reference,chr,i);
+        else
+        {
+            str += std::to_string(chrom + 1) + ":" + std::to_string(start + 1) + "-" + std::to_string(start + 32 + 1);
         }
-        seq[stop - p3 + p2 - start] = 0;
-    }
-}
-
-/*double calculate_event_probability(bam1_t * aln, 
-                                    bam_hdr_t * bamHdr, 
-                                    openfpm::vector<openfpm::vector<char>> & reference, 
-                                    double reading_error,
-                                    int expected_insert_size,
-                                    openfpm::vector<int> & chr_ins) {
-
-    int n_cigar = aln->core.n_cigar; // number of cigar operations
-    uint32_t * cigar = (uint32_t *)(aln->data + aln->core.l_qname);
-    int32_t pos = aln->core.pos +1;
-    uint8_t *q = bam_get_seq(aln);
 
-    char *chr = bamHdr->target_name[aln->core.tid];
+        bcf_srs_t *sr = bcf_sr_init();
 
-    short int chr_int = chr_to_chr_int(chr);
-    if (chr_int == -1)  {return 0.0;}
+        bcf_sr_set_opt(sr, BCF_SR_REQUIRE_IDX);
+        bcf_sr_set_regions(sr, str.c_str(), false);
+        bcf_sr_add_reader(sr, database);
 
-    double aligment_probability = 1.0;
-    int rpos = 0;
-    for (int k = 0 ; k < n_cigar ;  k++) {
-        int op = bam_cigar_opchr(bam_cigar_op(cigar[k]));
-        int len = bam_cigar_oplen(cigar[k]);
-        if (op == 'M') {
-            for (int j = 0 ; j < len ; j++, rpos++) {
-                char base = seq_nt16_str[bam_seqi(q,rpos)];
-                aligment_probability*=(get_base_from_reference(reference,chr_int,pos+j) == base)?(1.0-reading_error):reading_error;
-            }
-        } else {
-            for (int j = 0 ; j < len ; j++, rpos++) {
-                aligment_probability *= reading_error;
-            }
-            pos += len;
-        }
-    }
+        // get the header of the vcf file
+        bcf_hdr_t *hdr = bcf_sr_get_header(sr, 0);
 
-    return aligment_probability;
-}*/
+        openfpm::vector<variant> variants;
 
-double calculate_event_probability_between_to_sequences(char * seq1, 
-                                                        char * seq2,
-                                                        double reading_error) {
-    double align_probability = 0.0;
-    int len = strlen(seq1);
-    int len2 = strlen(seq2);
-
-    len = (len2 < len)?len2:len;
+        while (bcf_sr_next_line(sr))
+        {
+            for (int i = 0; i < sr->nreaders; i++)
+            {
+                if (!bcf_sr_has_line(sr, i))
+                    continue;
+                bcf1_t *rec = bcf_sr_get_line(sr, i);
+                if (rec->pos >= start && rec->pos < start + 32)
+                {
 
-    for(size_t j=0;j<len;j++) {
-        align_probability += (seq1[j] == seq2[j])?(log(1.0-reading_error)):log(reading_error);
-    }
+                    for (int j = 1; j < rec->n_allele; j++)
+                    {
+                        variants.add();
 
-    return align_probability;
-}
+                        variants.last().pos = rec->pos;
+                        variants.last().ref = std::string(rec->d.allele[0]);
+                        variants.last().alt = std::string(rec->d.allele[j]);
 
-double insert_probability(int ins, openfpm::vector<double> & bp_insert_prob) {
-    if (abs(ins) < bp_insert_prob.size()) {
-        return bp_insert_prob.get(abs(ins));
-    }
-    return 1.7e-8;
-}
+                        int n_float = 1;
+                        void *ptr[1];
+                        ptr[0] = &variants.last().freq;
 
-struct ProbsRead {
-    double log_align_probability;
-    double log_pair_probability;
-    double log_insert_probability;
-};
-
-void calculate_event_probability(char * seq1, 
-                                    char * seq2, 
-                                    char * seq3,
-                                    int expected_insert_size,
-                                    short int chr_int,
-                                    int pos,
-                                    double reading_error,
-                                    openfpm::vector<int> & chr_ins,
-                                    openfpm::vector<openfpm::vector<char>> & reference,
-                                    int & best_insert,
-                                    openfpm::vector<double> & bp_insert_prob,
-                                    ProbsRead & probs) {
-
-    char seq4[16384];
-    double align_probability = calculate_event_probability_between_to_sequences(seq1,seq2,reading_error);
-
-    // get the sequence
-    int len = strlen(seq1);
-
-    int max_i;
-    double max = -1.0e300;
-    for (int i = -4*chr_ins.get(chr_int) ; i < 4*chr_ins.get(chr_int) ; i++) {
-
-        get_sequence(reference,chr_int,pos+i,pos+i+len,-1,-1,seq4);
-
-        if (expected_insert_size != -1) {
-            // poisson_distribution(expected_insert_size,abs(i))
-            double event_p = log(insert_probability(abs(i),bp_insert_prob)) + calculate_event_probability_between_to_sequences(seq4,seq3,reading_error);
-            if (event_p > max) {
-                max = event_p;
-                max_i = i;
-            }
-        } else {
-            // poisson_distribution(chr_ins.get(chr_int),abs(i))
-            double event_p = log(insert_probability(abs(i),bp_insert_prob)) + calculate_event_probability_between_to_sequences(seq4,seq3,reading_error);
-            if (event_p > max) {
-                max = event_p;
-                max_i = i;
+                        // Get the frequency from AF in info of rec
+                        int err = bcf_get_info_float(hdr, rec, "AF", ptr, &n_float);
+                    }
+                }
             }
         }
-    }
 
-    best_insert = max_i;
-
-    probs.log_align_probability = align_probability;
-    probs.log_pair_probability = max;
-    probs.log_insert_probability = log(insert_probability(abs(max_i),bp_insert_prob));
-}
+        bcf_sr_destroy(sr);
 
-struct seed_pos{
-    short int chr;
-    int pos;
-    int cid;
-};
+        // Go across the group of variants
 
-struct seed_id{
-    size_t seed;
-    openfpm::vector<seed_pos> calls;
+        int n_bits = ((variants.size() < 16) ? variants.size() : 16);
+        int n_var_groups = 2 << (n_bits - 1);
 
-    bool operator<(const seed_id & tmp) const {
-        return seed < tmp.seed;
-    }
-};
+        for (short int i = 1; i < n_var_groups; i++)
+        {
+            double freq = 1.0;
 
+            int n_indel = 0;
+            int n_snv = 0;
 
-void get_reference_point(openfpm::vector<seed_id> & seed,
-                        openfpm::vector<openfpm::vector<char>> & reference, 
-                        openfpm::vector<openfpm::vector<aggregate<short int, int, int>>> & un_seed) {
-    seed.sort();
+            for (int j = 0; j < n_bits; j++)
+            {
+                if ((i >> j) & 0x1)
+                {
+                    if (variants.get(j).freq == 0.0)
+                    {
+                        freq *= 1e-9;
+                    }
+                    else
+                    {
+                        freq *= variants.get(j).freq;
+                    }
 
-    int latest_n_base = 0;
-    size_t seq = 0;
-    for (int i = 0 ; i < reference.size() ; i++) {
-        for (int j = 0 ; j < 2*reference.get(i).size() ; j++) {
+                    if (variants.get(j).ref.size() == 1 && variants.get(j).alt.size() == 1)
+                    {
+                        n_snv++;
+                    }
+                    else
+                    {
+                        n_indel++;
+                    }
+                }
+            }
 
-            char base = get_base_from_reference(reference,i,j);
-            if (base == 'N'){
-                latest_n_base = 0;
+            if (n_indel > 1)
+            {
+                continue;
             }
-            seq |= get_bits_from_base_char(base);
-            if (latest_n_base < 32) {
-                seq = seq << 2;
-                latest_n_base++;
+            if (n_indel == 1 && n_snv != 0)
+            {
                 continue;
             }
 
-            // search the sequence
-            int k = 0;
-            int end = seed.size() - 1;
+            if (freq >= 1e-9)
+            {
+                // construct the seed (indels are single)
 
-            while (end != k) {
-                int mid = (end - k) / 2 + k;
-                size_t mid_seed = seed.get(mid).seed;
+                size_t bases_pattern_alt = bases_pattern;
 
-                if (seq > mid_seed) {k = mid+1; end = (end > k)?end:k ;continue;}
-                if (seq < mid_seed) {end = mid; ;continue;}
-
-                k = mid;
-                break;
-            }       
-
-            // Found
-            if (seed.get(k).seed == seq) {
-                for (int m = 0 ; m < seed.get(k).calls.size() ; m++) {
-                    int cid = seed.get(k).calls.get(m).cid;
-                    std::cout << "SEED C: " << i << " POS: " << j << "    " << k << "  CALL ID: " << cid  << " " << string_from_32bases_pattern(seq) << std::endl;
-                    un_seed.get(cid).add();
-                    int last = un_seed.get(cid).size()-1;
-                    un_seed.get(cid).get<0>(last) = i;
-                    un_seed.get(cid).get<1>(last) = j-31;
-                    un_seed.get(cid).get<2>(last) = k;
+                for (int j = 0; j < n_bits; j++)
+                {
+                    if ((i >> j) & 0x1)
+                    {
+                        bases_pattern_alt = create_seed_variation_from_variant(chrom,
+                                                                               variants.get(j).pos,
+                                                                               start,
+                                                                               bases_pattern_alt,
+                                                                               variants.get(j).ref.c_str(),
+                                                                               variants.get(j).alt.c_str(),
+                                                                               chr_sequences);
+                    }
                 }
-            }
 
-            seq = seq << 2;
-            latest_n_base++;            
+                openfpm::vector<CNV_event_link> &calls = map[bases_pattern_alt];
+
+                struct CNV_event_link cel;
+                cel.call_id = call_id;
+                cel.padding_left = padding_left;
+                cel.padding_right = padding_right;
+                cel.path = 0x0;
+                cel.pos_seed = start;
+                calls.add(cel);
+            }
         }
+
+        return bases_pattern;
     }
-}
 
-void create_event_cigar(openfpm::vector<uint32_t> & cigar, 
-                        int i_shift, 
-                        int j_shift, 
-                        int pos_event, 
-                        int end, 
-                        call_vcf & call) {
-    cigar.resize(3);
-
-    cigar.get(0) = (call.start + i_shift - pos_event) << BAM_CIGAR_SHIFT | BAM_CMATCH;
-    cigar.get(1) = (call.stop+j_shift-call.start-i_shift) << BAM_CIGAR_SHIFT | BAM_CDEL;
-    cigar.get(2) = end << BAM_CIGAR_SHIFT | BAM_CMATCH;
-}
+    void add_32bases_pattern_with_variability_range_shift(int chrom,
+                                                          int start,
+                                                          int stop,
+                                                          int shift,
+                                                          openfpm::vector<openfpm::vector<char>> &chr_sequences,
+                                                          tsl::hopscotch_map<size_t, openfpm::vector<CNV_event_link>> &map,
+                                                          const char *database,
+                                                          int call_id,
+                                                          int padding_left,
+                                                          int padding_right)
+    {
 
-void create_ref_cigar(openfpm::vector<uint32_t> & cigar,  
-                        int len) {
-    cigar.clear();
-    cigar.resize(1);
+        for (int i = start; i <= stop; i += shift)
+        {
+            add_32bases_pattern_with_variability(chrom, i, chr_sequences, map, database, call_id, padding_left + (i - start), padding_right);
+        }
+    }
 
-    cigar.get(0) = len << BAM_CIGAR_SHIFT | BAM_CMATCH;
-}
+    size_t add_32bases_pattern_with_gap(int chrom,
+                                        int start,
+                                        openfpm::vector<openfpm::vector<char>> &chr_sequences,
+                                        tsl::hopscotch_map<size_t, openfpm::vector<CNV_event_link>> &map,
+                                        int start_gap,
+                                        int end_gap,
+                                        int call_id,
+                                        int padding_left,
+                                        int padding_right)
+    {
 
-void adjust_pos_by_event(int & pos, int & pos_event, call_vcf & call, int i ,int j) {
-    if (pos < call.stop+j &&
-        pos > call.start+i ) {
-            pos_event = call.start+i -(call.stop+j - pos);
-    }
-    else {
-        pos_event = pos;
-    }
-}
+        size_t bases_pattern;
+        int ret = get_32bases_pattern_with_gap(chrom, start, chr_sequences, start_gap, end_gap, bases_pattern);
+        if (ret != 0)
+            return -1;
 
-Eigen::ArrayXd Evidence_matrix_log(openfpm::vector<openfpm::vector<char>> & reference, 
-                                const Pair_read_type & seq,
-                                openfpm::vector<aggregate<short int, int, int>> & un_seed,
-                                call_vcf & call,
-                                int padding, 
-                                short int chr, 
-                                int pos,
-                                int distance_from_seed,
-                                openfpm::vector<int> & chr_ins,
-                                Eigen::ArrayXd & best_insert,
-                                openfpm::vector<double> & bp_insert_prob) {
-    Eigen::ArrayXd events;
-    events.resize((2*padding+1)*(2*padding+1) + un_seed.size());
-    best_insert.resize(events.size());
-
-    // Event 1 reference
-
-    char seq1[16384];
-    char seq2[16384]; // foward read
-    char seq3[16384]; // reverse read
-
-    for (int i = 0 ; i < seq.size() ; i++) {
-        seq2[i] = seq.get<0>(i);
-        seq3[i] = seq.get<1>(i);
-    }
-    seq2[seq.size()] = 0;
-    seq3[seq.size()] = 0;
+        openfpm::vector<CNV_event_link> &calls = map[bases_pattern];
 
-    //get_sequence(reference,chr,pos,pos+seq.size(),-1,-1,seq1);
-    //events(0) = calculate_event_probability(seq2,seq1,seq3,-1,chr,3e-3,chr_ins);
+        struct CNV_event_link cel;
+        cel.call_id = call_id;
+        cel.padding_left = padding_left;
+        cel.padding_right = padding_right;
+        cel.path = 0x0;
+        cel.pos_seed = start;
+        calls.add(cel);
 
-    std::cout << "Read name: ";
-    for (int i = 0; i < seq.size() && seq.get<2>(i) != 0 ; i++) {
-        std::cout << seq.get<2>(i);
+        return bases_pattern;
     }
 
-    //std::cout << std::endl;
-
-    //std::cout << "Distance from seed: " << distance_from_seed << std::endl;
+    void get_sequence(openfpm::vector<openfpm::vector<char>> &reference, short int chr, int start, int stop, int p2, int p3, char *seq)
+    {
+        if (p2 == -1)
+        {
+            for (int i = start; i < stop; i++)
+            {
+                seq[i - start] = get_base_from_reference(reference, chr, i);
+            }
+            seq[stop - start] = 0;
+        }
+        else
+        {
+            for (int i = start; i < p2; i++)
+            {
+                seq[i - start] = get_base_from_reference(reference, chr, i);
+            }
 
-    // Event 2 break
+            for (int i = p3; i < stop; i++)
+            {
+                seq[i - p3 + (p2 - start)] = get_base_from_reference(reference, chr, i);
+            }
+            seq[stop - p3 + p2 - start] = 0;
+        }
+    }
 
-    for (int i = -padding ; i <= padding ; i++) {
-        for (int j = -padding ; j <= padding ; j++) {
-            int id = (i+padding)*(2*padding+1) + (j+padding);
+    /*double calculate_event_probability(bam1_t * aln,
+                                        bam_hdr_t * bamHdr,
+                                        openfpm::vector<openfpm::vector<char>> & reference,
+                                        double reading_error,
+                                        int expected_insert_size,
+                                        openfpm::vector<int> & chr_ins) {
 
-            int pos_event;
+        int n_cigar = aln->core.n_cigar; // number of cigar operations
+        uint32_t * cigar = (uint32_t *)(aln->data + aln->core.l_qname);
+        int32_t pos = aln->core.pos +1;
+        uint8_t *q = bam_get_seq(aln);
 
-            adjust_pos_by_event(pos,pos_event,call,i,j);
+        char *chr = bamHdr->target_name[aln->core.tid];
 
-            ProbsRead probs;
-            int best_insert_;
+        short int chr_int = chr_to_chr_int(chr);
+        if (chr_int == -1)  {return 0.0;}
 
-            // it overlaps
-            int overlap_1 = std::max(pos,call.start+i);
-            int overlap_2 = std::min(pos+(int)seq.size(),call.stop+j);
-            if (overlap_2-overlap_1 > 0) {
-                get_sequence(reference,chr,pos_event,pos_event+seq.size()+(call.stop+j-call.start-i),call.start+i,call.stop+j,seq1);
-                calculate_event_probability(seq2,seq1,seq3,call.stop-call.start,chr,pos,3e-3,chr_ins,reference,best_insert_,bp_insert_prob,probs);
-                events(id) = probs.log_align_probability + probs.log_pair_probability + probs.log_insert_probability;
-                best_insert(id) = best_insert_;
+        double aligment_probability = 1.0;
+        int rpos = 0;
+        for (int k = 0 ; k < n_cigar ;  k++) {
+            int op = bam_cigar_opchr(bam_cigar_op(cigar[k]));
+            int len = bam_cigar_oplen(cigar[k]);
+            if (op == 'M') {
+                for (int j = 0 ; j < len ; j++, rpos++) {
+                    char base = seq_nt16_str[bam_seqi(q,rpos)];
+                    aligment_probability*=(get_base_from_reference(reference,chr_int,pos+j) == base)?(1.0-reading_error):reading_error;
+                }
             } else {
-                events(id) = -5000.0;
-                best_insert(id) = -1;
+                for (int j = 0 ; j < len ; j++, rpos++) {
+                    aligment_probability *= reading_error;
+                }
+                pos += len;
             }
-            
-
-            // Print
+        }
 
-            if (events(id) >  -1.0) {
-                std::cout << "--------------- " << i << "," << j << " ---------------------------------  event: " << id << std::endl;
-                std::cout << "EVENT ID: " << id << std::endl;
+        return aligment_probability;
+    }*/
 
-                int len = strlen(seq2);
-                for (int j = 0 ; j < len ; j++) {
-                    if (j == distance_from_seed) {
-                        std::cout << "*" << seq2[j];
-                    } else {
-                        std::cout << seq2[j];
-                    }
-                }
-                std::cout << std::endl;
+    double calculate_event_probability_between_to_sequences(char *seq1,
+                                                            char *seq2,
+                                                            double reading_error)
+    {
+        double align_probability = 0.0;
+        int len = strlen(seq1);
+        int len2 = strlen(seq2);
 
-                len - strlen(seq1);
-                for (int j = 0 ; j < len ; j++) {
-                    if (j == distance_from_seed) {
-                        std::cout << "*" << seq1[j];
-                    } else {
-                        std::cout << seq1[j];
-                    }
-                }
-                std::cout << std::endl;
+        len = (len2 < len) ? len2 : len;
 
-                std::cout << " Probability: " << events(id) << "   align: " << probs.log_align_probability << " pair align: " << probs.log_pair_probability << " insert: " << probs.log_insert_probability << std::endl;
-            }
-            // Create a file
-            
+        for (size_t j = 0; j < len; j++)
+        {
+            align_probability += (seq1[j] == seq2[j]) ? (log(1.0 - reading_error)) : log(reading_error);
         }
+
+        return align_probability;
     }
 
-    // Event 3 unaligned
+    double insert_probability(int ins, openfpm::vector<double> &bp_insert_prob)
+    {
+        if (abs(ins) < bp_insert_prob.size())
+        {
+            return bp_insert_prob.get(abs(ins));
+        }
+        return 1.7e-8;
+    }
 
-    // for all unaligned points (max 100)
-    for (int i = 0 ; i < un_seed.size() ; i++) {
-        //get_sequence(reference,un_seed.get<0>(i),un_seed.get<1>(i),un_seed.get<1>(i)+32,-1,-1,seq1);
-        get_sequence(reference,un_seed.get<0>(i),un_seed.get<1>(i)-distance_from_seed,un_seed.get<1>(i)-distance_from_seed+seq.size(),-1,-1,seq1);
-        int id = (2*padding+1)*(2*padding+1) + i;
+    struct ProbsRead
+    {
+        double log_align_probability;
+        double log_pair_probability;
+        double log_insert_probability;
+    };
+
+    void calculate_event_probability(char *seq1,
+                                     char *seq2,
+                                     char *seq3,
+                                     int expected_insert_size,
+                                     short int chr_int,
+                                     int pos,
+                                     double reading_error,
+                                     openfpm::vector<int> &chr_ins,
+                                     openfpm::vector<openfpm::vector<char>> &reference,
+                                     int &best_insert,
+                                     openfpm::vector<double> &bp_insert_prob,
+                                     ProbsRead &probs)
+    {
 
-        ProbsRead probs;
-        int best_insert_;
-        calculate_event_probability(seq2,seq1,seq3,-1,chr,un_seed.get<1>(i)-distance_from_seed+1,3e-3,chr_ins,reference,best_insert_,bp_insert_prob,probs);
-        events(id) = probs.log_align_probability + probs.log_pair_probability + probs.log_insert_probability;
-        best_insert(id) = best_insert_;
+        char seq4[16384];
+        double align_probability = calculate_event_probability_between_to_sequences(seq1, seq2, reading_error);
 
-        if (events(id) >  -1.0) {
-            std::cout << "------------------- un_seed: " << i << " ----------------------------- event: " << id << std::endl;
-            std::cout <<  id << "  SEED position: " << un_seed.get<1>(i) << "  SEED ID: " << un_seed.get<2>(i) << std::endl;
+        // get the sequence
+        int len = strlen(seq1);
 
-            // Print
+        int max_i;
+        double max = -1.0e300;
+        for (int i = -4 * chr_ins.get(chr_int); i < 4 * chr_ins.get(chr_int); i++)
+        {
 
-            std::cout << "UNALIGNED SEED: " << std::string(seq1) << std::endl;
+            get_sequence(reference, chr_int, pos + i, pos + i + len, -1, -1, seq4);
 
-            for (int j = 0 ; j < seq.size() ; j++) {
-                if (j == distance_from_seed) {
-                    std::cout << "*" << seq2[j];
-                } else {
-                    std::cout << seq2[j];
+            if (expected_insert_size != -1)
+            {
+                // poisson_distribution(expected_insert_size,abs(i))
+                double event_p = log(insert_probability(abs(i), bp_insert_prob)) + calculate_event_probability_between_to_sequences(seq4, seq3, reading_error);
+                if (event_p > max)
+                {
+                    max = event_p;
+                    max_i = i;
                 }
             }
-            std::cout << std::endl;
-
-            for (int j = 0 ; j < seq.size() ; j++) {
-                if (j == distance_from_seed) {
-                    std::cout << "*" << seq1[j];
-                } else {
-                    std::cout << seq1[j];
+            else
+            {
+                // poisson_distribution(chr_ins.get(chr_int),abs(i))
+                double event_p = log(insert_probability(abs(i), bp_insert_prob)) + calculate_event_probability_between_to_sequences(seq4, seq3, reading_error);
+                if (event_p > max)
+                {
+                    max = event_p;
+                    max_i = i;
                 }
             }
-            std::cout << std::endl;
-
-            std::cout << " Probability: " << events(id) << "   align: " << probs.log_align_probability << " pair align: " << probs.log_pair_probability << " insert: " << probs.log_insert_probability << std::endl;
         }
-    }
-
-    return events;
-}
 
-// Function to generate a random permutation of numbers from 1 to N
-void randomPermutation(int N, openfpm::vector<int> & permutation) {
-    permutation.resize(N);
+        best_insert = max_i;
 
-    // Initialize the permutation with numbers from 1 to N
-    for (int i = 0; i < N; ++i) {
-        permutation.get(i) = i;
+        probs.log_align_probability = align_probability;
+        probs.log_pair_probability = max;
+        probs.log_insert_probability = log(insert_probability(abs(max_i), bp_insert_prob));
     }
 
-    // Create a random number generator
-    std::random_device rd;
-    std::mt19937 gen(rd());
+    struct seed_pos
+    {
+        short int chr;
+        int pos;
+        int cid;
+    };
 
-    // Perform the Fisher-Yates shuffle
-    for (int i = N - 1; i > 0; --i) {
-        std::uniform_int_distribution<int> distribution(0, i);
-        int j = distribution(gen);
-        std::swap(permutation.get(i), permutation.get(j));
-    }
-}
+    struct seed_id
+    {
+        size_t seed;
+        openfpm::vector<seed_pos> calls;
 
-int ArgMax(const Eigen::Vector3d & v) {
-    int i_max = 0;
-    double v_max = v(0);
-    for (int i = 1 ; i < 3 ; i++) {
-        if (v_max > v(i) ) {
-            v_max = v(i);
-            i_max = i;
+        bool operator<(const seed_id &tmp) const
+        {
+            return seed < tmp.seed;
         }
-    }
-
-    return i_max;
-}
-
+    };
 
+    void get_reference_point(openfpm::vector<seed_id> &seed,
+                             openfpm::vector<openfpm::vector<char>> &reference,
+                             openfpm::vector<openfpm::vector<aggregate<short int, int, int>>> &un_seed)
+    {
+        seed.sort();
 
-void CalculateViterbi(openfpm::vector<openfpm::vector<char>> & reference,
-                      Call_related_relevant_read_type & seqs,
-                      openfpm::vector<aggregate<short int, int, int>> & un_seed,
-                      call_vcf & call,
-                      int padding,
-                      openfpm::vector<int> & chr_ins,
-                      openfpm::vector<double> & bp_insert_prob) {
-    // User viterbi algorithm to get the sequence of events
-
-    // There are 6 events
+        int latest_n_base = 0;
+        size_t seq = 0;
+        for (int i = 0; i < reference.size(); i++)
+        {
+            for (int j = 0; j < 2 * reference.get(i).size(); j++)
+            {
 
-    // 1 reference
-    // 2 Events  <------ This is an array of events of size N
-    // 3 unaligned
+                char base = get_base_from_reference(reference, i, j);
+                if (base == 'N')
+                {
+                    latest_n_base = 0;
+                }
+                seq |= get_bits_from_base_char(base);
+                if (latest_n_base < 32)
+                {
+                    seq = seq << 2;
+                    latest_n_base++;
+                    continue;
+                }
 
-    // The transition matrix is f where f is the frequency of the allele (because we do not do any assumption f = 0.5)
-    //      1            2.1         3
-    // 1)  1/3*(1-f)  1/3N*f ...    1/3
+                // search the sequence
+                int k = 0;
+                int end = seed.size() - 1;
 
-    // 2.1)  1/3  1/3N ... 1/3
-    // 2.2)  1/3  1/3N ... 1/3
+                while (end != k)
+                {
+                    int mid = (end - k) / 2 + k;
+                    size_t mid_seed = seed.get(mid).seed;
+
+                    if (seq > mid_seed)
+                    {
+                        k = mid + 1;
+                        end = (end > k) ? end : k;
+                        continue;
+                    }
+                    if (seq < mid_seed)
+                    {
+                        end = mid;
+                        ;
+                        continue;
+                    }
 
-    // 3)  1/3  1/3N ...    1/3
+                    k = mid;
+                    break;
+                }
 
-    // The evidence Matrix is the probability of the read to support that evidence
+                // Found
+                if (seed.get(k).seed == seq)
+                {
+                    for (int m = 0; m < seed.get(k).calls.size(); m++)
+                    {
+                        int cid = seed.get(k).calls.get(m).cid;
+                        std::cout << "SEED C: " << i << " POS: " << j << "    " << k << "  CALL ID: " << cid << " " << string_from_32bases_pattern(seq) << std::endl;
+                        un_seed.get(cid).add();
+                        int last = un_seed.get(cid).size() - 1;
+                        un_seed.get(cid).get<0>(last) = i;
+                        un_seed.get(cid).get<1>(last) = j - 31;
+                        un_seed.get(cid).get<2>(last) = k;
+                    }
+                }
 
-    // We apply Viterbi algorithm to the sequence of randomly picked reads as described here:
-    // https://ocw.mit.edu/courses/16-410-principles-of-autonomy-and-decision-making-fall-2010/55e488318190f148c4ed211e2c96bada_MIT16_410F10_lec20.pdf
-    // Once we have the sequence
-    // We sum all the probabilities of the trajectory generated by the Viterbi algorithm divided by the the number the events
+                seq = seq << 2;
+                latest_n_base++;
+            }
+        }
+    }
 
-    // An event probability higher than 0.5 is considered an event
+    void create_event_cigar(openfpm::vector<uint32_t> &cigar,
+                            int i_shift,
+                            int j_shift,
+                            int pos_event,
+                            int end,
+                            call_vcf &call)
+    {
+        cigar.resize(3);
 
-    int N = (2*padding+1)*(2*padding+1)+un_seed.size(); 
+        cigar.get(0) = (call.start + i_shift - pos_event) << BAM_CIGAR_SHIFT | BAM_CMATCH;
+        cigar.get(1) = (call.stop + j_shift - call.start - i_shift) << BAM_CIGAR_SHIFT | BAM_CDEL;
+        cigar.get(2) = end << BAM_CIGAR_SHIFT | BAM_CMATCH;
+    }
 
-    Eigen::MatrixXd transition_log(N,N);
-    Eigen::VectorXd Initial_log(N); // <------ Initial state
+    void create_ref_cigar(openfpm::vector<uint32_t> &cigar,
+                          int len)
+    {
+        cigar.clear();
+        cigar.resize(1);
 
-    // Initial state
-    for (int i = 0 ; i < (2*padding+1)*(2*padding+1) ; i++) {
-        Initial_log(i) = std::log(1.0f/N);
-    }
-    for (int i = (2*padding+1)*(2*padding+1) ; i < (2*padding+1)*(2*padding+1)+un_seed.size() ; i++) {
-        Initial_log(i) = std::log(1.0f/N);
+        cigar.get(0) = len << BAM_CIGAR_SHIFT | BAM_CMATCH;
     }
 
-    // Fill transition matrix with uniform distribution
-    for (int i = 0 ; i < N ; i++) {
-        for (int j = 0 ; j < N ; j++) {
-            transition_log(i,j) = std::log(1.0 / ((2*padding+1)*(2*padding+1)+un_seed.size()));
+    void adjust_pos_by_event(int &pos, int &pos_event, call_vcf &call, int i, int j)
+    {
+        if (pos < call.stop + j &&
+            pos > call.start + i)
+        {
+            pos_event = call.start + i - (call.stop + j - pos);
+        }
+        else
+        {
+            pos_event = pos;
         }
     }
 
-    openfpm::vector<int> permutation;
+    Eigen::ArrayXd Evidence_matrix_log(openfpm::vector<openfpm::vector<char>> &reference,
+                                       const Pair_read_type &seq,
+                                       openfpm::vector<aggregate<short int, int, int>> &un_seed,
+                                       call_vcf &call,
+                                       int padding,
+                                       short int chr,
+                                       int pos,
+                                       int distance_from_seed,
+                                       openfpm::vector<int> &chr_ins,
+                                       Eigen::ArrayXd &best_insert,
+                                       openfpm::vector<double> &bp_insert_prob)
+    {
+        Eigen::ArrayXd events;
+        events.resize((2 * padding + 1) * (2 * padding + 1) + un_seed.size());
+        best_insert.resize(events.size());
 
-    openfpm::vector<double> events;
-    events.resize((2*padding+1)*(2*padding+1)+un_seed.size());
+        // Event 1 reference
 
-    // create a random permutation
-    randomPermutation(seqs.size(),permutation);
+        char seq1[16384];
+        char seq2[16384]; // foward read
+        char seq3[16384]; // reverse read
 
-    openfpm::vector<Eigen::ArrayXd> delta_log;
-    openfpm::vector<Eigen::ArrayXd> insert;
-    openfpm::vector<Eigen::ArrayXd> Pre;
-    delta_log.resize(seqs.size());
-    insert.resize(seqs.size());
-    Pre.resize(seqs.size());
+        for (int i = 0; i < seq.size(); i++)
+        {
+            seq2[i] = seq.get<0>(i);
+            seq3[i] = seq.get<1>(i);
+        }
+        seq2[seq.size()] = 0;
+        seq3[seq.size()] = 0;
 
-    int s = permutation.get(0)/*673*/;
+        // get_sequence(reference,chr,pos,pos+seq.size(),-1,-1,seq1);
+        // events(0) = calculate_event_probability(seq2,seq1,seq3,-1,chr,3e-3,chr_ins);
 
-    int seed_pos = seqs.get<4>(s);
-    delta_log.get(0).resize(Initial_log.size());
+        std::cout << "Read name: ";
+        for (int i = 0; i < seq.size() && seq.get<2>(i) != 0; i++)
+        {
+            std::cout << seq.get<2>(i);
+        }
 
-    // Carefull the Evidence matrix return the natural logarithm of the probability, initial contain the logarithm of the initial probability Initial_log = log(Initial)
-    // and delta_log contain the logarim of the delta log(delta)
-    // so the formula delta = Initial*Evidence_matrix in logaritm space become
-    // delta_log = log(Initial*Evidemce_matrix)
-    // delta_log = Initial_log + Evidence_matrix_log
-    Eigen::ArrayXd best_insert;
+        // std::cout << std::endl;
 
-    delta_log.get(0) = Initial_log.array() + Evidence_matrix_log(reference,seqs.get<0>(s),un_seed,call,padding,seqs.get<1>(s),seqs.get<2>(s),seed_pos,chr_ins,best_insert,bp_insert_prob);
-    int x;
-    auto mC = delta_log.get(0).maxCoeff(&x);
-    std::cout << "BEST event: " << x << " " << mC << std::endl;
-    Pre.get(0).resize(Initial_log.size());
-    Pre.get(0) = -1;
+        // std::cout << "Distance from seed: " << distance_from_seed << std::endl;
 
-    for (int i = 1 ; i < seqs.size() ; i++) {
-        int s = permutation.get(i);
+        // Event 2 break
 
-        seed_pos = seqs.get<4>(s);
-        Eigen::VectorXd next_transition(Initial_log.size());
-        std::cout << "Initial Array: " << Initial_log.array() << std::endl;
-        std::cout << "Event probs: " << delta_log.get(i-1) << std::endl;
+        for (int i = -padding; i <= padding; i++)
+        {
+            for (int j = -padding; j <= padding; j++)
+            {
+                int id = (i + padding) * (2 * padding + 1) + (j + padding);
 
-        // Here we tranform by the transition matrix (we do everything in logaritmic space) 
-        // The formula below is the multiplication of the transition matrix by the previous delta (Viterbi)
-        // avoiding undeflow problems
-        for (int j = 0 ; j < N ; j++) {
+                int pos_event;
 
-            // First accumulation accum = transition(j,0)*delta(0)
-            // in log space
-            // accum_log = transition_log(j,0) + delta_log(0)
-            double accum_log = transition_log(j,0) + delta_log.get(i-1)(0);
+                adjust_pos_by_event(pos, pos_event, call, i, j);
 
-            // we are trying to calculate accum = sum_over_k (transition(j,k)*delta(k))
-            // in logarithmic space.
-            for (int k = 1 ; k < N ; k++) { // Classical Matix vector multiplication loop
-                
-                // accum = accum + transition(j,k)*delta(k)
-                // in log space:
-                // accum_log = log(accum + transition(j,k)*delta(k))
-                // We split in two cases accum > transition(j,k)*delta(k), we also indicate accum -> a, transition(j,k) -> t, delta(k) -> d
-                // accum_log = log(a*(1+ t*d/a))
-                // accum_log = log(a) + log(1+t*d/a)
-                // accum_log = log(a) + log(1+exp(log(t*d/a)))
-                // accum_log = log(a) + log(1+exp(log(t)+log(d)-log(a)))
-                // accum_log = log(a) + log(1+exp(-(log(a)-log(t)*log(d)))
+                ProbsRead probs;
+                int best_insert_;
 
-                // In case t*d > accum we have
-                // accum_log = log(t*d) + log(1+exp(-(log(t)+log(d)-log(a)))
+                // it overlaps
+                int overlap_1 = std::max(pos, call.start + i);
+                int overlap_2 = std::min(pos + (int)seq.size(), call.stop + j);
+                if (overlap_2 - overlap_1 > 0)
+                {
+                    get_sequence(reference, chr, pos_event, pos_event + seq.size() + (call.stop + j - call.start - i), call.start + i, call.stop + j, seq1);
+                    calculate_event_probability(seq2, seq1, seq3, call.stop - call.start, chr, pos, 3e-3, chr_ins, reference, best_insert_, bp_insert_prob, probs);
+                    events(id) = probs.log_align_probability + probs.log_pair_probability + probs.log_insert_probability;
+                    best_insert(id) = best_insert_;
+                }
+                else
+                {
+                    events(id) = -5000.0;
+                    best_insert(id) = -1;
+                }
 
-                // This can be rewritten in a single case as C math functions
+                // Print
 
-                // accum_log = fmax(a,t_log+d_log) + log(1+exp(-fabs(t_log+d_log-a_log))))
-                // or
-                // accum_log = fmax(a,t_log+d_log) + log1p(1+exp(-fabs(t_log+d_log-a_log))))
+                if (events(id) > -1.0)
+                {
+                    std::cout << "--------------- " << i << "," << j << " ---------------------------------  event: " << id << std::endl;
+                    std::cout << "EVENT ID: " << id << std::endl;
+
+                    int len = strlen(seq2);
+                    for (int j = 0; j < len; j++)
+                    {
+                        if (j == distance_from_seed)
+                        {
+                            std::cout << "*" << seq2[j];
+                        }
+                        else
+                        {
+                            std::cout << seq2[j];
+                        }
+                    }
+                    std::cout << std::endl;
+
+                    len - strlen(seq1);
+                    for (int j = 0; j < len; j++)
+                    {
+                        if (j == distance_from_seed)
+                        {
+                            std::cout << "*" << seq1[j];
+                        }
+                        else
+                        {
+                            std::cout << seq1[j];
+                        }
+                    }
+                    std::cout << std::endl;
 
-                accum_log = fmax(accum_log,transition_log(j,k) + delta_log.get(i-1)(k)) + log1p(exp(-fabs(delta_log.get(i-1)(k) + transition_log(j,k) - accum_log)));
+                    std::cout << " Probability: " << events(id) << "   align: " << probs.log_align_probability << " pair align: " << probs.log_pair_probability << " insert: " << probs.log_insert_probability << std::endl;
+                }
+                // Create a file
             }
+        }
 
-            std::cout <<  accum_log << std::endl;
+        // Event 3 unaligned
 
-            next_transition(j) = accum_log; 
-        }
+        // for all unaligned points (max 100)
+        for (int i = 0; i < un_seed.size(); i++)
+        {
+            // get_sequence(reference,un_seed.get<0>(i),un_seed.get<1>(i),un_seed.get<1>(i)+32,-1,-1,seq1);
+            get_sequence(reference, un_seed.get<0>(i), un_seed.get<1>(i) - distance_from_seed, un_seed.get<1>(i) - distance_from_seed + seq.size(), -1, -1, seq1);
+            int id = (2 * padding + 1) * (2 * padding + 1) + i;
 
-        int x;
-        double coeff = next_transition.maxCoeff(&x);
-        best_insert.resize(Initial_log.size());
-        Eigen::ArrayXd eml = Evidence_matrix_log(reference,seqs.get<0>(s),un_seed,call,padding,seqs.get<1>(s),seqs.get<2>(s),seed_pos,chr_ins,best_insert,bp_insert_prob);
-        auto mC = eml.maxCoeff(&x);
-        std::cout << "Best event: " << x << " " << mC << std::endl;
-        std::cout << "Next transition: " << eml << std::endl;
-        delta_log.get(i) = coeff + eml;
+            ProbsRead probs;
+            int best_insert_;
+            calculate_event_probability(seq2, seq1, seq3, -1, chr, un_seed.get<1>(i) - distance_from_seed + 1, 3e-3, chr_ins, reference, best_insert_, bp_insert_prob, probs);
+            events(id) = probs.log_align_probability + probs.log_pair_probability + probs.log_insert_probability;
+            best_insert(id) = best_insert_;
 
-        if (i+1 < seqs.size()) {
-            Pre.get(i+1) = x;
-        }
-    }
+            if (events(id) > -1.0)
+            {
+                std::cout << "------------------- un_seed: " << i << " ----------------------------- event: " << id << std::endl;
+                std::cout << id << "  SEED position: " << un_seed.get<1>(i) << "  SEED ID: " << un_seed.get<2>(i) << std::endl;
 
-    int s_star = ArgMax(delta_log.last());
+                // Print
 
-    // backtrace to find the most probable path
+                std::cout << "UNALIGNED SEED: " << std::string(seq1) << std::endl;
 
-    openfpm::vector<int> event;
-    openfpm::vector<Eigen::Array3d> probs;
+                for (int j = 0; j < seq.size(); j++)
+                {
+                    if (j == distance_from_seed)
+                    {
+                        std::cout << "*" << seq2[j];
+                    }
+                    else
+                    {
+                        std::cout << seq2[j];
+                    }
+                }
+                std::cout << std::endl;
 
-    event.resize(seqs.size());
-    probs.resize(seqs.size());
+                for (int j = 0; j < seq.size(); j++)
+                {
+                    if (j == distance_from_seed)
+                    {
+                        std::cout << "*" << seq1[j];
+                    }
+                    else
+                    {
+                        std::cout << seq1[j];
+                    }
+                }
+                std::cout << std::endl;
 
-    int q_k_p1 = s_star;
+                std::cout << " Probability: " << events(id) << "   align: " << probs.log_align_probability << " pair align: " << probs.log_pair_probability << " insert: " << probs.log_insert_probability << std::endl;
+            }
+        }
 
-    for (int i = seqs.size()-1 ; i > 0 ; i--) {
-        event.get(i) = Pre.get(i)(q_k_p1);
-        q_k_p1 = event.get(i);
+        return events;
     }
-}
 
-void convert_seed_map_to_array(openfpm::vector<seed_id> & seed, 
-                                tsl::hopscotch_map<size_t, openfpm::vector<CNV_event_link>> & map, 
-                                openfpm::vector<call_vcf> & calls) {
-    for (auto i = map.begin() ; i != map.end() ; i++) {
-        seed.add();
-        int last = seed.size() - 1;
-        seed.get(last).seed = i->first;
-        for (int j = 0 ; j < i->second.size() ; j++) {
-            int cid = i->second.get(j).call_id;
+    Eigen::ArrayXd Evidence_matrix_log_bam_out(openfpm::vector<openfpm::vector<char>> &reference,
+                                       const Pair_read_type &seq,
+                                       openfpm::vector<aggregate<short int, int, int>> &un_seed,
+                                       call_vcf &call,
+                                       int padding,
+                                       short int chr,
+                                       int pos,
+                                       int distance_from_seed,
+                                       openfpm::vector<int> &chr_ins,
+                                       Eigen::ArrayXd &best_insert,
+                                       openfpm::vector<double> &bp_insert_prob,
+                                       bam1_t *aln,
+                                       bam_hdr_t *bamHdr,
+                                       samFile * fp_out_best)
+    {
+        int kf = 0;
+        int kr = 0;
+        int kn = 0;
 
-            struct seed_pos tmp;
-            tmp.cid = cid;
-            tmp.chr = calls.get(i->second.get(j).call_id).chromosome;;
-            tmp.pos = i->second.get(j).pos_seed;;
+        char name[256];
+        memset(name, 0, 256);
 
-            seed.get(last).calls.add(tmp);
+        for (; kn < seq.size() && seq.get<2>(kn) != 0; kn++)
+        {
+            name[kn] = seq.get<2>(kn);
         }
-    }
-}
-
-void CNV_event_test(openfpm::vector<call_vcf> & calls, 
-                    openfpm::vector<openfpm::vector<char>> & reference, 
-                    openfpm::vector<std::string> & files_bams,
-                    int padding,
-                    openfpm::vector<aggregate<openfpm::vector<int>>> & chr_ins) {
-    char seq1[16384];
-    char seq2[16384];
-    char seq3[16384];
-
-    openfpm::vector<double> bp_insert_prob;
-    bp_insert_prob.load("insert_probability_distribution");
-    tsl::hopscotch_map<size_t, openfpm::vector<CNV_event_link>> map;
 
-    map.reserve(calls.size()*2);
+        Eigen::ArrayXd eml3 = Evidence_matrix_log(reference,seq,un_seed,call,padding,chr,pos,distance_from_seed,chr_ins,best_insert,bp_insert_prob);
 
-    for (int i = 0 ; i < calls.size() ; i ++) {
+        // Here we write the read in the bam
+        double best_event = -1000.0;
+        double best_ref = -1000.0;
+        double best_ref_2 = -1000.0;
+        int best_ref_seed_pos = -1;
+        int best_ei = -1;
 
-        if (i % 1000 == 0) {
-            std::cout << "Creating Map: " << i << "/" << calls.size() << std::endl;
+        for (int i = 0; i < (2 * padding + 1) * (2 * padding + 1); i++)
+        {
+            if (eml3(i) > best_event)
+            {
+                best_event = eml3(i);
+                best_ei = i;
+            }
         }
 
-        int offset = std::min(calls.get(i).start - 32 , 0);
+        int best_ri = -1;
 
-        // Store the patterns related to the reference
-        for (int j = -padding ; j < padding ; j++ ) {
-            if (calls.get(i).start-32+j-offset < 0) {continue;}
+        for (int i = (2 * padding + 1) * (2 * padding + 1); i < eml3.size(); i++)
+        {
+            if (eml3(i) > best_ref)
+            {
+                best_ref_2 = best_ref;
+                best_ref = eml3(i);
+                best_ref_seed_pos = un_seed.get<1>(i - (2 * padding + 1) * (2 * padding + 1));
+                best_ri = i;
+            }
+        }
 
-            // DEBUG
-            char seq[64];
-            get_sequence(reference,calls.get(i).chromosome,calls.get(i).start-32+j-offset,calls.get(i).start+j-offset,-1,-1,seq);
-            seq[33] = 0;
-            std::cout << "ADDING sequence at " << calls.get(i).chromosome << ":" << calls.get(i).start-32+j-offset << "  SEQUENCE: " << seq << std::endl;
+        char seq1[MAX_READ_LENGTH];
+        char seq2[MAX_READ_LENGTH];
+        memset(seq1, 0, MAX_READ_LENGTH);
 
+        for (; kf < seq.size() && seq.get<0>(kf) != 0; kf++)
+        {
+            seq1[kf] = seq.get<0>(kf);
+        }
 
-            add_32bases_pattern(calls.get(i).chromosome,calls.get(i).start-32+j-offset,
-                                reference,map,i,-32+j-offset,-1);
+        for (; kr < seq.size() && seq.get<1>(kr) != 0; kr++)
+        {
+            seq2[kr] = seq.get<1>(kr);
         }
 
-        // Store the patterns related to the stop
-        for (int j = -padding ; j < padding ; j++ ) {
-            if (calls.get(i).stop+j+32 >= reference.get(calls.get(i).chromosome).size()) {continue;}
+        char qual[MAX_READ_LENGTH];
+        memset(qual, 'F', MAX_READ_LENGTH);
 
-            // DEBUG
-            char seq[64];
-            get_sequence(reference,calls.get(i).chromosome,calls.get(i).stop+j,calls.get(i).stop+j+32,-1,-1,seq);
-            seq[33] = 0;
-            std::cout << "ADDING sequence at " << calls.get(i).chromosome << ":" << calls.get(i).stop+j << "  SEQUENCE: " << seq << std::endl;
+        int pos_event;
+        int i_shift = best_ei / (2 * padding + 1) - padding;
+        int j_shift = best_ei % (2 * padding + 1) - padding;
 
-            add_32bases_pattern(calls.get(i).chromosome,calls.get(i).stop+j,
-                                    reference,map,i,j,-1);
-        }
-    }
+        CNVcaller::adjust_pos_by_event(pos, pos_event, call, i_shift, j_shift);
 
-    // Collect evidences for the SV calls
-    // Samples // calls // sequences // bases
+        int overlap_1 = std::max(pos, call.start + i_shift);
+        int overlap_2 = std::min(pos + (int)seq.size(), call.stop + j_shift);
+        if (overlap_2 - overlap_1 > 0)
+        {
 
-    All_samples_call_related_relevant_read_type seqs;
+            int end = kf - (call.start + i_shift - pos_event);
 
-/*    seqs.resize(files_bams.size());
+            // create event CIGAR
 
-    for (int i = 0 ; i < files_bams.size() ; i++) {
-        collect_reads_for_call_evidence(files_bams.get(i),map,calls,seqs.get<0>(i),reference);
-    }
+            openfpm::vector<uint32_t> cigar;
 
-    std::cout << "Saving sequences" << std::endl;
-    seqs.save("seqs_call_vector");
-    std::cout << "Saved sequences" << std::endl;
+            if (best_event > best_ref)
+            {
+                int r;
+                int diff = abs((best_event - best_ref) * 10.0);
 
-    return;*/
+                if (diff > 255)
+                {diff = 255;}
 
-    seqs.load("seqs_call_vector");
+                CNVcaller::create_event_cigar(cigar, i_shift, j_shift, pos_event, end, call);
 
-    openfpm::vector<seed_id> seed;
-    openfpm::vector<openfpm::vector<aggregate<short int, int, int>>> un_seed;
+                int insert = best_insert(best_ei);
 
-    convert_seed_map_to_array(seed,map,calls);
+                // write forward read
+                bam_set1(aln, kn, name,
+                            BAM_FPAIRED | BAM_FPROPER_PAIR | BAM_FMREVERSE | BAM_FREAD2, chr, pos_event, diff,
+                            cigar.size(), &cigar.get(0), chr, pos + insert, insert,
+                            kf, seq1, qual, 64);
 
-    un_seed.resize(calls.size());
-    get_reference_point(seed,reference,un_seed);
+                r = sam_write1(fp_out_best, bamHdr, aln);
 
-    for (int i = 0 ; i < seed.size() ; i++) {
-        for (int j = 0 ; j < seed.get(i).calls.size() ; j++) {
-            char seq[64];
-            get_sequence(reference,seed.get(i).calls.get(j).chr,seed.get(i).calls.get(j).pos,seed.get(i).calls.get(j).pos+32,-1,-1,seq);
-            seq[33] = 0;
+                // write reverse read
 
-            std::cout << "SEED POS: " << seed.get(i).calls.get(j).chr << ":" << seed.get(i).calls.get(j).pos <<  "  SEQUENCE: " << seq << "   ID " << seed.get(i).seed << std::endl;
-        }
-    }
+                CNVcaller::create_ref_cigar(cigar, kr);
 
-    // Check reference points
-    for (int cid = 0 ; cid < un_seed.size() ; cid++) {
-        std::cout << "CALL ID: " << cid << std::endl;
-        for (int j = 0 ; j < un_seed.get(cid).size() ; j++ ) {
-            char seq[64];
-            get_sequence(reference,un_seed.get(cid).get<0>(j),un_seed.get(cid).get<1>(j),un_seed.get(cid).get<1>(j)+32,-1,-1,seq);
-            seq[33] = 0;
-            std::cout << "    " << un_seed.get(cid).get<0>(j) << ":" << un_seed.get(cid).get<1>(j) << " SEQUENCE: " << seq << "   ID " << seed.get(un_seed.get(cid).get<2>(j)).seed << " K:" << un_seed.get(cid).get<2>(j) << std::endl;
-        }
-    }
+                bam_set1(aln, kn, name,
+                            BAM_FPAIRED | BAM_FPROPER_PAIR | BAM_FREVERSE | BAM_FREAD1, chr, pos + insert, diff,
+                            cigar.size(), &cigar.get(0), chr, pos, insert,
+                            kr, seq2, qual, 64);
 
-    double reading_error = 1e-2;
+                r = sam_write1(fp_out_best, bamHdr, aln);
+            }
+            else
+            {
+                int r;
+                int diff = abs((best_ref - best_ref_2) * 10.0);
 
-    for (int i = 0 ; i < seqs.size(); i++) {
-        for (int j = 0 ; j < seqs.get<0>(i).size() ; j++) {
-            CalculateViterbi(reference,seqs.get<0>(i).get<0>(j),un_seed.get(j),calls.get(i),padding,chr_ins.get<0>(i),bp_insert_prob);
-        }
-    }
-}
+                if (diff > 255)
+                {diff = 255;}
 
-void read_bed_file(std::string bed_f, openfpm::vector<aggregate<short int,int,int>> & intervals,int pad) {
-    std::ifstream bedFile(bed_f.c_str());
+                CNVcaller::create_ref_cigar(cigar, kf);
 
-    if (!bedFile.is_open()) {
-        std::cerr << "Error: Unable to open the BED file." << std::endl;
-        return;
-    }
+                int insert = best_insert(best_ri);
+                int pos = un_seed.get<1>(best_ri - (2 * padding + 1) * (2 * padding + 1)) - distance_from_seed;
 
-    std::string line;
+                // write forward read
+                bam_set1(aln, kn, name,
+                            BAM_FPAIRED | BAM_FPROPER_PAIR | BAM_FMREVERSE | BAM_FREAD2, chr, pos, diff,
+                            cigar.size(), &cigar.get(0), chr, pos + insert, insert,
+                            kf, seq1, qual, 64);
 
-    char str[256];
+                r = sam_write1(fp_out_best, bamHdr, aln);
 
-    while (std::getline(bedFile, line)) {
-        std::istringstream iss(line);
+                // write reverse read
 
-        iss >> str;
-        int chr_int = chr_to_chr_int(str);
-        if (chr_int == -1)  {continue;}
+                CNVcaller::create_ref_cigar(cigar, kr);
 
-        intervals.add();
-        intervals.last().get<0>() = chr_int;
-        iss >> intervals.last().get<1>();
-        iss >> intervals.last().get<2>();
+                bam_set1(aln, kn, name,
+                            BAM_FPAIRED | BAM_FPROPER_PAIR | BAM_FREVERSE | BAM_FREAD1, chr, pos + insert + 1, diff,
+                            cigar.size(), &cigar.get(0), chr, pos, insert,
+                            kr, seq2, qual, 64);
 
-        intervals.last().get<2>() += 1;
-
-        if (intervals.last().get<2>() <= intervals.last().get<1>()) {
-            std::cout << "Bed file are interpreted as start (included) and stop (included), based on this standard the region " << chr_int + 1 << " " <<  intervals.last().get<1>() << " " << intervals.last().get<2>() << std::endl;
-            std::cout << "Note aside internally we use the more conventional (included) (excluded) it look like that famous enrichment kits has the above fetish ... or they do not know what they are doing" << std::endl;
+                r = sam_write1(fp_out_best, bamHdr, aln);
+            }
         }
     }
 
-    bedFile.close();
-}
-
-
-template<typename T> T penalization_fishing(T & a, T left, T right) {
-    T min_distance = std::min(fabs(a-left)*1000,fabs(a-right)*1000);
+    // Function to generate a random permutation of numbers from 1 to N
+    void randomPermutation(int N, openfpm::vector<int> &permutation)
+    {
+        permutation.resize(N);
 
-    return min_distance;
-}
+        // Initialize the permutation with numbers from 1 to N
+        for (int i = 0; i < N; ++i)
+        {
+            permutation.get(i) = i;
+        }
 
+        // Create a random number generator
+        std::random_device rd;
+        std::mt19937 gen(rd());
 
-std::string GRCh37_length[] = {"249250621",
-                "243199373",
-                "198022430",
-                "191154276",
-                "180915260",
-                "171115067",
-                "159138663",
-                "146364022",
-                "141213431",
-                "135534747",
-                "135006516",
-                "133851895",
-                "115169878",
-                "107349540",
-                "102531392",
-                "90354753",
-                "81195210",
-                "78077248",
-                "59128983",
-                "63025520",
-                "48129895",
-                "51304566",
-                "155270560",
-                "59373566",
-                "16569"};
-
-std::string GRCh37_contig[] = {"1",
-                "2",
-                "3",
-                "4",
-                "5",
-                "6",
-                "7",
-                "8",
-                "9",
-                "10",
-                "11",
-                "12",
-                "13",
-                "14",
-                "15",
-                "16",
-                "17",
-                "18",
-                "19",
-                "20",
-                "21",
-                "22",
-                "X",
-                "Y",
-                "MT"};
-
-const int GRCh37_n_contig = 24;
-
-int set_header_assembly(bcf_hdr_t* header, htsFile* vcfFile, const std::string & assembly) {
-    if (assembly == "GRCh37") {
-        for (int i = 0 ; i < GRCh37_n_contig ; i++) {
-            // Create the header
-            bcf_hrec_t *hrec = (bcf_hrec_t *)calloc(1, sizeof(bcf_hrec_t));
-            hrec->key = strdup("contig");
-            if (bcf_hrec_add_key(hrec, "ID", strlen("ID")) < 0) {
-                std::cerr << "Error: Cannot create VCF header contigs." << std::endl;
-                hts_close(vcfFile);
-                return 1;
-            }
+        // Perform the Fisher-Yates shuffle
+        for (int i = N - 1; i > 0; --i)
+        {
+            std::uniform_int_distribution<int> distribution(0, i);
+            int j = distribution(gen);
+            std::swap(permutation.get(i), permutation.get(j));
+        }
+    }
 
-            if (bcf_hrec_set_val(hrec, hrec->nkeys-1, GRCh37_contig[i].c_str(), strlen(GRCh37_contig[i].c_str()), 0) < 0) {
-                std::cerr << "Error: Cannot create VCF header contigs." << std::endl;
-                hts_close(vcfFile);
-                return 1;
+    int ArgMax(const Eigen::Vector3d &v)
+    {
+        int i_max = 0;
+        double v_max = v(0);
+        for (int i = 1; i < 3; i++)
+        {
+            if (v_max > v(i))
+            {
+                v_max = v(i);
+                i_max = i;
             }
+        }
 
-            if (bcf_hrec_add_key(hrec, "length", strlen("length")) < 0) {
-                std::cerr << "Error: Cannot create VCF header contigs." << std::endl;
-                hts_close(vcfFile);
-                return 1;
-            }
+        return i_max;
+    }
 
-            if (bcf_hrec_set_val(hrec, hrec->nkeys-1, GRCh37_length[i].c_str(), strlen(GRCh37_length[i].c_str()), 0) < 0) {
-                std::cerr << "Error: Cannot create VCF header contigs." << std::endl;
-                hts_close(vcfFile);
-                return 1;
-            }
+    void CalculateViterbi(openfpm::vector<openfpm::vector<char>> &reference,
+                          Call_related_relevant_read_type &seqs,
+                          openfpm::vector<aggregate<short int, int, int>> &un_seed,
+                          call_vcf &call,
+                          int padding,
+                          openfpm::vector<int> &chr_ins,
+                          openfpm::vector<double> &bp_insert_prob)
+    {
+        // User viterbi algorithm to get the sequence of events
 
-            if (bcf_hrec_add_key(hrec, "assembly", strlen("assembly")) < 0) {
-                std::cerr << "Error: Cannot create VCF header contigs." << std::endl;
-                hts_close(vcfFile);
-                return 1;
-            }
+        // There are 6 events
 
-            if (bcf_hrec_set_val(hrec, hrec->nkeys-1, "b37", strlen("b37"), 0) < 0) {
-                std::cerr << "Error: Cannot create VCF header contigs." << std::endl;
-                hts_close(vcfFile);
-                return 1;
-            }
+        // 1 reference
+        // 2 Events  <------ This is an array of events of size N
+        // 3 unaligned
 
-            if (bcf_hdr_add_hrec(header,hrec) < 0) {
-                std::cerr << "Error: Cannot create VCF header contigs." << std::endl;
-                hts_close(vcfFile);
-                return 1;
-            }
-        }
-    }
+        // The transition matrix is f where f is the frequency of the allele (because we do not do any assumption f = 0.5)
+        //      1            2.1         3
+        // 1)  1/3*(1-f)  1/3N*f ...    1/3
 
-    return 0;
-}
+        // 2.1)  1/3  1/3N ... 1/3
+        // 2.2)  1/3  1/3N ... 1/3
 
-int set_header_format(bcf_hdr_t* header, htsFile* vcfFile) {
+        // 3)  1/3  1/3N ...    1/3
 
-    // Set GT
-    {
-        bcf_hrec_t *hrec = (bcf_hrec_t *)calloc(1, sizeof(bcf_hrec_t));
-        hrec->key = strdup("FORMAT");
-        if (bcf_hrec_add_key(hrec, "ID", strlen("ID")) < 0) {
-            std::cerr << "Error: Cannot create VCF header FORMAT" << std::endl;
-            hts_close(vcfFile);
-            return 1;
-        }
+        // The evidence Matrix is the probability of the read to support that evidence
 
-        if (bcf_hrec_set_val(hrec, hrec->nkeys-1, "GT", strlen("GT"), 0) < 0) {
-            std::cerr << "Error: Cannot create VCF header FORMAT" << std::endl;
-            hts_close(vcfFile);
-            return 1;
-        }
+        // We apply Viterbi algorithm to the sequence of randomly picked reads as described here:
+        // https://ocw.mit.edu/courses/16-410-principles-of-autonomy-and-decision-making-fall-2010/55e488318190f148c4ed211e2c96bada_MIT16_410F10_lec20.pdf
+        // Once we have the sequence
+        // We sum all the probabilities of the trajectory generated by the Viterbi algorithm divided by the the number the events
 
-        if (bcf_hrec_add_key(hrec, "Number", strlen("Number")) < 0) {
-            std::cerr << "Error: Cannot create VCF header contigs." << std::endl;
-            hts_close(vcfFile);
-            return 1;
-        }
+        // An event probability higher than 0.5 is considered an event
 
-        if (bcf_hrec_set_val(hrec, hrec->nkeys-1, "1", strlen("1"), 0) < 0) {
-            std::cerr << "Error: Cannot create VCF header contigs." << std::endl;
-            hts_close(vcfFile);
-            return 1;
-        }
+        int N = (2 * padding + 1) * (2 * padding + 1) + un_seed.size();
 
-        if (bcf_hrec_add_key(hrec, "Type", strlen("Type")) < 0) {
-            std::cerr << "Error: Cannot create VCF header contigs." << std::endl;
-            hts_close(vcfFile);
-            return 1;
-        }
+        Eigen::MatrixXd transition_log(N, N);
+        Eigen::VectorXd Initial_log(N); // <------ Initial state
 
-        if (bcf_hrec_set_val(hrec, hrec->nkeys-1, "String", strlen("String"), 0) < 0) {
-            std::cerr << "Error: Cannot create VCF header contigs." << std::endl;
-            hts_close(vcfFile);
-            return 1;
+        // Initial state
+        for (int i = 0; i < (2 * padding + 1) * (2 * padding + 1); i++)
+        {
+            Initial_log(i) = std::log(1.0f / N);
         }
-
-        if (bcf_hrec_add_key(hrec, "Description", strlen("Description")) < 0) {
-            std::cerr << "Error: Cannot create VCF header contigs." << std::endl;
-            hts_close(vcfFile);
-            return 1;
+        for (int i = (2 * padding + 1) * (2 * padding + 1); i < (2 * padding + 1) * (2 * padding + 1) + un_seed.size(); i++)
+        {
+            Initial_log(i) = std::log(1.0f / N);
         }
 
-        if (bcf_hrec_set_val(hrec, hrec->nkeys-1, "Segment genotype", strlen("Segment genotype"), 0) < 0) {
-            std::cerr << "Error: Cannot create VCF header contigs." << std::endl;
-            hts_close(vcfFile);
-            return 1;
+        // Fill transition matrix with uniform distribution
+        for (int i = 0; i < N; i++)
+        {
+            for (int j = 0; j < N; j++)
+            {
+                transition_log(i, j) = std::log(1.0 / ((2 * padding + 1) * (2 * padding + 1) + un_seed.size()));
+            }
         }
 
-        if (bcf_hdr_add_hrec(header,hrec) < 0) {
-            std::cerr << "Error: Cannot create VCF header contigs." << std::endl;
-            hts_close(vcfFile);
-            return 1;
-        }
-    }
+        openfpm::vector<int> permutation;
 
-    // Set QS
+        openfpm::vector<double> events;
+        events.resize((2 * padding + 1) * (2 * padding + 1) + un_seed.size());
 
-    {
-        bcf_hrec_t *hrec = (bcf_hrec_t *)calloc(1, sizeof(bcf_hrec_t));
-        hrec->key = strdup("FORMAT");
-        if (bcf_hrec_add_key(hrec, "ID", strlen("ID")) < 0) {
-            std::cerr << "Error: Cannot create VCF header FORMAT" << std::endl;
-            hts_close(vcfFile);
-            return 1;
-        }
+        // create a random permutation
+        randomPermutation(seqs.size(), permutation);
 
-        if (bcf_hrec_set_val(hrec, hrec->nkeys-1, "QS", strlen("QS"), 0) < 0) {
-            std::cerr << "Error: Cannot create VCF header FORMAT" << std::endl;
-            hts_close(vcfFile);
-            return 1;
-        }
+        openfpm::vector<Eigen::ArrayXd> delta_log;
+        openfpm::vector<Eigen::ArrayXd> insert;
+        openfpm::vector<Eigen::ArrayXd> Pre;
+        delta_log.resize(seqs.size());
+        insert.resize(seqs.size());
+        Pre.resize(seqs.size());
 
-        if (bcf_hrec_add_key(hrec, "Number", strlen("Number")) < 0) {
-            std::cerr << "Error: Cannot create VCF header contigs." << std::endl;
-            hts_close(vcfFile);
-            return 1;
-        }
+        int s = permutation.get(0) /*673*/;
 
-        if (bcf_hrec_set_val(hrec, hrec->nkeys-1, "1", strlen("1"), 0) < 0) {
-            std::cerr << "Error: Cannot create VCF header contigs." << std::endl;
-            hts_close(vcfFile);
-            return 1;
-        }
+        int seed_pos = seqs.get<4>(s);
+        delta_log.get(0).resize(Initial_log.size());
 
-        if (bcf_hrec_add_key(hrec, "Type", strlen("Type")) < 0) {
-            std::cerr << "Error: Cannot create VCF header contigs." << std::endl;
-            hts_close(vcfFile);
-            return 1;
-        }
+        // Carefull the Evidence matrix return the natural logarithm of the probability, initial contain the logarithm of the initial probability Initial_log = log(Initial)
+        // and delta_log contain the logarim of the delta log(delta)
+        // so the formula delta = Initial*Evidence_matrix in logaritm space become
+        // delta_log = log(Initial*Evidemce_matrix)
+        // delta_log = Initial_log + Evidence_matrix_log
+        Eigen::ArrayXd best_insert;
 
-        if (bcf_hrec_set_val(hrec, hrec->nkeys-1, "Float", strlen("Float"), 0) < 0) {
-            std::cerr << "Error: Cannot create VCF header contigs." << std::endl;
-            hts_close(vcfFile);
-            return 1;
-        }
+        delta_log.get(0) = Initial_log.array() + Evidence_matrix_log(reference, seqs.get<0>(s), un_seed, call, padding, seqs.get<1>(s), seqs.get<2>(s), seed_pos, chr_ins, best_insert, bp_insert_prob);
+        int x;
+        auto mC = delta_log.get(0).maxCoeff(&x);
+        std::cout << "BEST event: " << x << " " << mC << std::endl;
+        Pre.get(0).resize(Initial_log.size());
+        Pre.get(0) = -1;
 
-        if (bcf_hrec_add_key(hrec, "Description", strlen("Description")) < 0) {
-            std::cerr << "Error: Cannot create VCF header contigs." << std::endl;
-            hts_close(vcfFile);
-            return 1;
-        }
+        for (int i = 1; i < seqs.size(); i++)
+        {
+            int s = permutation.get(i);
+
+            seed_pos = seqs.get<4>(s);
+            Eigen::VectorXd next_transition(Initial_log.size());
+            std::cout << "Initial Array: " << Initial_log.array() << std::endl;
+            std::cout << "Event probs: " << delta_log.get(i - 1) << std::endl;
+
+            // Here we tranform by the transition matrix (we do everything in logaritmic space)
+            // The formula below is the multiplication of the transition matrix by the previous delta (Viterbi)
+            // avoiding undeflow problems
+            for (int j = 0; j < N; j++)
+            {
+
+                // First accumulation accum = transition(j,0)*delta(0)
+                // in log space
+                // accum_log = transition_log(j,0) + delta_log(0)
+                double accum_log = transition_log(j, 0) + delta_log.get(i - 1)(0);
+
+                // we are trying to calculate accum = sum_over_k (transition(j,k)*delta(k))
+                // in logarithmic space.
+                for (int k = 1; k < N; k++)
+                { // Classical Matix vector multiplication loop
+
+                    // accum = accum + transition(j,k)*delta(k)
+                    // in log space:
+                    // accum_log = log(accum + transition(j,k)*delta(k))
+                    // We split in two cases accum > transition(j,k)*delta(k), we also indicate accum -> a, transition(j,k) -> t, delta(k) -> d
+                    // accum_log = log(a*(1+ t*d/a))
+                    // accum_log = log(a) + log(1+t*d/a)
+                    // accum_log = log(a) + log(1+exp(log(t*d/a)))
+                    // accum_log = log(a) + log(1+exp(log(t)+log(d)-log(a)))
+                    // accum_log = log(a) + log(1+exp(-(log(a)-log(t)*log(d)))
+
+                    // In case t*d > accum we have
+                    // accum_log = log(t*d) + log(1+exp(-(log(t)+log(d)-log(a)))
+
+                    // This can be rewritten in a single case as C math functions
+
+                    // accum_log = fmax(a,t_log+d_log) + log(1+exp(-fabs(t_log+d_log-a_log))))
+                    // or
+                    // accum_log = fmax(a,t_log+d_log) + log1p(1+exp(-fabs(t_log+d_log-a_log))))
+
+                    accum_log = fmax(accum_log, transition_log(j, k) + delta_log.get(i - 1)(k)) + log1p(exp(-fabs(delta_log.get(i - 1)(k) + transition_log(j, k) - accum_log)));
+                }
 
+                std::cout << accum_log << std::endl;
 
-        if (bcf_hrec_set_val(hrec, hrec->nkeys-1, "Quality of the call, number of expected false positives", strlen("Quality of the call, number of expected false positives"), 0) < 0) {
-            std::cerr << "Error: Cannot create VCF header contigs." << std::endl;
-            hts_close(vcfFile);
-            return 1;
-        }
+                next_transition(j) = accum_log;
+            }
 
-        if (bcf_hdr_add_hrec(header,hrec) < 0) {
-            std::cerr << "Error: Cannot create VCF header contigs." << std::endl;
-            hts_close(vcfFile);
-            return 1;
+            int x;
+            double coeff = next_transition.maxCoeff(&x);
+            best_insert.resize(Initial_log.size());
+            Eigen::ArrayXd eml = Evidence_matrix_log(reference, seqs.get<0>(s), un_seed, call, padding, seqs.get<1>(s), seqs.get<2>(s), seed_pos, chr_ins, best_insert, bp_insert_prob);
+            auto mC = eml.maxCoeff(&x);
+            std::cout << "Best event: " << x << " " << mC << std::endl;
+            std::cout << "Next transition: " << eml << std::endl;
+            delta_log.get(i) = coeff + eml;
+
+            if (i + 1 < seqs.size())
+            {
+                Pre.get(i + 1) = x;
+            }
         }
-    }
 
-    // Set the CN
+        int s_star = ArgMax(delta_log.last());
 
-    {
-        bcf_hrec_t *hrec = (bcf_hrec_t *)calloc(1, sizeof(bcf_hrec_t));
-        hrec->key = strdup("FORMAT");
-        if (bcf_hrec_add_key(hrec, "ID", strlen("ID")) < 0) {
-            std::cerr << "Error: Cannot create VCF header FORMAT" << std::endl;
-            hts_close(vcfFile);
-            return 1;
-        }
+        // backtrace to find the most probable path
 
-        if (bcf_hrec_set_val(hrec, hrec->nkeys-1, "CN", strlen("CN"), 0) < 0) {
-            std::cerr << "Error: Cannot create VCF header FORMAT" << std::endl;
-            hts_close(vcfFile);
-            return 1;
-        }
+        openfpm::vector<int> event;
+        openfpm::vector<Eigen::Array3d> probs;
 
-        if (bcf_hrec_add_key(hrec, "Number", strlen("Number")) < 0) {
-            std::cerr << "Error: Cannot create VCF header contigs." << std::endl;
-            hts_close(vcfFile);
-            return 1;
-        }
+        event.resize(seqs.size());
+        probs.resize(seqs.size());
 
-        if (bcf_hrec_set_val(hrec, hrec->nkeys-1, "1", strlen("1"), 0) < 0) {
-            std::cerr << "Error: Cannot create VCF header contigs." << std::endl;
-            hts_close(vcfFile);
-            return 1;
-        }
+        int q_k_p1 = s_star;
 
-        if (bcf_hrec_add_key(hrec, "Type", strlen("Type")) < 0) {
-            std::cerr << "Error: Cannot create VCF header contigs." << std::endl;
-            hts_close(vcfFile);
-            return 1;
+        for (int i = seqs.size() - 1; i > 0; i--)
+        {
+            event.get(i) = Pre.get(i)(q_k_p1);
+            q_k_p1 = event.get(i);
         }
+    }
 
-        if (bcf_hrec_set_val(hrec, hrec->nkeys-1, "Integer", strlen("Integer"), 0) < 0) {
-            std::cerr << "Error: Cannot create VCF header contigs." << std::endl;
-            hts_close(vcfFile);
-            return 1;
+    void convert_seed_map_to_array(openfpm::vector<seed_id> &seed,
+                                   tsl::hopscotch_map<size_t, openfpm::vector<CNV_event_link>> &map,
+                                   openfpm::vector<call_vcf> &calls)
+    {
+        for (auto i = map.begin(); i != map.end(); i++)
+        {
+            seed.add();
+            int last = seed.size() - 1;
+            seed.get(last).seed = i->first;
+            for (int j = 0; j < i->second.size(); j++)
+            {
+                int cid = i->second.get(j).call_id;
+
+                struct seed_pos tmp;
+                tmp.cid = cid;
+                tmp.chr = calls.get(i->second.get(j).call_id).chromosome;
+                ;
+                tmp.pos = i->second.get(j).pos_seed;
+                ;
+
+                seed.get(last).calls.add(tmp);
+            }
         }
+    }
 
-        if (bcf_hrec_add_key(hrec, "Description", strlen("Description")) < 0) {
-            std::cerr << "Error: Cannot create VCF header contigs." << std::endl;
-            hts_close(vcfFile);
-            return 1;
-        }
+    void CNV_event_test(openfpm::vector<call_vcf> &calls,
+                        openfpm::vector<openfpm::vector<char>> &reference,
+                        openfpm::vector<std::string> &files_bams,
+                        int padding,
+                        openfpm::vector<aggregate<openfpm::vector<int>>> &chr_ins)
+    {
+        char seq1[16384];
+        char seq2[16384];
+        char seq3[16384];
 
+        openfpm::vector<double> bp_insert_prob;
+        bp_insert_prob.load("insert_probability_distribution");
+        tsl::hopscotch_map<size_t, openfpm::vector<CNV_event_link>> map;
 
-        if (bcf_hrec_set_val(hrec, hrec->nkeys-1, "Segment most-likely copy-number call", strlen("Segment most-likely copy-number call"), 0) < 0) {
-            std::cerr << "Error: Cannot create VCF header contigs." << std::endl;
-            hts_close(vcfFile);
-            return 1;
-        }
+        map.reserve(calls.size() * 2);
 
-        if (bcf_hdr_add_hrec(header,hrec) < 0) {
-            std::cerr << "Error: Cannot create VCF header contigs." << std::endl;
-            hts_close(vcfFile);
-            return 1;
-        }
-    }
+        for (int i = 0; i < calls.size(); i++)
+        {
 
-    // Set END
+            if (i % 1000 == 0)
+            {
+                std::cout << "Creating Map: " << i << "/" << calls.size() << std::endl;
+            }
 
-    {
-        bcf_hrec_t *hrec = (bcf_hrec_t *)calloc(1, sizeof(bcf_hrec_t));
-        hrec->key = strdup("INFO");
-        if (bcf_hrec_add_key(hrec, "ID", strlen("ID")) < 0) {
-            std::cerr << "Error: Cannot create VCF header FORMAT" << std::endl;
-            hts_close(vcfFile);
-            return 1;
-        }
+            int offset = std::min(calls.get(i).start - 32, 0);
 
-        if (bcf_hrec_set_val(hrec, hrec->nkeys-1, "END", strlen("END"), 0) < 0) {
-            std::cerr << "Error: Cannot create VCF header FORMAT" << std::endl;
-            hts_close(vcfFile);
-            return 1;
-        }
+            // Store the patterns related to the reference
+            for (int j = -padding; j < padding; j++)
+            {
+                if (calls.get(i).start - 32 + j - offset < 0)
+                {
+                    continue;
+                }
 
-        if (bcf_hrec_add_key(hrec, "Number", strlen("Number")) < 0) {
-            std::cerr << "Error: Cannot create VCF header contigs." << std::endl;
-            hts_close(vcfFile);
-            return 1;
-        }
+                // DEBUG
+                char seq[64];
+                get_sequence(reference, calls.get(i).chromosome, calls.get(i).start - 32 + j - offset, calls.get(i).start + j - offset, -1, -1, seq);
+                seq[33] = 0;
+                std::cout << "ADDING sequence at " << calls.get(i).chromosome << ":" << calls.get(i).start - 32 + j - offset << "  SEQUENCE: " << seq << std::endl;
 
-        if (bcf_hrec_set_val(hrec, hrec->nkeys-1, "1", strlen("1"), 0) < 0) {
-            std::cerr << "Error: Cannot create VCF header contigs." << std::endl;
-            hts_close(vcfFile);
-            return 1;
-        }
+                add_32bases_pattern(calls.get(i).chromosome, calls.get(i).start - 32 + j - offset,
+                                    reference, map, i, -32 + j - offset, -1);
+            }
 
-        if (bcf_hrec_add_key(hrec, "Type", strlen("Type")) < 0) {
-            std::cerr << "Error: Cannot create VCF header contigs." << std::endl;
-            hts_close(vcfFile);
-            return 1;
-        }
+            // Store the patterns related to the stop
+            for (int j = -padding; j < padding; j++)
+            {
+                if (calls.get(i).stop + j + 32 >= reference.get(calls.get(i).chromosome).size())
+                {
+                    continue;
+                }
 
-        if (bcf_hrec_set_val(hrec, hrec->nkeys-1, "Integer", strlen("Integer"), 0) < 0) {
-            std::cerr << "Error: Cannot create VCF header contigs." << std::endl;
-            hts_close(vcfFile);
-            return 1;
-        }
+                // DEBUG
+                char seq[64];
+                get_sequence(reference, calls.get(i).chromosome, calls.get(i).stop + j, calls.get(i).stop + j + 32, -1, -1, seq);
+                seq[33] = 0;
+                std::cout << "ADDING sequence at " << calls.get(i).chromosome << ":" << calls.get(i).stop + j << "  SEQUENCE: " << seq << std::endl;
 
-        if (bcf_hrec_add_key(hrec, "Description", strlen("Description")) < 0) {
-            std::cerr << "Error: Cannot create VCF header contigs." << std::endl;
-            hts_close(vcfFile);
-            return 1;
+                add_32bases_pattern(calls.get(i).chromosome, calls.get(i).stop + j,
+                                    reference, map, i, j, -1);
+            }
         }
 
+        // Collect evidences for the SV calls
+        // Samples // calls // sequences // bases
 
-        if (bcf_hrec_set_val(hrec, hrec->nkeys-1, "End coordinate of the variant", strlen("End coordinate of the variant"), 0) < 0) {
-            std::cerr << "Error: Cannot create VCF header contigs." << std::endl;
-            hts_close(vcfFile);
-            return 1;
-        }
+        All_samples_call_related_relevant_read_type seqs;
 
-        if (bcf_hdr_add_hrec(header,hrec) < 0) {
-            std::cerr << "Error: Cannot create VCF header contigs." << std::endl;
-            hts_close(vcfFile);
-            return 1;
-        }
-    }
+        /*    seqs.resize(files_bams.size());
 
-    return 0;
-}
+            for (int i = 0 ; i < files_bams.size() ; i++) {
+                collect_reads_for_call_evidence(files_bams.get(i),map,calls,seqs.get<0>(i),reference);
+            }
 
+            std::cout << "Saving sequences" << std::endl;
+            seqs.save("seqs_call_vector");
+            std::cout << "Saved sequences" << std::endl;
 
-int set_header_info(bcf_hdr_t* header, htsFile* vcfFile) {
+            return;*/
 
-    // Set PS_START
-    {
-        bcf_hrec_t *hrec = (bcf_hrec_t *)calloc(1, sizeof(bcf_hrec_t));
-        hrec->key = strdup("INFO");
-        if (bcf_hrec_add_key(hrec, "ID", strlen("ID")) < 0) {
-            std::cerr << "Error: Cannot create VCF header INFO" << std::endl;
-            hts_close(vcfFile);
-            return 1;
-        }
+        seqs.load("seqs_call_vector");
 
-        if (bcf_hrec_set_val(hrec, hrec->nkeys-1, "PS_START", strlen("PS_START"), 0) < 0) {
-            std::cerr << "Error: Cannot create VCF header INFO" << std::endl;
-            hts_close(vcfFile);
-            return 1;
-        }
+        openfpm::vector<seed_id> seed;
+        openfpm::vector<openfpm::vector<aggregate<short int, int, int>>> un_seed;
 
-        if (bcf_hrec_add_key(hrec, "Number", strlen("Number")) < 0) {
-            std::cerr << "Error: Cannot create VCF header INFO." << std::endl;
-            hts_close(vcfFile);
-            return 1;
-        }
+        convert_seed_map_to_array(seed, map, calls);
 
-        if (bcf_hrec_set_val(hrec, hrec->nkeys-1, "1", strlen("1"), 0) < 0) {
-            std::cerr << "Error: Cannot create VCF header INFO." << std::endl;
-            hts_close(vcfFile);
-            return 1;
-        }
+        un_seed.resize(calls.size());
+        get_reference_point(seed, reference, un_seed);
 
-        if (bcf_hrec_add_key(hrec, "Type", strlen("Type")) < 0) {
-            std::cerr << "Error: Cannot create VCF header INFO." << std::endl;
-            hts_close(vcfFile);
-            return 1;
-        }
+        for (int i = 0; i < seed.size(); i++)
+        {
+            for (int j = 0; j < seed.get(i).calls.size(); j++)
+            {
+                char seq[64];
+                get_sequence(reference, seed.get(i).calls.get(j).chr, seed.get(i).calls.get(j).pos, seed.get(i).calls.get(j).pos + 32, -1, -1, seq);
+                seq[33] = 0;
 
-        if (bcf_hrec_set_val(hrec, hrec->nkeys-1, "Integer", strlen("Integer"), 0) < 0) {
-            std::cerr << "Error: Cannot create VCF header INFO." << std::endl;
-            hts_close(vcfFile);
-            return 1;
+                std::cout << "SEED POS: " << seed.get(i).calls.get(j).chr << ":" << seed.get(i).calls.get(j).pos << "  SEQUENCE: " << seq << "   ID " << seed.get(i).seed << std::endl;
+            }
         }
 
-        if (bcf_hrec_add_key(hrec, "Description", strlen("Description")) < 0) {
-            std::cerr << "Error: Cannot create VCF header INFO." << std::endl;
-            hts_close(vcfFile);
-            return 1;
+        // Check reference points
+        for (int cid = 0; cid < un_seed.size(); cid++)
+        {
+            std::cout << "CALL ID: " << cid << std::endl;
+            for (int j = 0; j < un_seed.get(cid).size(); j++)
+            {
+                char seq[64];
+                get_sequence(reference, un_seed.get(cid).get<0>(j), un_seed.get(cid).get<1>(j), un_seed.get(cid).get<1>(j) + 32, -1, -1, seq);
+                seq[33] = 0;
+                std::cout << "    " << un_seed.get(cid).get<0>(j) << ":" << un_seed.get(cid).get<1>(j) << " SEQUENCE: " << seq << "   ID " << seed.get(un_seed.get(cid).get<2>(j)).seed << " K:" << un_seed.get(cid).get<2>(j) << std::endl;
+            }
         }
 
-        if (bcf_hrec_set_val(hrec, hrec->nkeys-1, "Indicate if a split-read has been found to identify the precise starting point of the  event", 
-                                           strlen("Indicate if a split-read has been found to identify the precise starting point of the  event"), 0) < 0) {
-            std::cerr << "Error: Cannot create VCF header INFO." << std::endl;
-            hts_close(vcfFile);
-            return 1;
-        }
+        double reading_error = 1e-2;
 
-        if (bcf_hdr_add_hrec(header,hrec) < 0) {
-            std::cerr << "Error: Cannot create VCF header INFO." << std::endl;
-            hts_close(vcfFile);
-            return 1;
+        for (int i = 0; i < seqs.size(); i++)
+        {
+            for (int j = 0; j < seqs.get<0>(i).size(); j++)
+            {
+                CalculateViterbi(reference, seqs.get<0>(i).get<0>(j), un_seed.get(j), calls.get(i), padding, chr_ins.get<0>(i), bp_insert_prob);
+            }
         }
     }
 
-    // Set PS_STOP
-
+    void read_bed_file(std::string bed_f, openfpm::vector<aggregate<short int, int, int>> &intervals, int pad)
     {
-        bcf_hrec_t *hrec = (bcf_hrec_t *)calloc(1, sizeof(bcf_hrec_t));
-        hrec->key = strdup("INFO");
-        if (bcf_hrec_add_key(hrec, "ID", strlen("ID")) < 0) {
-            std::cerr << "Error: Cannot create VCF header INFO" << std::endl;
-            hts_close(vcfFile);
-            return 1;
-        }
+        std::ifstream bedFile(bed_f.c_str());
 
-        if (bcf_hrec_set_val(hrec, hrec->nkeys-1, "PS_STOP", strlen("PS_STOP"), 0) < 0) {
-            std::cerr << "Error: Cannot create VCF header INFO" << std::endl;
-            hts_close(vcfFile);
-            return 1;
+        if (!bedFile.is_open())
+        {
+            std::cerr << "Error: Unable to open the BED file." << std::endl;
+            return;
         }
 
-        if (bcf_hrec_add_key(hrec, "Number", strlen("Number")) < 0) {
-            std::cerr << "Error: Cannot create VCF header INFO" << std::endl;
-            hts_close(vcfFile);
-            return 1;
-        }
+        std::string line;
 
-        if (bcf_hrec_set_val(hrec, hrec->nkeys-1, "1", strlen("1"), 0) < 0) {
-            std::cerr << "Error: Cannot create VCF header INFO" << std::endl;
-            hts_close(vcfFile);
-            return 1;
-        }
+        char str[256];
 
-        if (bcf_hrec_add_key(hrec, "Type", strlen("Type")) < 0) {
-            std::cerr << "Error: Cannot create VCF header INFO" << std::endl;
-            hts_close(vcfFile);
-            return 1;
-        }
+        while (std::getline(bedFile, line))
+        {
+            std::istringstream iss(line);
 
-        if (bcf_hrec_set_val(hrec, hrec->nkeys-1, "Integer", strlen("Integer"), 0) < 0) {
-            std::cerr << "Error: Cannot create VCF header INFO" << std::endl;
-            hts_close(vcfFile);
-            return 1;
-        }
+            iss >> str;
+            int chr_int = chr_to_chr_int(str);
+            if (chr_int == -1)
+            {
+                continue;
+            }
 
-        if (bcf_hrec_add_key(hrec, "Description", strlen("Description")) < 0) {
-            std::cerr << "Error: Cannot create VCF header INFO" << std::endl;
-            hts_close(vcfFile);
-            return 1;
-        }
+            intervals.add();
+            intervals.last().get<0>() = chr_int;
+            iss >> intervals.last().get<1>();
+            iss >> intervals.last().get<2>();
 
-        if (bcf_hrec_set_val(hrec, hrec->nkeys-1, "Indicate if a split-read has been found to identify the precise stop point of the  event", 
-                                           strlen("Indicate if a split-read has been found to identify the precise stop point of the  event"), 0) < 0) {
-            std::cerr << "Error: Cannot create VCF header INFO" << std::endl;
-            hts_close(vcfFile);
-            return 1;
-        }
+            intervals.last().get<2>() += 1;
 
-        if (bcf_hdr_add_hrec(header,hrec) < 0) {
-            std::cerr << "Error: Cannot create VCF header INFO" << std::endl;
-            hts_close(vcfFile);
-            return 1;
+            if (intervals.last().get<2>() <= intervals.last().get<1>())
+            {
+                std::cout << "Bed file are interpreted as start (included) and stop (included), based on this standard the region " << chr_int + 1 << " " << intervals.last().get<1>() << " " << intervals.last().get<2>() << std::endl;
+                std::cout << "Note aside internally we use the more conventional (included) (excluded) it look like that famous enrichment kits has the above fetish ... or they do not know what they are doing" << std::endl;
+            }
         }
-    }
- 
-    return 0;
-}
-
-template<unsigned int N_sample_opt>
-int create_vcf_calls(openfpm::vector<openfpm::vector<call_vcf>> & calls, openfpm::vector<std::string> & files_bams) {
-
-    for (int i = 0 ; i < calls.size() ; i++) {
-        std::string str;
-        openfpm::vector<call_vcf> & cvcf = calls.get(i);
 
-        std::string sample_name = split(basename(files_bams.get(i).c_str()),".")[0];
+        bedFile.close();
+    }
 
-        // Initialize VCF header and writer
-        htsFile* vcfFile = hts_open(std::string(sample_name + ".vcf").c_str(), "w");
-        if (vcfFile == nullptr) {
-            std::cerr << "Error: Cannot open output VCF file" << std::endl;
-            return 1;
-        }
+    template <typename T>
+    T penalization_fishing(T &a, T left, T right)
+    {
+        T min_distance = std::min(fabs(a - left) * 1000, fabs(a - right) * 1000);
+
+        return min_distance;
+    }
+
+    std::string GRCh37_length[] = {"249250621",
+                                   "243199373",
+                                   "198022430",
+                                   "191154276",
+                                   "180915260",
+                                   "171115067",
+                                   "159138663",
+                                   "146364022",
+                                   "141213431",
+                                   "135534747",
+                                   "135006516",
+                                   "133851895",
+                                   "115169878",
+                                   "107349540",
+                                   "102531392",
+                                   "90354753",
+                                   "81195210",
+                                   "78077248",
+                                   "59128983",
+                                   "63025520",
+                                   "48129895",
+                                   "51304566",
+                                   "155270560",
+                                   "59373566",
+                                   "16569"};
+
+    std::string GRCh37_contig[] = {"1",
+                                   "2",
+                                   "3",
+                                   "4",
+                                   "5",
+                                   "6",
+                                   "7",
+                                   "8",
+                                   "9",
+                                   "10",
+                                   "11",
+                                   "12",
+                                   "13",
+                                   "14",
+                                   "15",
+                                   "16",
+                                   "17",
+                                   "18",
+                                   "19",
+                                   "20",
+                                   "21",
+                                   "22",
+                                   "X",
+                                   "Y",
+                                   "MT"};
+
+    const int GRCh37_n_contig = 24;
+
+    int set_header_assembly(bcf_hdr_t *header, htsFile *vcfFile, const std::string &assembly)
+    {
+        if (assembly == "GRCh37")
+        {
+            for (int i = 0; i < GRCh37_n_contig; i++)
+            {
+                // Create the header
+                bcf_hrec_t *hrec = (bcf_hrec_t *)calloc(1, sizeof(bcf_hrec_t));
+                hrec->key = strdup("contig");
+                if (bcf_hrec_add_key(hrec, "ID", strlen("ID")) < 0)
+                {
+                    std::cerr << "Error: Cannot create VCF header contigs." << std::endl;
+                    hts_close(vcfFile);
+                    return 1;
+                }
 
-        // Create a VCF header
-        bcf_hdr_t* header = bcf_hdr_init("w");
-        if (header == nullptr) {
-            std::cerr << "Error: Cannot create VCF header." << std::endl;
-            hts_close(vcfFile);
-            return 1;
-        }
+                if (bcf_hrec_set_val(hrec, hrec->nkeys - 1, GRCh37_contig[i].c_str(), strlen(GRCh37_contig[i].c_str()), 0) < 0)
+                {
+                    std::cerr << "Error: Cannot create VCF header contigs." << std::endl;
+                    hts_close(vcfFile);
+                    return 1;
+                }
 
-        bcf_hdr_add_sample(header,sample_name.c_str());
+                if (bcf_hrec_add_key(hrec, "length", strlen("length")) < 0)
+                {
+                    std::cerr << "Error: Cannot create VCF header contigs." << std::endl;
+                    hts_close(vcfFile);
+                    return 1;
+                }
 
-        set_header_assembly(header,vcfFile,"GRCh37");
-        set_header_format(header,vcfFile);
-        set_header_info(header,vcfFile);
+                if (bcf_hrec_set_val(hrec, hrec->nkeys - 1, GRCh37_length[i].c_str(), strlen(GRCh37_length[i].c_str()), 0) < 0)
+                {
+                    std::cerr << "Error: Cannot create VCF header contigs." << std::endl;
+                    hts_close(vcfFile);
+                    return 1;
+                }
 
-        // Add sample information to the header if needed
-        // bcf_hdr_add_sample(header, "Sample1");
+                if (bcf_hrec_add_key(hrec, "assembly", strlen("assembly")) < 0)
+                {
+                    std::cerr << "Error: Cannot create VCF header contigs." << std::endl;
+                    hts_close(vcfFile);
+                    return 1;
+                }
 
-        // Write the VCF header to the output file
-        if (bcf_hdr_write(vcfFile, header) != 0) {
-            std::cerr << "Error: Cannot write VCF header" << std::endl;
-            bcf_hdr_destroy(header);
-            hts_close(vcfFile);
-            return 1;
-        }
+                if (bcf_hrec_set_val(hrec, hrec->nkeys - 1, "b37", strlen("b37"), 0) < 0)
+                {
+                    std::cerr << "Error: Cannot create VCF header contigs." << std::endl;
+                    hts_close(vcfFile);
+                    return 1;
+                }
 
-        // Create a VCF record
-        bcf1_t* record = bcf_init1();
-        if (record == nullptr) {
-            std::cerr << "Error: Cannot create VCF record" << std::endl;
-            bcf_hdr_destroy(header);
-            hts_close(vcfFile);
-            return 1;
+                if (bcf_hdr_add_hrec(header, hrec) < 0)
+                {
+                    std::cerr << "Error: Cannot create VCF header contigs." << std::endl;
+                    hts_close(vcfFile);
+                    return 1;
+                }
+            }
         }
 
+        return 0;
+    }
 
-        for (int j = 0 ; j < cvcf.size() ; j++) {
-            std::stringstream ss;
-
+    int set_header_format(bcf_hdr_t *header, htsFile *vcfFile)
+    {
 
-            ss << chr_int_to_chr(cvcf.get(j).chromosome+1) << "\t";
-            ss << cvcf.get(j).start << "\t";
-            ss << "CNV_" << cvcf.get(j).chromosome << "_" << cvcf.get(j).start << "_" << cvcf.get(j).stop << "_" << cvcf.get(j).CN << "\t";
-            ss << "N" << "\t";
-            if (cvcf.get(j).CN < 2) {
-                ss << "<DEL>" << "\t";
-            } else {
-                ss << "<DUP>" << "\t";
+        // Set GT
+        {
+            bcf_hrec_t *hrec = (bcf_hrec_t *)calloc(1, sizeof(bcf_hrec_t));
+            hrec->key = strdup("FORMAT");
+            if (bcf_hrec_add_key(hrec, "ID", strlen("ID")) < 0)
+            {
+                std::cerr << "Error: Cannot create VCF header FORMAT" << std::endl;
+                hts_close(vcfFile);
+                return 1;
             }
 
-            // QUALITY
-            ss << cvcf.get(j).quality << "\t";
-
-            // FILTER
-            ss << "." << "\t";
-
-            // INFO
-            std::string info;
-            if (cvcf.get(j).precise_start == true) {
-                info += "PS_START=1";
-            }
-            if (cvcf.get(j).precise_stop == true) {
-                if (info.size() != 0) {
-                    info += ";";
-                }
-                ss << "PS_STOP=1";
-            }
-            if (info.size() != 0) {
-                info += ";";
+            if (bcf_hrec_set_val(hrec, hrec->nkeys - 1, "GT", strlen("GT"), 0) < 0)
+            {
+                std::cerr << "Error: Cannot create VCF header FORMAT" << std::endl;
+                hts_close(vcfFile);
+                return 1;
             }
-            info += "END=" + std::to_string(cvcf.get(j).stop);
 
-            if (info.size() != 0) {
-                ss << info << "\t";
-            } else {
-                ss << "." << "\t";
+            if (bcf_hrec_add_key(hrec, "Number", strlen("Number")) < 0)
+            {
+                std::cerr << "Error: Cannot create VCF header contigs." << std::endl;
+                hts_close(vcfFile);
+                return 1;
             }
 
-            ss << "GT:CN:QS" << "\t";
-            if (cvcf.get(j).CN == 0) {
-                ss << "1/1";
-            } else if (cvcf.get(j).CN == 1) {
-                ss << "0/1";
-            } else {
-                ss << "./.";
+            if (bcf_hrec_set_val(hrec, hrec->nkeys - 1, "1", strlen("1"), 0) < 0)
+            {
+                std::cerr << "Error: Cannot create VCF header contigs." << std::endl;
+                hts_close(vcfFile);
+                return 1;
             }
-            ss << ":" << cvcf.get(j).CN << ":" << cvcf.get(j).quality;
-            kstring_t s;
-            ks_initialize(&s);
-            kputs(ss.str().c_str(),&s);
-            vcf_parse(&s,header,record);
 
-            if (bcf_write1(vcfFile, header, record) != 0) {
-                std::cerr << "Error: Cannot write VCF record" << std::endl;
-            }
-        }
+            if (bcf_hrec_add_key(hrec, "Type", strlen("Type")) < 0)
+            {
+                std::cerr << "Error: Cannot create VCF header contigs." << std::endl;
+                hts_close(vcfFile);
+                return 1;
+            }
 
-        // Clean up resources
-        bcf_destroy1(record);
-        bcf_hdr_destroy(header);
-        hts_close(vcfFile);
+            if (bcf_hrec_set_val(hrec, hrec->nkeys - 1, "String", strlen("String"), 0) < 0)
+            {
+                std::cerr << "Error: Cannot create VCF header contigs." << std::endl;
+                hts_close(vcfFile);
+                return 1;
+            }
+
+            if (bcf_hrec_add_key(hrec, "Description", strlen("Description")) < 0)
+            {
+                std::cerr << "Error: Cannot create VCF header contigs." << std::endl;
+                hts_close(vcfFile);
+                return 1;
+            }
+
+            if (bcf_hrec_set_val(hrec, hrec->nkeys - 1, "Segment genotype", strlen("Segment genotype"), 0) < 0)
+            {
+                std::cerr << "Error: Cannot create VCF header contigs." << std::endl;
+                hts_close(vcfFile);
+                return 1;
+            }
+
+            if (bcf_hdr_add_hrec(header, hrec) < 0)
+            {
+                std::cerr << "Error: Cannot create VCF header contigs." << std::endl;
+                hts_close(vcfFile);
+                return 1;
+            }
+        }
+
+        // Set QS
+
+        {
+            bcf_hrec_t *hrec = (bcf_hrec_t *)calloc(1, sizeof(bcf_hrec_t));
+            hrec->key = strdup("FORMAT");
+            if (bcf_hrec_add_key(hrec, "ID", strlen("ID")) < 0)
+            {
+                std::cerr << "Error: Cannot create VCF header FORMAT" << std::endl;
+                hts_close(vcfFile);
+                return 1;
+            }
+
+            if (bcf_hrec_set_val(hrec, hrec->nkeys - 1, "QS", strlen("QS"), 0) < 0)
+            {
+                std::cerr << "Error: Cannot create VCF header FORMAT" << std::endl;
+                hts_close(vcfFile);
+                return 1;
+            }
+
+            if (bcf_hrec_add_key(hrec, "Number", strlen("Number")) < 0)
+            {
+                std::cerr << "Error: Cannot create VCF header contigs." << std::endl;
+                hts_close(vcfFile);
+                return 1;
+            }
+
+            if (bcf_hrec_set_val(hrec, hrec->nkeys - 1, "1", strlen("1"), 0) < 0)
+            {
+                std::cerr << "Error: Cannot create VCF header contigs." << std::endl;
+                hts_close(vcfFile);
+                return 1;
+            }
+
+            if (bcf_hrec_add_key(hrec, "Type", strlen("Type")) < 0)
+            {
+                std::cerr << "Error: Cannot create VCF header contigs." << std::endl;
+                hts_close(vcfFile);
+                return 1;
+            }
+
+            if (bcf_hrec_set_val(hrec, hrec->nkeys - 1, "Float", strlen("Float"), 0) < 0)
+            {
+                std::cerr << "Error: Cannot create VCF header contigs." << std::endl;
+                hts_close(vcfFile);
+                return 1;
+            }
+
+            if (bcf_hrec_add_key(hrec, "Description", strlen("Description")) < 0)
+            {
+                std::cerr << "Error: Cannot create VCF header contigs." << std::endl;
+                hts_close(vcfFile);
+                return 1;
+            }
+
+            if (bcf_hrec_set_val(hrec, hrec->nkeys - 1, "Quality of the call, number of expected false positives", strlen("Quality of the call, number of expected false positives"), 0) < 0)
+            {
+                std::cerr << "Error: Cannot create VCF header contigs." << std::endl;
+                hts_close(vcfFile);
+                return 1;
+            }
+
+            if (bcf_hdr_add_hrec(header, hrec) < 0)
+            {
+                std::cerr << "Error: Cannot create VCF header contigs." << std::endl;
+                hts_close(vcfFile);
+                return 1;
+            }
+        }
+
+        // Set the CN
+
+        {
+            bcf_hrec_t *hrec = (bcf_hrec_t *)calloc(1, sizeof(bcf_hrec_t));
+            hrec->key = strdup("FORMAT");
+            if (bcf_hrec_add_key(hrec, "ID", strlen("ID")) < 0)
+            {
+                std::cerr << "Error: Cannot create VCF header FORMAT" << std::endl;
+                hts_close(vcfFile);
+                return 1;
+            }
+
+            if (bcf_hrec_set_val(hrec, hrec->nkeys - 1, "CN", strlen("CN"), 0) < 0)
+            {
+                std::cerr << "Error: Cannot create VCF header FORMAT" << std::endl;
+                hts_close(vcfFile);
+                return 1;
+            }
+
+            if (bcf_hrec_add_key(hrec, "Number", strlen("Number")) < 0)
+            {
+                std::cerr << "Error: Cannot create VCF header contigs." << std::endl;
+                hts_close(vcfFile);
+                return 1;
+            }
+
+            if (bcf_hrec_set_val(hrec, hrec->nkeys - 1, "1", strlen("1"), 0) < 0)
+            {
+                std::cerr << "Error: Cannot create VCF header contigs." << std::endl;
+                hts_close(vcfFile);
+                return 1;
+            }
+
+            if (bcf_hrec_add_key(hrec, "Type", strlen("Type")) < 0)
+            {
+                std::cerr << "Error: Cannot create VCF header contigs." << std::endl;
+                hts_close(vcfFile);
+                return 1;
+            }
+
+            if (bcf_hrec_set_val(hrec, hrec->nkeys - 1, "Integer", strlen("Integer"), 0) < 0)
+            {
+                std::cerr << "Error: Cannot create VCF header contigs." << std::endl;
+                hts_close(vcfFile);
+                return 1;
+            }
+
+            if (bcf_hrec_add_key(hrec, "Description", strlen("Description")) < 0)
+            {
+                std::cerr << "Error: Cannot create VCF header contigs." << std::endl;
+                hts_close(vcfFile);
+                return 1;
+            }
+
+            if (bcf_hrec_set_val(hrec, hrec->nkeys - 1, "Segment most-likely copy-number call", strlen("Segment most-likely copy-number call"), 0) < 0)
+            {
+                std::cerr << "Error: Cannot create VCF header contigs." << std::endl;
+                hts_close(vcfFile);
+                return 1;
+            }
+
+            if (bcf_hdr_add_hrec(header, hrec) < 0)
+            {
+                std::cerr << "Error: Cannot create VCF header contigs." << std::endl;
+                hts_close(vcfFile);
+                return 1;
+            }
+        }
+
+        // Set END
+
+        {
+            bcf_hrec_t *hrec = (bcf_hrec_t *)calloc(1, sizeof(bcf_hrec_t));
+            hrec->key = strdup("INFO");
+            if (bcf_hrec_add_key(hrec, "ID", strlen("ID")) < 0)
+            {
+                std::cerr << "Error: Cannot create VCF header FORMAT" << std::endl;
+                hts_close(vcfFile);
+                return 1;
+            }
+
+            if (bcf_hrec_set_val(hrec, hrec->nkeys - 1, "END", strlen("END"), 0) < 0)
+            {
+                std::cerr << "Error: Cannot create VCF header FORMAT" << std::endl;
+                hts_close(vcfFile);
+                return 1;
+            }
+
+            if (bcf_hrec_add_key(hrec, "Number", strlen("Number")) < 0)
+            {
+                std::cerr << "Error: Cannot create VCF header contigs." << std::endl;
+                hts_close(vcfFile);
+                return 1;
+            }
+
+            if (bcf_hrec_set_val(hrec, hrec->nkeys - 1, "1", strlen("1"), 0) < 0)
+            {
+                std::cerr << "Error: Cannot create VCF header contigs." << std::endl;
+                hts_close(vcfFile);
+                return 1;
+            }
+
+            if (bcf_hrec_add_key(hrec, "Type", strlen("Type")) < 0)
+            {
+                std::cerr << "Error: Cannot create VCF header contigs." << std::endl;
+                hts_close(vcfFile);
+                return 1;
+            }
+
+            if (bcf_hrec_set_val(hrec, hrec->nkeys - 1, "Integer", strlen("Integer"), 0) < 0)
+            {
+                std::cerr << "Error: Cannot create VCF header contigs." << std::endl;
+                hts_close(vcfFile);
+                return 1;
+            }
+
+            if (bcf_hrec_add_key(hrec, "Description", strlen("Description")) < 0)
+            {
+                std::cerr << "Error: Cannot create VCF header contigs." << std::endl;
+                hts_close(vcfFile);
+                return 1;
+            }
+
+            if (bcf_hrec_set_val(hrec, hrec->nkeys - 1, "End coordinate of the variant", strlen("End coordinate of the variant"), 0) < 0)
+            {
+                std::cerr << "Error: Cannot create VCF header contigs." << std::endl;
+                hts_close(vcfFile);
+                return 1;
+            }
+
+            if (bcf_hdr_add_hrec(header, hrec) < 0)
+            {
+                std::cerr << "Error: Cannot create VCF header contigs." << std::endl;
+                hts_close(vcfFile);
+                return 1;
+            }
+        }
+
+        return 0;
     }
 
+    int set_header_info(bcf_hdr_t *header, htsFile *vcfFile)
+    {
 
+        // Set PS_START
+        {
+            bcf_hrec_t *hrec = (bcf_hrec_t *)calloc(1, sizeof(bcf_hrec_t));
+            hrec->key = strdup("INFO");
+            if (bcf_hrec_add_key(hrec, "ID", strlen("ID")) < 0)
+            {
+                std::cerr << "Error: Cannot create VCF header INFO" << std::endl;
+                hts_close(vcfFile);
+                return 1;
+            }
 
-    return 0;
-}
+            if (bcf_hrec_set_val(hrec, hrec->nkeys - 1, "PS_START", strlen("PS_START"), 0) < 0)
+            {
+                std::cerr << "Error: Cannot create VCF header INFO" << std::endl;
+                hts_close(vcfFile);
+                return 1;
+            }
+
+            if (bcf_hrec_add_key(hrec, "Number", strlen("Number")) < 0)
+            {
+                std::cerr << "Error: Cannot create VCF header INFO." << std::endl;
+                hts_close(vcfFile);
+                return 1;
+            }
+
+            if (bcf_hrec_set_val(hrec, hrec->nkeys - 1, "1", strlen("1"), 0) < 0)
+            {
+                std::cerr << "Error: Cannot create VCF header INFO." << std::endl;
+                hts_close(vcfFile);
+                return 1;
+            }
+
+            if (bcf_hrec_add_key(hrec, "Type", strlen("Type")) < 0)
+            {
+                std::cerr << "Error: Cannot create VCF header INFO." << std::endl;
+                hts_close(vcfFile);
+                return 1;
+            }
+
+            if (bcf_hrec_set_val(hrec, hrec->nkeys - 1, "Integer", strlen("Integer"), 0) < 0)
+            {
+                std::cerr << "Error: Cannot create VCF header INFO." << std::endl;
+                hts_close(vcfFile);
+                return 1;
+            }
+
+            if (bcf_hrec_add_key(hrec, "Description", strlen("Description")) < 0)
+            {
+                std::cerr << "Error: Cannot create VCF header INFO." << std::endl;
+                hts_close(vcfFile);
+                return 1;
+            }
+
+            if (bcf_hrec_set_val(hrec, hrec->nkeys - 1, "Indicate if a split-read has been found to identify the precise starting point of the  event",
+                                 strlen("Indicate if a split-read has been found to identify the precise starting point of the  event"), 0) < 0)
+            {
+                std::cerr << "Error: Cannot create VCF header INFO." << std::endl;
+                hts_close(vcfFile);
+                return 1;
+            }
+
+            if (bcf_hdr_add_hrec(header, hrec) < 0)
+            {
+                std::cerr << "Error: Cannot create VCF header INFO." << std::endl;
+                hts_close(vcfFile);
+                return 1;
+            }
+        }
+
+        // Set PS_STOP
+
+        {
+            bcf_hrec_t *hrec = (bcf_hrec_t *)calloc(1, sizeof(bcf_hrec_t));
+            hrec->key = strdup("INFO");
+            if (bcf_hrec_add_key(hrec, "ID", strlen("ID")) < 0)
+            {
+                std::cerr << "Error: Cannot create VCF header INFO" << std::endl;
+                hts_close(vcfFile);
+                return 1;
+            }
+
+            if (bcf_hrec_set_val(hrec, hrec->nkeys - 1, "PS_STOP", strlen("PS_STOP"), 0) < 0)
+            {
+                std::cerr << "Error: Cannot create VCF header INFO" << std::endl;
+                hts_close(vcfFile);
+                return 1;
+            }
+
+            if (bcf_hrec_add_key(hrec, "Number", strlen("Number")) < 0)
+            {
+                std::cerr << "Error: Cannot create VCF header INFO" << std::endl;
+                hts_close(vcfFile);
+                return 1;
+            }
+
+            if (bcf_hrec_set_val(hrec, hrec->nkeys - 1, "1", strlen("1"), 0) < 0)
+            {
+                std::cerr << "Error: Cannot create VCF header INFO" << std::endl;
+                hts_close(vcfFile);
+                return 1;
+            }
+
+            if (bcf_hrec_add_key(hrec, "Type", strlen("Type")) < 0)
+            {
+                std::cerr << "Error: Cannot create VCF header INFO" << std::endl;
+                hts_close(vcfFile);
+                return 1;
+            }
+
+            if (bcf_hrec_set_val(hrec, hrec->nkeys - 1, "Integer", strlen("Integer"), 0) < 0)
+            {
+                std::cerr << "Error: Cannot create VCF header INFO" << std::endl;
+                hts_close(vcfFile);
+                return 1;
+            }
+
+            if (bcf_hrec_add_key(hrec, "Description", strlen("Description")) < 0)
+            {
+                std::cerr << "Error: Cannot create VCF header INFO" << std::endl;
+                hts_close(vcfFile);
+                return 1;
+            }
+
+            if (bcf_hrec_set_val(hrec, hrec->nkeys - 1, "Indicate if a split-read has been found to identify the precise stop point of the  event",
+                                 strlen("Indicate if a split-read has been found to identify the precise stop point of the  event"), 0) < 0)
+            {
+                std::cerr << "Error: Cannot create VCF header INFO" << std::endl;
+                hts_close(vcfFile);
+                return 1;
+            }
+
+            if (bcf_hdr_add_hrec(header, hrec) < 0)
+            {
+                std::cerr << "Error: Cannot create VCF header INFO" << std::endl;
+                hts_close(vcfFile);
+                return 1;
+            }
+        }
+
+        return 0;
+    }
+
+    template <unsigned int N_sample_opt>
+    int create_vcf_calls(openfpm::vector<openfpm::vector<call_vcf>> &calls, openfpm::vector<std::string> &files_bams)
+    {
+
+        for (int i = 0; i < calls.size(); i++)
+        {
+            std::string str;
+            openfpm::vector<call_vcf> &cvcf = calls.get(i);
+
+            std::string sample_name = split(basename(files_bams.get(i).c_str()), ".")[0];
+
+            // Initialize VCF header and writer
+            htsFile *vcfFile = hts_open(std::string(sample_name + ".vcf").c_str(), "w");
+            if (vcfFile == nullptr)
+            {
+                std::cerr << "Error: Cannot open output VCF file" << std::endl;
+                return 1;
+            }
+
+            // Create a VCF header
+            bcf_hdr_t *header = bcf_hdr_init("w");
+            if (header == nullptr)
+            {
+                std::cerr << "Error: Cannot create VCF header." << std::endl;
+                hts_close(vcfFile);
+                return 1;
+            }
+
+            bcf_hdr_add_sample(header, sample_name.c_str());
+
+            set_header_assembly(header, vcfFile, "GRCh37");
+            set_header_format(header, vcfFile);
+            set_header_info(header, vcfFile);
+
+            // Add sample information to the header if needed
+            // bcf_hdr_add_sample(header, "Sample1");
+
+            // Write the VCF header to the output file
+            if (bcf_hdr_write(vcfFile, header) != 0)
+            {
+                std::cerr << "Error: Cannot write VCF header" << std::endl;
+                bcf_hdr_destroy(header);
+                hts_close(vcfFile);
+                return 1;
+            }
+
+            // Create a VCF record
+            bcf1_t *record = bcf_init1();
+            if (record == nullptr)
+            {
+                std::cerr << "Error: Cannot create VCF record" << std::endl;
+                bcf_hdr_destroy(header);
+                hts_close(vcfFile);
+                return 1;
+            }
+
+            for (int j = 0; j < cvcf.size(); j++)
+            {
+                std::stringstream ss;
+
+                ss << chr_int_to_chr(cvcf.get(j).chromosome + 1) << "\t";
+                ss << cvcf.get(j).start << "\t";
+                ss << "CNV_" << cvcf.get(j).chromosome << "_" << cvcf.get(j).start << "_" << cvcf.get(j).stop << "_" << cvcf.get(j).CN << "\t";
+                ss << "N" << "\t";
+                if (cvcf.get(j).CN < 2)
+                {
+                    ss << "<DEL>" << "\t";
+                }
+                else
+                {
+                    ss << "<DUP>" << "\t";
+                }
+
+                // QUALITY
+                ss << cvcf.get(j).quality << "\t";
+
+                // FILTER
+                ss << "." << "\t";
+
+                // INFO
+                std::string info;
+                if (cvcf.get(j).precise_start == true)
+                {
+                    info += "PS_START=1";
+                }
+                if (cvcf.get(j).precise_stop == true)
+                {
+                    if (info.size() != 0)
+                    {
+                        info += ";";
+                    }
+                    ss << "PS_STOP=1";
+                }
+                if (info.size() != 0)
+                {
+                    info += ";";
+                }
+                info += "END=" + std::to_string(cvcf.get(j).stop);
+
+                if (info.size() != 0)
+                {
+                    ss << info << "\t";
+                }
+                else
+                {
+                    ss << "." << "\t";
+                }
+
+                ss << "GT:CN:QS" << "\t";
+                if (cvcf.get(j).CN == 0)
+                {
+                    ss << "1/1";
+                }
+                else if (cvcf.get(j).CN == 1)
+                {
+                    ss << "0/1";
+                }
+                else
+                {
+                    ss << "./.";
+                }
+                ss << ":" << cvcf.get(j).CN << ":" << cvcf.get(j).quality;
+                kstring_t s;
+                ks_initialize(&s);
+                kputs(ss.str().c_str(), &s);
+                vcf_parse(&s, header, record);
+
+                if (bcf_write1(vcfFile, header, record) != 0)
+                {
+                    std::cerr << "Error: Cannot write VCF record" << std::endl;
+                }
+            }
+
+            // Clean up resources
+            bcf_destroy1(record);
+            bcf_hdr_destroy(header);
+            hts_close(vcfFile);
+        }
+
+        return 0;
+    }
 
 }
\ No newline at end of file
diff --git a/example/Sequencing/CNVcaller/testing.cpp b/example/Sequencing/CNVcaller/testing.cpp
index a0664974f..3f2a5f109 100644
--- a/example/Sequencing/CNVcaller/testing.cpp
+++ b/example/Sequencing/CNVcaller/testing.cpp
@@ -2,19 +2,19 @@
 #include <boost/test/unit_test.hpp>
 #include "functions.hpp"
 
-BOOST_AUTO_TEST_SUITE( CNV_caller_test_suite )
+BOOST_AUTO_TEST_SUITE(CNV_caller_test_suite)
 
-BOOST_AUTO_TEST_CASE( CNV_caller_test_read_CNV_hypothesys )
+BOOST_AUTO_TEST_CASE(CNV_caller_test_read_CNV_hypothesys)
 {
-  openfpm::vector<CNVcaller::call_vcf> calls_to_test;
-  CNVcaller::read_CNV_hypothesys("test/test_one_CNV.vcf.gz",calls_to_test);
+    openfpm::vector<CNVcaller::call_vcf> calls_to_test;
+    CNVcaller::read_CNV_hypothesys("test/test_one_CNV.vcf.gz", calls_to_test);
 
-  BOOST_REQUIRE_EQUAL(calls_to_test.get(0).chromosome,0);
-  BOOST_REQUIRE_EQUAL(calls_to_test.get(0).start,44605948);
-  BOOST_REQUIRE_EQUAL(calls_to_test.get(0).stop,44606030);
+    BOOST_REQUIRE_EQUAL(calls_to_test.get(0).chromosome, 0);
+    BOOST_REQUIRE_EQUAL(calls_to_test.get(0).start, 44605948);
+    BOOST_REQUIRE_EQUAL(calls_to_test.get(0).stop, 44606030);
 }
 
-BOOST_AUTO_TEST_CASE( CNV_caller_test_add_32bases_pattern )
+BOOST_AUTO_TEST_CASE(CNV_caller_test_add_32bases_pattern)
 {
     openfpm::vector<openfpm::vector<char>> reference;
     tsl::hopscotch_map<size_t, openfpm::vector<CNVcaller::CNV_event_link>> map;
@@ -22,34 +22,32 @@ BOOST_AUTO_TEST_CASE( CNV_caller_test_add_32bases_pattern )
     reference.load("reference_vector");
 
     // chromosome 0
-    add_32bases_pattern(0,44605910,reference,map,0,-1,NO_PADDING);
+    add_32bases_pattern(0, 44605910, reference, map, 0, -1, NO_PADDING);
 
-    BOOST_REQUIRE_EQUAL(map.size(),1);
+    BOOST_REQUIRE_EQUAL(map.size(), 1);
     auto i = map.begin();
-    BOOST_REQUIRE_EQUAL(i->first >> 62,0);
-    BOOST_REQUIRE_EQUAL(i->first & 0x3,3);
+    BOOST_REQUIRE_EQUAL(i->first >> 62, 0);
+    BOOST_REQUIRE_EQUAL(i->first & 0x3, 3);
 
-    BOOST_REQUIRE_EQUAL(i->second.size(),1);
+    BOOST_REQUIRE_EQUAL(i->second.size(), 1);
 
     BOOST_REQUIRE_EQUAL(i->second.get(0).padding_left, -1);
     BOOST_REQUIRE_EQUAL(i->second.get(0).padding_right, NO_PADDING);
 
     map.clear();
 
-    add_32bases_pattern(0,44605911,reference,map,1,-2,NO_PADDING);
+    add_32bases_pattern(0, 44605911, reference, map, 1, -2, NO_PADDING);
 
-    BOOST_REQUIRE_EQUAL(map.size(),1);
+    BOOST_REQUIRE_EQUAL(map.size(), 1);
     i = map.begin();
-    BOOST_REQUIRE_EQUAL(i->first >> 62,3);
-    BOOST_REQUIRE_EQUAL(i->first & 0x03,2);
-
-    
+    BOOST_REQUIRE_EQUAL(i->first >> 62, 3);
+    BOOST_REQUIRE_EQUAL(i->first & 0x03, 2);
 
     BOOST_REQUIRE_EQUAL(i->second.get(0).padding_left, -2);
     BOOST_REQUIRE_EQUAL(i->second.get(0).padding_right, NO_PADDING);
 }
 
-BOOST_AUTO_TEST_CASE( CNV_caller_test_add_32bases_pattern_with_variability )
+BOOST_AUTO_TEST_CASE(CNV_caller_test_add_32bases_pattern_with_variability)
 {
     openfpm::vector<openfpm::vector<char>> reference;
     tsl::hopscotch_map<size_t, openfpm::vector<CNVcaller::CNV_event_link>> map;
@@ -57,10 +55,10 @@ BOOST_AUTO_TEST_CASE( CNV_caller_test_add_32bases_pattern_with_variability )
     reference.load("reference_vector");
 
     // chromosome 0
-    add_32bases_pattern_with_variability(2,195452030,reference,map,"test/gnomad_variants.vcf.gz",0,-1,NO_PADDING);
+    add_32bases_pattern_with_variability(2, 195452030, reference, map, "test/gnomad_variants.vcf.gz", 0, -1, NO_PADDING);
+
+    BOOST_REQUIRE_EQUAL(map.size(), 8);
 
-    BOOST_REQUIRE_EQUAL(map.size(),8);
-    
     // check that these seed are presents
     std::string s1("TCATCACCCCGTCACGGGCCTCAGAGAGCAGC"); // reference
     std::string s2("TCATCACCCCCTCACGGGCCTCAGAGAGCAGC"); // variants
@@ -81,7 +79,6 @@ BOOST_AUTO_TEST_CASE( CNV_caller_test_add_32bases_pattern_with_variability )
     size_t s7_s = CNVcaller::convert_to_bit_pattern(s7.c_str());
     size_t s8_s = CNVcaller::convert_to_bit_pattern(s8.c_str());
 
-
     BOOST_REQUIRE(map.find(s1_s) != map.end());
     BOOST_REQUIRE(map.find(s2_s) != map.end());
     BOOST_REQUIRE(map.find(s3_s) != map.end());
@@ -93,15 +90,15 @@ BOOST_AUTO_TEST_CASE( CNV_caller_test_add_32bases_pattern_with_variability )
 
     // print all seeds in map
 
-/*    auto i = map.begin();
+    /*    auto i = map.begin();
 
-    while (i != map.end()) {
-      std::cout << CNVcaller::string_from_32bases_pattern(i->first) << std::endl;
-      i++;
-    }*/
+        while (i != map.end()) {
+          std::cout << CNVcaller::string_from_32bases_pattern(i->first) << std::endl;
+          i++;
+        }*/
 }
 
-BOOST_AUTO_TEST_CASE( CNV_caller_test_add_32bases_pattern_with_variability_range_shift )
+BOOST_AUTO_TEST_CASE(CNV_caller_test_add_32bases_pattern_with_variability_range_shift)
 {
     openfpm::vector<openfpm::vector<char>> reference;
     tsl::hopscotch_map<size_t, openfpm::vector<CNVcaller::CNV_event_link>> map;
@@ -109,204 +106,203 @@ BOOST_AUTO_TEST_CASE( CNV_caller_test_add_32bases_pattern_with_variability_range
     reference.load("reference_vector");
 
     // chromosome 3                                           // 195452062
-    add_32bases_pattern_with_variability_range_shift(2,195452030,195452062,8,reference,map,"test/gnomad_variants.vcf.gz",0,0,NO_PADDING);
+    add_32bases_pattern_with_variability_range_shift(2, 195452030, 195452062, 8, reference, map, "test/gnomad_variants.vcf.gz", 0, 0, NO_PADDING);
+
+    BOOST_REQUIRE_EQUAL(map.size(), 8 + 8 + 8 + 8 + 4);
 
-    BOOST_REQUIRE_EQUAL(map.size(),8+8+8+8+4);
-    
     // From 30
 
     {
-    // check that these seed are presents
-    std::string s1("TCATCACCCCGTCACGGGCCTCAGAGAGCAGC"); // reference
-    std::string s2("TCATCACCCCCTCACGGGCCTCAGAGAGCAGC"); // variants
-    std::string s3("TCATCACCCCGTCACGGGTCTCAGAGAGCAGC");
-    std::string s4("TCATCACCCCGTCACGGGCCTCAGAGCAGCGC"); // <--- indel
-    std::string s5("TCATCACCCCGTCACGGGCCTCAGAGAGCAGT");
-
-    std::string s6("TCATCACCCCCTCACGGGTCTCAGAGAGCAGC"); // 1-2
-    std::string s7("TCATCACCCCCTCACGGGCCTCAGAGAGCAGT"); // 1-4
-    std::string s8("TCATCACCCCGTCACGGGTCTCAGAGAGCAGT"); // 2-4
-
-    size_t s1_s = CNVcaller::convert_to_bit_pattern(s1.c_str());
-    size_t s2_s = CNVcaller::convert_to_bit_pattern(s2.c_str());
-    size_t s3_s = CNVcaller::convert_to_bit_pattern(s3.c_str());
-    size_t s4_s = CNVcaller::convert_to_bit_pattern(s4.c_str());
-    size_t s5_s = CNVcaller::convert_to_bit_pattern(s5.c_str());
-    size_t s6_s = CNVcaller::convert_to_bit_pattern(s6.c_str());
-    size_t s7_s = CNVcaller::convert_to_bit_pattern(s7.c_str());
-    size_t s8_s = CNVcaller::convert_to_bit_pattern(s8.c_str());
-
-    BOOST_REQUIRE(map.find(s1_s) != map.end());
-    BOOST_REQUIRE(map.find(s2_s) != map.end());
-    BOOST_REQUIRE(map.find(s3_s) != map.end());
-    BOOST_REQUIRE(map.find(s4_s) != map.end());
-    BOOST_REQUIRE(map.find(s5_s) != map.end());
-    BOOST_REQUIRE(map.find(s6_s) != map.end());
-    BOOST_REQUIRE(map.find(s7_s) != map.end());
-    BOOST_REQUIRE(map.find(s8_s) != map.end());
-
-    BOOST_REQUIRE(map.find(s1_s)->second.get(0).padding_left == 0);
-    BOOST_REQUIRE(map.find(s2_s)->second.get(0).padding_left == 0);
-    BOOST_REQUIRE(map.find(s3_s)->second.get(0).padding_left == 0);
-    BOOST_REQUIRE(map.find(s4_s)->second.get(0).padding_left == 0);
-    BOOST_REQUIRE(map.find(s5_s)->second.get(0).padding_left == 0);
-    BOOST_REQUIRE(map.find(s6_s)->second.get(0).padding_left == 0);
-    BOOST_REQUIRE(map.find(s7_s)->second.get(0).padding_left == 0);
-    BOOST_REQUIRE(map.find(s8_s)->second.get(0).padding_left == 0);
+        // check that these seed are presents
+        std::string s1("TCATCACCCCGTCACGGGCCTCAGAGAGCAGC"); // reference
+        std::string s2("TCATCACCCCCTCACGGGCCTCAGAGAGCAGC"); // variants
+        std::string s3("TCATCACCCCGTCACGGGTCTCAGAGAGCAGC");
+        std::string s4("TCATCACCCCGTCACGGGCCTCAGAGCAGCGC"); // <--- indel
+        std::string s5("TCATCACCCCGTCACGGGCCTCAGAGAGCAGT");
+
+        std::string s6("TCATCACCCCCTCACGGGTCTCAGAGAGCAGC"); // 1-2
+        std::string s7("TCATCACCCCCTCACGGGCCTCAGAGAGCAGT"); // 1-4
+        std::string s8("TCATCACCCCGTCACGGGTCTCAGAGAGCAGT"); // 2-4
+
+        size_t s1_s = CNVcaller::convert_to_bit_pattern(s1.c_str());
+        size_t s2_s = CNVcaller::convert_to_bit_pattern(s2.c_str());
+        size_t s3_s = CNVcaller::convert_to_bit_pattern(s3.c_str());
+        size_t s4_s = CNVcaller::convert_to_bit_pattern(s4.c_str());
+        size_t s5_s = CNVcaller::convert_to_bit_pattern(s5.c_str());
+        size_t s6_s = CNVcaller::convert_to_bit_pattern(s6.c_str());
+        size_t s7_s = CNVcaller::convert_to_bit_pattern(s7.c_str());
+        size_t s8_s = CNVcaller::convert_to_bit_pattern(s8.c_str());
+
+        BOOST_REQUIRE(map.find(s1_s) != map.end());
+        BOOST_REQUIRE(map.find(s2_s) != map.end());
+        BOOST_REQUIRE(map.find(s3_s) != map.end());
+        BOOST_REQUIRE(map.find(s4_s) != map.end());
+        BOOST_REQUIRE(map.find(s5_s) != map.end());
+        BOOST_REQUIRE(map.find(s6_s) != map.end());
+        BOOST_REQUIRE(map.find(s7_s) != map.end());
+        BOOST_REQUIRE(map.find(s8_s) != map.end());
+
+        BOOST_REQUIRE(map.find(s1_s)->second.get(0).padding_left == 0);
+        BOOST_REQUIRE(map.find(s2_s)->second.get(0).padding_left == 0);
+        BOOST_REQUIRE(map.find(s3_s)->second.get(0).padding_left == 0);
+        BOOST_REQUIRE(map.find(s4_s)->second.get(0).padding_left == 0);
+        BOOST_REQUIRE(map.find(s5_s)->second.get(0).padding_left == 0);
+        BOOST_REQUIRE(map.find(s6_s)->second.get(0).padding_left == 0);
+        BOOST_REQUIRE(map.find(s7_s)->second.get(0).padding_left == 0);
+        BOOST_REQUIRE(map.find(s8_s)->second.get(0).padding_left == 0);
     }
 
     // from 38
 
     // check that these seed are presents
     {
-    std::string s1("CCGTCACGGGCCTCAGAGAGCAGCGCCTCTTC"); // reference
-    std::string s2("CCCTCACGGGCCTCAGAGAGCAGCGCCTCTTC");
-    std::string s3("CCGTCACGGGTCTCAGAGAGCAGCGCCTCTTC");
-    std::string s4("CCGTCACGGGCCTCAGAGCAGCGCCTCTTCCG"); // <--- indel
-    std::string s5("CCGTCACGGGCCTCAGAGAGCAGTGCCTCTTC");
-
-    std::string s6("CCCTCACGGGTCTCAGAGAGCAGCGCCTCTTC"); // 1-2
-    std::string s7("CCCTCACGGGCCTCAGAGAGCAGTGCCTCTTC"); // 1-4
-    std::string s8("CCGTCACGGGTCTCAGAGAGCAGTGCCTCTTC"); // 2-4
-
-    size_t s1_s = CNVcaller::convert_to_bit_pattern(s1.c_str());
-    size_t s2_s = CNVcaller::convert_to_bit_pattern(s2.c_str());
-    size_t s3_s = CNVcaller::convert_to_bit_pattern(s3.c_str());
-    size_t s4_s = CNVcaller::convert_to_bit_pattern(s4.c_str());
-    size_t s5_s = CNVcaller::convert_to_bit_pattern(s5.c_str());
-    size_t s6_s = CNVcaller::convert_to_bit_pattern(s6.c_str());
-    size_t s7_s = CNVcaller::convert_to_bit_pattern(s7.c_str());
-    size_t s8_s = CNVcaller::convert_to_bit_pattern(s8.c_str());
-
-    BOOST_REQUIRE(map.find(s1_s) != map.end());
-    BOOST_REQUIRE(map.find(s2_s) != map.end());
-    BOOST_REQUIRE(map.find(s3_s) != map.end());
-    BOOST_REQUIRE(map.find(s4_s) != map.end());
-    BOOST_REQUIRE(map.find(s5_s) != map.end());
-    BOOST_REQUIRE(map.find(s6_s) != map.end());
-    BOOST_REQUIRE(map.find(s7_s) != map.end());
-    BOOST_REQUIRE(map.find(s8_s) != map.end());
-
-    BOOST_REQUIRE(map.find(s1_s)->second.get(0).padding_left == 8);
-    BOOST_REQUIRE(map.find(s2_s)->second.get(0).padding_left == 8);
-    BOOST_REQUIRE(map.find(s3_s)->second.get(0).padding_left == 8);
-    BOOST_REQUIRE(map.find(s4_s)->second.get(0).padding_left == 8);
-    BOOST_REQUIRE(map.find(s5_s)->second.get(0).padding_left == 8);
-    BOOST_REQUIRE(map.find(s6_s)->second.get(0).padding_left == 8);
-    BOOST_REQUIRE(map.find(s7_s)->second.get(0).padding_left == 8);
-    BOOST_REQUIRE(map.find(s8_s)->second.get(0).padding_left == 8);
+        std::string s1("CCGTCACGGGCCTCAGAGAGCAGCGCCTCTTC"); // reference
+        std::string s2("CCCTCACGGGCCTCAGAGAGCAGCGCCTCTTC");
+        std::string s3("CCGTCACGGGTCTCAGAGAGCAGCGCCTCTTC");
+        std::string s4("CCGTCACGGGCCTCAGAGCAGCGCCTCTTCCG"); // <--- indel
+        std::string s5("CCGTCACGGGCCTCAGAGAGCAGTGCCTCTTC");
+
+        std::string s6("CCCTCACGGGTCTCAGAGAGCAGCGCCTCTTC"); // 1-2
+        std::string s7("CCCTCACGGGCCTCAGAGAGCAGTGCCTCTTC"); // 1-4
+        std::string s8("CCGTCACGGGTCTCAGAGAGCAGTGCCTCTTC"); // 2-4
+
+        size_t s1_s = CNVcaller::convert_to_bit_pattern(s1.c_str());
+        size_t s2_s = CNVcaller::convert_to_bit_pattern(s2.c_str());
+        size_t s3_s = CNVcaller::convert_to_bit_pattern(s3.c_str());
+        size_t s4_s = CNVcaller::convert_to_bit_pattern(s4.c_str());
+        size_t s5_s = CNVcaller::convert_to_bit_pattern(s5.c_str());
+        size_t s6_s = CNVcaller::convert_to_bit_pattern(s6.c_str());
+        size_t s7_s = CNVcaller::convert_to_bit_pattern(s7.c_str());
+        size_t s8_s = CNVcaller::convert_to_bit_pattern(s8.c_str());
+
+        BOOST_REQUIRE(map.find(s1_s) != map.end());
+        BOOST_REQUIRE(map.find(s2_s) != map.end());
+        BOOST_REQUIRE(map.find(s3_s) != map.end());
+        BOOST_REQUIRE(map.find(s4_s) != map.end());
+        BOOST_REQUIRE(map.find(s5_s) != map.end());
+        BOOST_REQUIRE(map.find(s6_s) != map.end());
+        BOOST_REQUIRE(map.find(s7_s) != map.end());
+        BOOST_REQUIRE(map.find(s8_s) != map.end());
+
+        BOOST_REQUIRE(map.find(s1_s)->second.get(0).padding_left == 8);
+        BOOST_REQUIRE(map.find(s2_s)->second.get(0).padding_left == 8);
+        BOOST_REQUIRE(map.find(s3_s)->second.get(0).padding_left == 8);
+        BOOST_REQUIRE(map.find(s4_s)->second.get(0).padding_left == 8);
+        BOOST_REQUIRE(map.find(s5_s)->second.get(0).padding_left == 8);
+        BOOST_REQUIRE(map.find(s6_s)->second.get(0).padding_left == 8);
+        BOOST_REQUIRE(map.find(s7_s)->second.get(0).padding_left == 8);
+        BOOST_REQUIRE(map.find(s8_s)->second.get(0).padding_left == 8);
     }
 
     // from 46
     // check that these seed are presents
     {
-    std::string s1("GGCCTCAGAGAGCAGCGCCTCTTCCGACGGCC"); // reference
-    std::string s2("GGTCTCAGAGAGCAGCGCCTCTTCCGACGGCC");
-    std::string s3("GGCCTCAGAGCAGCGCCTCTTCCGACGGCCCC"); // <--- indel
-    std::string s4("GGCCTCAGAGAGCAGTGCCTCTTCCGACGGCC");
-    std::string s5("GGCCTCAGAGAGCAGCGCCTCTTCCGACAGCC");
-
-    std::string s6("GGTCTCAGAGAGCAGCGCCTCTTCCGACAGCC"); // 1-3
-    std::string s7("GGTCTCAGAGAGCAGTGCCTCTTCCGACGGCC"); // 1-4
-    std::string s8("GGCCTCAGAGAGCAGCGCCTCTTCCGACAGCC"); // 3-4
-
-    size_t s1_s = CNVcaller::convert_to_bit_pattern(s1.c_str());
-    size_t s2_s = CNVcaller::convert_to_bit_pattern(s2.c_str());
-    size_t s3_s = CNVcaller::convert_to_bit_pattern(s3.c_str());
-    size_t s4_s = CNVcaller::convert_to_bit_pattern(s4.c_str());
-    size_t s5_s = CNVcaller::convert_to_bit_pattern(s5.c_str());
-    size_t s6_s = CNVcaller::convert_to_bit_pattern(s6.c_str());
-    size_t s7_s = CNVcaller::convert_to_bit_pattern(s7.c_str());
-    size_t s8_s = CNVcaller::convert_to_bit_pattern(s8.c_str());
-
-    BOOST_REQUIRE(map.find(s1_s) != map.end());
-    BOOST_REQUIRE(map.find(s2_s) != map.end());
-    BOOST_REQUIRE(map.find(s3_s) != map.end());
-    BOOST_REQUIRE(map.find(s4_s) != map.end());
-    BOOST_REQUIRE(map.find(s5_s) != map.end());
-    BOOST_REQUIRE(map.find(s6_s) != map.end());
-    BOOST_REQUIRE(map.find(s7_s) != map.end());
-    BOOST_REQUIRE(map.find(s8_s) != map.end());
-
-    BOOST_REQUIRE(map.find(s1_s)->second.get(0).padding_left == 16);
-    BOOST_REQUIRE(map.find(s2_s)->second.get(0).padding_left == 16);
-    BOOST_REQUIRE(map.find(s3_s)->second.get(0).padding_left == 16);
-    BOOST_REQUIRE(map.find(s4_s)->second.get(0).padding_left == 16);
-    BOOST_REQUIRE(map.find(s5_s)->second.get(0).padding_left == 16);
-    BOOST_REQUIRE(map.find(s6_s)->second.get(0).padding_left == 16);
-    BOOST_REQUIRE(map.find(s7_s)->second.get(0).padding_left == 16);
-    BOOST_REQUIRE(map.find(s8_s)->second.get(0).padding_left == 16);
+        std::string s1("GGCCTCAGAGAGCAGCGCCTCTTCCGACGGCC"); // reference
+        std::string s2("GGTCTCAGAGAGCAGCGCCTCTTCCGACGGCC");
+        std::string s3("GGCCTCAGAGCAGCGCCTCTTCCGACGGCCCC"); // <--- indel
+        std::string s4("GGCCTCAGAGAGCAGTGCCTCTTCCGACGGCC");
+        std::string s5("GGCCTCAGAGAGCAGCGCCTCTTCCGACAGCC");
+
+        std::string s6("GGTCTCAGAGAGCAGCGCCTCTTCCGACAGCC"); // 1-3
+        std::string s7("GGTCTCAGAGAGCAGTGCCTCTTCCGACGGCC"); // 1-4
+        std::string s8("GGCCTCAGAGAGCAGCGCCTCTTCCGACAGCC"); // 3-4
+
+        size_t s1_s = CNVcaller::convert_to_bit_pattern(s1.c_str());
+        size_t s2_s = CNVcaller::convert_to_bit_pattern(s2.c_str());
+        size_t s3_s = CNVcaller::convert_to_bit_pattern(s3.c_str());
+        size_t s4_s = CNVcaller::convert_to_bit_pattern(s4.c_str());
+        size_t s5_s = CNVcaller::convert_to_bit_pattern(s5.c_str());
+        size_t s6_s = CNVcaller::convert_to_bit_pattern(s6.c_str());
+        size_t s7_s = CNVcaller::convert_to_bit_pattern(s7.c_str());
+        size_t s8_s = CNVcaller::convert_to_bit_pattern(s8.c_str());
+
+        BOOST_REQUIRE(map.find(s1_s) != map.end());
+        BOOST_REQUIRE(map.find(s2_s) != map.end());
+        BOOST_REQUIRE(map.find(s3_s) != map.end());
+        BOOST_REQUIRE(map.find(s4_s) != map.end());
+        BOOST_REQUIRE(map.find(s5_s) != map.end());
+        BOOST_REQUIRE(map.find(s6_s) != map.end());
+        BOOST_REQUIRE(map.find(s7_s) != map.end());
+        BOOST_REQUIRE(map.find(s8_s) != map.end());
+
+        BOOST_REQUIRE(map.find(s1_s)->second.get(0).padding_left == 16);
+        BOOST_REQUIRE(map.find(s2_s)->second.get(0).padding_left == 16);
+        BOOST_REQUIRE(map.find(s3_s)->second.get(0).padding_left == 16);
+        BOOST_REQUIRE(map.find(s4_s)->second.get(0).padding_left == 16);
+        BOOST_REQUIRE(map.find(s5_s)->second.get(0).padding_left == 16);
+        BOOST_REQUIRE(map.find(s6_s)->second.get(0).padding_left == 16);
+        BOOST_REQUIRE(map.find(s7_s)->second.get(0).padding_left == 16);
+        BOOST_REQUIRE(map.find(s8_s)->second.get(0).padding_left == 16);
     }
 
     // from 54
     // check that these seed are presents
     {
-    std::string s1("AGAGCAGCGCCTCTTCCGACGGCCCCCATCCA"); // reference
-    std::string s3("AGAGCAGTGCCTCTTCCGACGGCCCCCATCCA");
-    std::string s4("AGAGCAGCGCCTCTTCCGACAGCCCCCATCCA");
-    std::string s5("AGAGCAGCGCCTCTTCCGACGGCCTCCATCCA");
-
-    std::string s6("AGAGCAGTGCCTCTTCCGACAGCCCCCATCCA"); // 1-2
-    std::string s7("AGAGCAGTGCCTCTTCCGACGGCCTCCATCCA"); // 1-3
-    std::string s8("AGAGCAGCGCCTCTTCCGACAGCCTCCATCCA"); // 2-3
-
-    std::string s9("AGAGCAGTGCCTCTTCCGACAGCCTCCATCCA"); // 1-2-3
-
-    size_t s1_s = CNVcaller::convert_to_bit_pattern(s1.c_str());
-    size_t s3_s = CNVcaller::convert_to_bit_pattern(s3.c_str());
-    size_t s4_s = CNVcaller::convert_to_bit_pattern(s4.c_str());
-    size_t s5_s = CNVcaller::convert_to_bit_pattern(s5.c_str());
-    size_t s6_s = CNVcaller::convert_to_bit_pattern(s6.c_str());
-    size_t s7_s = CNVcaller::convert_to_bit_pattern(s7.c_str());
-    size_t s8_s = CNVcaller::convert_to_bit_pattern(s8.c_str());
-    size_t s9_s = CNVcaller::convert_to_bit_pattern(s9.c_str());
-
-    BOOST_REQUIRE(map.find(s1_s) != map.end());
-    BOOST_REQUIRE(map.find(s3_s) != map.end());
-    BOOST_REQUIRE(map.find(s4_s) != map.end());
-    BOOST_REQUIRE(map.find(s5_s) != map.end());
-    BOOST_REQUIRE(map.find(s6_s) != map.end());
-    BOOST_REQUIRE(map.find(s7_s) != map.end());
-    BOOST_REQUIRE(map.find(s8_s) != map.end());
-    BOOST_REQUIRE(map.find(s9_s) != map.end());
-
-    BOOST_REQUIRE(map.find(s1_s)->second.get(0).padding_left == 24);
-    BOOST_REQUIRE(map.find(s3_s)->second.get(0).padding_left == 24);
-    BOOST_REQUIRE(map.find(s4_s)->second.get(0).padding_left == 24);
-    BOOST_REQUIRE(map.find(s5_s)->second.get(0).padding_left == 24);
-    BOOST_REQUIRE(map.find(s6_s)->second.get(0).padding_left == 24);
-    BOOST_REQUIRE(map.find(s7_s)->second.get(0).padding_left == 24);
-    BOOST_REQUIRE(map.find(s8_s)->second.get(0).padding_left == 24);
+        std::string s1("AGAGCAGCGCCTCTTCCGACGGCCCCCATCCA"); // reference
+        std::string s3("AGAGCAGTGCCTCTTCCGACGGCCCCCATCCA");
+        std::string s4("AGAGCAGCGCCTCTTCCGACAGCCCCCATCCA");
+        std::string s5("AGAGCAGCGCCTCTTCCGACGGCCTCCATCCA");
+
+        std::string s6("AGAGCAGTGCCTCTTCCGACAGCCCCCATCCA"); // 1-2
+        std::string s7("AGAGCAGTGCCTCTTCCGACGGCCTCCATCCA"); // 1-3
+        std::string s8("AGAGCAGCGCCTCTTCCGACAGCCTCCATCCA"); // 2-3
+
+        std::string s9("AGAGCAGTGCCTCTTCCGACAGCCTCCATCCA"); // 1-2-3
+
+        size_t s1_s = CNVcaller::convert_to_bit_pattern(s1.c_str());
+        size_t s3_s = CNVcaller::convert_to_bit_pattern(s3.c_str());
+        size_t s4_s = CNVcaller::convert_to_bit_pattern(s4.c_str());
+        size_t s5_s = CNVcaller::convert_to_bit_pattern(s5.c_str());
+        size_t s6_s = CNVcaller::convert_to_bit_pattern(s6.c_str());
+        size_t s7_s = CNVcaller::convert_to_bit_pattern(s7.c_str());
+        size_t s8_s = CNVcaller::convert_to_bit_pattern(s8.c_str());
+        size_t s9_s = CNVcaller::convert_to_bit_pattern(s9.c_str());
+
+        BOOST_REQUIRE(map.find(s1_s) != map.end());
+        BOOST_REQUIRE(map.find(s3_s) != map.end());
+        BOOST_REQUIRE(map.find(s4_s) != map.end());
+        BOOST_REQUIRE(map.find(s5_s) != map.end());
+        BOOST_REQUIRE(map.find(s6_s) != map.end());
+        BOOST_REQUIRE(map.find(s7_s) != map.end());
+        BOOST_REQUIRE(map.find(s8_s) != map.end());
+        BOOST_REQUIRE(map.find(s9_s) != map.end());
+
+        BOOST_REQUIRE(map.find(s1_s)->second.get(0).padding_left == 24);
+        BOOST_REQUIRE(map.find(s3_s)->second.get(0).padding_left == 24);
+        BOOST_REQUIRE(map.find(s4_s)->second.get(0).padding_left == 24);
+        BOOST_REQUIRE(map.find(s5_s)->second.get(0).padding_left == 24);
+        BOOST_REQUIRE(map.find(s6_s)->second.get(0).padding_left == 24);
+        BOOST_REQUIRE(map.find(s7_s)->second.get(0).padding_left == 24);
+        BOOST_REQUIRE(map.find(s8_s)->second.get(0).padding_left == 24);
     }
 
     // from 62
     // check that these seed are presents
     {
-    std::string s1("GCCTCTTCCGACGGCCCCCATCCAGTCATCAC"); // reference
-    std::string s2("GCCTCTTCCGACAGCCCCCATCCAGTCATCAC");
-    std::string s3("GCCTCTTCCGACGGCCTCCATCCAGTCATCAC");
-
-    std::string s4("GCCTCTTCCGACAGCCTCCATCCAGTCATCAC"); // 1-2
-
-    size_t s1_s = CNVcaller::convert_to_bit_pattern(s1.c_str());
-    size_t s2_s = CNVcaller::convert_to_bit_pattern(s2.c_str());
-    size_t s3_s = CNVcaller::convert_to_bit_pattern(s3.c_str());
-    size_t s4_s = CNVcaller::convert_to_bit_pattern(s4.c_str());
-
-    BOOST_REQUIRE(map.find(s1_s) != map.end());
-    BOOST_REQUIRE(map.find(s2_s) != map.end());
-    BOOST_REQUIRE(map.find(s3_s) != map.end());
-    BOOST_REQUIRE(map.find(s4_s) != map.end());
-
-    BOOST_REQUIRE(map.find(s1_s)->second.get(0).padding_left == 32);
-    BOOST_REQUIRE(map.find(s2_s)->second.get(0).padding_left == 32);
-    BOOST_REQUIRE(map.find(s3_s)->second.get(0).padding_left == 32);
-    BOOST_REQUIRE(map.find(s4_s)->second.get(0).padding_left == 32);
-
+        std::string s1("GCCTCTTCCGACGGCCCCCATCCAGTCATCAC"); // reference
+        std::string s2("GCCTCTTCCGACAGCCCCCATCCAGTCATCAC");
+        std::string s3("GCCTCTTCCGACGGCCTCCATCCAGTCATCAC");
+
+        std::string s4("GCCTCTTCCGACAGCCTCCATCCAGTCATCAC"); // 1-2
+
+        size_t s1_s = CNVcaller::convert_to_bit_pattern(s1.c_str());
+        size_t s2_s = CNVcaller::convert_to_bit_pattern(s2.c_str());
+        size_t s3_s = CNVcaller::convert_to_bit_pattern(s3.c_str());
+        size_t s4_s = CNVcaller::convert_to_bit_pattern(s4.c_str());
+
+        BOOST_REQUIRE(map.find(s1_s) != map.end());
+        BOOST_REQUIRE(map.find(s2_s) != map.end());
+        BOOST_REQUIRE(map.find(s3_s) != map.end());
+        BOOST_REQUIRE(map.find(s4_s) != map.end());
+
+        BOOST_REQUIRE(map.find(s1_s)->second.get(0).padding_left == 32);
+        BOOST_REQUIRE(map.find(s2_s)->second.get(0).padding_left == 32);
+        BOOST_REQUIRE(map.find(s3_s)->second.get(0).padding_left == 32);
+        BOOST_REQUIRE(map.find(s4_s)->second.get(0).padding_left == 32);
     }
 }
 
-BOOST_AUTO_TEST_CASE( CNV_caller_test_add_32bases_pattern_with_variability_range_shift_big_del )
+BOOST_AUTO_TEST_CASE(CNV_caller_test_add_32bases_pattern_with_variability_range_shift_big_del)
 {
     openfpm::vector<openfpm::vector<char>> reference;
     tsl::hopscotch_map<size_t, openfpm::vector<CNVcaller::CNV_event_link>> map;
@@ -314,43 +310,41 @@ BOOST_AUTO_TEST_CASE( CNV_caller_test_add_32bases_pattern_with_variability_range
     reference.load("reference_vector");
 
     // chromosome 3                                           // 195452062
-    add_32bases_pattern_with_variability_range_shift(2,195452504,195452504+2,8,reference,map,"test/gnomad_variants_variability_test.vcf.gz",77,195452504-195451992+32,NO_PADDING);
+    add_32bases_pattern_with_variability_range_shift(2, 195452504, 195452504 + 2, 8, reference, map, "test/gnomad_variants_variability_test.vcf.gz", 77, 195452504 - 195451992 + 32, NO_PADDING);
+
+    BOOST_REQUIRE_EQUAL(map.size(), 5);
 
-    BOOST_REQUIRE_EQUAL(map.size(),5);
-    
     // From 30
 
     {
-    // check that these seed are presents
-    std::string s1("CCTCAGAGAGCAGCGCCTCTTCCGACGGCCTC"); // reference
-    std::string s2("CCTCTCAGAGAGCAGCGCCTCTTCCGACGGCC"); // variants
-    std::string s3("CCTCAGAGAGCAGCGCCTCTTCCGACATCCAG");
-    std::string s4("CCTCAGAGAGCAGCGCCTCTTCCGACAGCCTC");
-    std::string s5("CCTCAGAGAGCAGCGCCTCTTCCGACGGCCCC");
-
-
-    size_t s1_s = CNVcaller::convert_to_bit_pattern(s1.c_str());
-    size_t s2_s = CNVcaller::convert_to_bit_pattern(s2.c_str());
-    size_t s3_s = CNVcaller::convert_to_bit_pattern(s3.c_str());
-    size_t s4_s = CNVcaller::convert_to_bit_pattern(s4.c_str());
-    size_t s5_s = CNVcaller::convert_to_bit_pattern(s5.c_str());
-
-    BOOST_REQUIRE(map.find(s1_s) != map.end());
-    BOOST_REQUIRE(map.find(s2_s) != map.end());
-    BOOST_REQUIRE(map.find(s3_s) != map.end());
-    BOOST_REQUIRE(map.find(s4_s) != map.end());
-    BOOST_REQUIRE(map.find(s5_s) != map.end());
-
-
-    BOOST_REQUIRE_EQUAL(map.find(s1_s)->second.get(0).padding_left,544);
-    BOOST_REQUIRE_EQUAL(map.find(s2_s)->second.get(0).padding_left,544);
-    BOOST_REQUIRE_EQUAL(map.find(s3_s)->second.get(0).padding_left,544);
-    BOOST_REQUIRE_EQUAL(map.find(s4_s)->second.get(0).padding_left,544);
-    BOOST_REQUIRE_EQUAL(map.find(s5_s)->second.get(0).padding_left,544);
+        // check that these seed are presents
+        std::string s1("CCTCAGAGAGCAGCGCCTCTTCCGACGGCCTC"); // reference
+        std::string s2("CCTCTCAGAGAGCAGCGCCTCTTCCGACGGCC"); // variants
+        std::string s3("CCTCAGAGAGCAGCGCCTCTTCCGACATCCAG");
+        std::string s4("CCTCAGAGAGCAGCGCCTCTTCCGACAGCCTC");
+        std::string s5("CCTCAGAGAGCAGCGCCTCTTCCGACGGCCCC");
+
+        size_t s1_s = CNVcaller::convert_to_bit_pattern(s1.c_str());
+        size_t s2_s = CNVcaller::convert_to_bit_pattern(s2.c_str());
+        size_t s3_s = CNVcaller::convert_to_bit_pattern(s3.c_str());
+        size_t s4_s = CNVcaller::convert_to_bit_pattern(s4.c_str());
+        size_t s5_s = CNVcaller::convert_to_bit_pattern(s5.c_str());
+
+        BOOST_REQUIRE(map.find(s1_s) != map.end());
+        BOOST_REQUIRE(map.find(s2_s) != map.end());
+        BOOST_REQUIRE(map.find(s3_s) != map.end());
+        BOOST_REQUIRE(map.find(s4_s) != map.end());
+        BOOST_REQUIRE(map.find(s5_s) != map.end());
+
+        BOOST_REQUIRE_EQUAL(map.find(s1_s)->second.get(0).padding_left, 544);
+        BOOST_REQUIRE_EQUAL(map.find(s2_s)->second.get(0).padding_left, 544);
+        BOOST_REQUIRE_EQUAL(map.find(s3_s)->second.get(0).padding_left, 544);
+        BOOST_REQUIRE_EQUAL(map.find(s4_s)->second.get(0).padding_left, 544);
+        BOOST_REQUIRE_EQUAL(map.find(s5_s)->second.get(0).padding_left, 544);
     }
 }
 
-BOOST_AUTO_TEST_CASE( CNV_caller_test_32_bases_to_string )
+BOOST_AUTO_TEST_CASE(CNV_caller_test_32_bases_to_string)
 {
     openfpm::vector<openfpm::vector<char>> reference;
     tsl::hopscotch_map<size_t, openfpm::vector<CNVcaller::CNV_event_link>> map;
@@ -358,31 +352,30 @@ BOOST_AUTO_TEST_CASE( CNV_caller_test_32_bases_to_string )
     reference.load("reference_vector");
 
     // chromosome 0
-    add_32bases_pattern(0,44605910,reference,map,0,-1,NO_PADDING);
+    add_32bases_pattern(0, 44605910, reference, map, 0, -1, NO_PADDING);
 
     auto i = map.begin();
 
     std::string bases = CNVcaller::string_from_32bases_pattern(i->first);
     char seq[256];
-    CNVcaller::get_sequence(reference,0,44605910,44605942,-1,-1,seq);
+    CNVcaller::get_sequence(reference, 0, 44605910, 44605942, -1, -1, seq);
     std::string seq_str(seq);
 
-    BOOST_REQUIRE_EQUAL(bases,seq_str);
+    BOOST_REQUIRE_EQUAL(bases, seq_str);
 
     map.clear();
-    add_32bases_pattern(0,44605911,reference,map,1,-2,NO_PADDING);
+    add_32bases_pattern(0, 44605911, reference, map, 1, -2, NO_PADDING);
 
     i = map.begin();
 
     bases = CNVcaller::string_from_32bases_pattern(i->first);
-    CNVcaller::get_sequence(reference,0,44605911,44605943,-1,-1,seq);
+    CNVcaller::get_sequence(reference, 0, 44605911, 44605943, -1, -1, seq);
     seq_str = std::string(seq);
 
-    BOOST_REQUIRE_EQUAL(bases,seq_str);
-
+    BOOST_REQUIRE_EQUAL(bases, seq_str);
 }
 
-BOOST_AUTO_TEST_CASE( CNV_caller_test_get_Nbases_pattern )
+BOOST_AUTO_TEST_CASE(CNV_caller_test_get_Nbases_pattern)
 {
     openfpm::vector<openfpm::vector<char>> reference;
     tsl::hopscotch_map<size_t, openfpm::vector<CNVcaller::CNV_event_link>> map;
@@ -392,48 +385,48 @@ BOOST_AUTO_TEST_CASE( CNV_caller_test_get_Nbases_pattern )
     size_t seed = 0;
 
     // 1 base
-    CNVcaller::get_Nbases_pattern(0,44605910,reference,1,seed);
-    BOOST_REQUIRE_EQUAL(seed,0);
+    CNVcaller::get_Nbases_pattern(0, 44605910, reference, 1, seed);
+    BOOST_REQUIRE_EQUAL(seed, 0);
 
     // 1 base
-    CNVcaller::get_Nbases_pattern(0,44605911,reference,1,seed);
-    BOOST_REQUIRE_EQUAL(seed,3);
+    CNVcaller::get_Nbases_pattern(0, 44605911, reference, 1, seed);
+    BOOST_REQUIRE_EQUAL(seed, 3);
 
     // 1 base
-    CNVcaller::get_Nbases_pattern(0,44605912,reference,1,seed);
-    BOOST_REQUIRE_EQUAL(seed,15);
+    CNVcaller::get_Nbases_pattern(0, 44605912, reference, 1, seed);
+    BOOST_REQUIRE_EQUAL(seed, 15);
 
     seed = 0;
     // 1 base
-    CNVcaller::get_Nbases_pattern(0,44605911,reference,1,seed);
-    BOOST_REQUIRE_EQUAL(seed,3);
+    CNVcaller::get_Nbases_pattern(0, 44605911, reference, 1, seed);
+    BOOST_REQUIRE_EQUAL(seed, 3);
 
     // 1 base
-    CNVcaller::get_Nbases_pattern(0,44605911,reference,1,seed);
-    BOOST_REQUIRE_EQUAL(seed,15);
+    CNVcaller::get_Nbases_pattern(0, 44605911, reference, 1, seed);
+    BOOST_REQUIRE_EQUAL(seed, 15);
 
     seed = 0;
     // 2 base
-    CNVcaller::get_Nbases_pattern(0,44605911,reference,2,seed);
-    BOOST_REQUIRE_EQUAL(seed,15);
+    CNVcaller::get_Nbases_pattern(0, 44605911, reference, 2, seed);
+    BOOST_REQUIRE_EQUAL(seed, 15);
 
     seed = 0;
     // 3 base
-    CNVcaller::get_Nbases_pattern(0,44605910,reference,3,seed);
-    BOOST_REQUIRE_EQUAL(seed,15);
+    CNVcaller::get_Nbases_pattern(0, 44605910, reference, 3, seed);
+    BOOST_REQUIRE_EQUAL(seed, 15);
 
     seed = 0;
     // 9 bases
-    CNVcaller::get_Nbases_pattern(0,44605911,reference,9,seed);
-    BOOST_REQUIRE_EQUAL(seed & 0x03,2);
+    CNVcaller::get_Nbases_pattern(0, 44605911, reference, 9, seed);
+    BOOST_REQUIRE_EQUAL(seed & 0x03, 2);
 
     seed = 0;
     // 8 bases
-    CNVcaller::get_Nbases_pattern(0,44605911,reference,8,seed);
-    BOOST_REQUIRE_EQUAL(seed & 0x03,3);
+    CNVcaller::get_Nbases_pattern(0, 44605911, reference, 8, seed);
+    BOOST_REQUIRE_EQUAL(seed & 0x03, 3);
 }
 
-BOOST_AUTO_TEST_CASE( CNV_caller_test_add_32bases_pattern_with_gap )
+BOOST_AUTO_TEST_CASE(CNV_caller_test_add_32bases_pattern_with_gap)
 {
     openfpm::vector<openfpm::vector<char>> reference;
     tsl::hopscotch_map<size_t, openfpm::vector<CNVcaller::CNV_event_link>> map;
@@ -441,815 +434,860 @@ BOOST_AUTO_TEST_CASE( CNV_caller_test_add_32bases_pattern_with_gap )
     reference.load("reference_vector");
 
     // chromosome 0
-    CNVcaller::add_32bases_pattern_with_gap(0,44605910,reference,map,44605920,44605920,0,-1,NO_PADDING);
+    CNVcaller::add_32bases_pattern_with_gap(0, 44605910, reference, map, 44605920, 44605920, 0, -1, NO_PADDING);
 
-    BOOST_REQUIRE_EQUAL(map.size(),1);
+    BOOST_REQUIRE_EQUAL(map.size(), 1);
     auto i = map.begin();
-    BOOST_REQUIRE_EQUAL(i->first >> 62,0);
-    BOOST_REQUIRE_EQUAL(i->first & 0x3,3);
+    BOOST_REQUIRE_EQUAL(i->first >> 62, 0);
+    BOOST_REQUIRE_EQUAL(i->first & 0x3, 3);
 
-    BOOST_REQUIRE_EQUAL(i->second.size(),1);
+    BOOST_REQUIRE_EQUAL(i->second.size(), 1);
 
     BOOST_REQUIRE_EQUAL(i->second.get(0).padding_left, -1);
     BOOST_REQUIRE_EQUAL(i->second.get(0).padding_right, NO_PADDING);
 
     map.clear();
 
-    CNVcaller::add_32bases_pattern_with_gap(0,44605911,reference,map,44605920,44605930,1,-2,NO_PADDING);
+    CNVcaller::add_32bases_pattern_with_gap(0, 44605911, reference, map, 44605920, 44605930, 1, -2, NO_PADDING);
 
-    BOOST_REQUIRE_EQUAL(map.size(),1);
+    BOOST_REQUIRE_EQUAL(map.size(), 1);
     i = map.begin();
-    BOOST_REQUIRE_EQUAL(i->first >> 62,3);
-    BOOST_REQUIRE_EQUAL(i->first & 0x03,0);
+    BOOST_REQUIRE_EQUAL(i->first >> 62, 3);
+    BOOST_REQUIRE_EQUAL(i->first & 0x03, 0);
 
     BOOST_REQUIRE_EQUAL(i->second.get(0).padding_left, -2);
     BOOST_REQUIRE_EQUAL(i->second.get(0).padding_right, NO_PADDING);
 }
 
-BOOST_AUTO_TEST_CASE( CNV_caller_test_collect_reads_for_call_evidence )
+BOOST_AUTO_TEST_CASE(CNV_caller_test_collect_reads_for_call_evidence)
 {
-  openfpm::vector<openfpm::vector<char>> reference;
-  reference.load("reference_vector");
+    openfpm::vector<openfpm::vector<char>> reference;
+    reference.load("reference_vector");
 
-  openfpm::vector<CNVcaller::call_vcf> calls_to_test;
-  CNVcaller::read_CNV_hypothesys("test/test_one_CNV.vcf.gz",calls_to_test);
-  tsl::hopscotch_map<size_t, openfpm::vector<CNVcaller::CNV_event_link>> map;
+    openfpm::vector<CNVcaller::call_vcf> calls_to_test;
+    CNVcaller::read_CNV_hypothesys("test/test_one_CNV.vcf.gz", calls_to_test);
+    tsl::hopscotch_map<size_t, openfpm::vector<CNVcaller::CNV_event_link>> map;
 
-  All_samples_call_related_relevant_read_type seqs;
+    All_samples_call_related_relevant_read_type seqs;
 
-  // remeber is 0-based index, call id is 0
-  add_32bases_pattern(0,44605798,reference,map,0,-2,NO_PADDING);
+    // remeber is 0-based index, call id is 0
+    add_32bases_pattern(0, 44605798, reference, map, 0, -2, NO_PADDING);
 
-  seqs.resize(1);
+    seqs.resize(1);
 
-  std::string test_bam("test/HG002_one_read.bam");
-  collect_reads_for_call_evidence(test_bam,map,calls_to_test,seqs.get<0>(0),reference,6);
+    std::string test_bam("test/HG002_one_read.bam");
+    collect_reads_for_call_evidence(test_bam, map, calls_to_test, seqs.get<0>(0), reference, 6);
 
-  // Despite the read follow the seed, it is irrelevant for the call
-  BOOST_REQUIRE_EQUAL(seqs.get<0>(0).get<0>(0).size(),0);
+    // Despite the read follow the seed, it is irrelevant for the call
+    BOOST_REQUIRE_EQUAL(seqs.get<0>(0).get<0>(0).size(), 0);
 
-  // Reset
-  map.clear();
-  seqs.clear();
-  seqs.resize(1);
+    // Reset
+    map.clear();
+    seqs.clear();
+    seqs.resize(1);
 
-  // remeber is 0-based index, call id is 0
-  add_32bases_pattern(0,44605948-32,reference,map,0,0,NO_PADDING);
+    // remeber is 0-based index, call id is 0
+    add_32bases_pattern(0, 44605948 - 32, reference, map, 0, 0, NO_PADDING);
 
-  std::string test_bam2("test/HG002_one_read_cnv.bam");
-  collect_reads_for_call_evidence(test_bam2,map,calls_to_test,seqs.get<0>(0),reference,6);
+    std::string test_bam2("test/HG002_one_read_cnv.bam");
+    collect_reads_for_call_evidence(test_bam2, map, calls_to_test, seqs.get<0>(0), reference, 6);
 
-  // Despite the read follow the seed, it is irrelevant for the call
-  BOOST_REQUIRE_EQUAL(seqs.get<0>(0).get<0>(0).size(),1);
+    // Despite the read follow the seed, it is irrelevant for the call
+    BOOST_REQUIRE_EQUAL(seqs.get<0>(0).get<0>(0).size(), 1);
 
-  char sequence[] = "CGTCGTCTGCTCTCCACAGAGGGTCTGGTTACTAGTGGAGGTCATCACTTGCTCTCCACAGAGGTTCTGGTTACCAGTGGAGGTCATCATCTGCCCCCAGT";
+    char sequence[] = "CGTCGTCTGCTCTCCACAGAGGGTCTGGTTACTAGTGGAGGTCATCACTTGCTCTCCACAGAGGTTCTGGTTACCAGTGGAGGTCATCATCTGCCCCCAGT";
 
-  BOOST_REQUIRE_EQUAL(seqs.get<0>(0).get<0>(0).get<0>(0).size(),101);
+    BOOST_REQUIRE_EQUAL(seqs.get<0>(0).get<0>(0).get<0>(0).size(), 101);
 
-  for (int i = 0 ; i < 100 ; i++) {
-    BOOST_REQUIRE_EQUAL(sequence[i],seqs.get<0>(0).get<0>(0).get<0>(0).get<0>(i));
-  }
+    for (int i = 0; i < 100; i++)
+    {
+        BOOST_REQUIRE_EQUAL(sequence[i], seqs.get<0>(0).get<0>(0).get<0>(0).get<0>(i));
+    }
 
-  // Check the reverse read is detected
+    // Check the reverse read is detected
 
-  char sequence_rev[] = "GAGGTTGTCATCTGCTCTCCACAGAGGTTCTGGTTACCAGTGGAGGTCATCATCTGCCCCCAGTAGAGGGTCTGGTTACCAGTGGAGGTCATCATCTGCCC";
+    char sequence_rev[] = "GAGGTTGTCATCTGCTCTCCACAGAGGTTCTGGTTACCAGTGGAGGTCATCATCTGCCCCCAGTAGAGGGTCTGGTTACCAGTGGAGGTCATCATCTGCCC";
 
-  for (int i = 0 ; i < 100 ; i++) {
-    BOOST_REQUIRE_EQUAL(sequence_rev[i],seqs.get<0>(0).get<0>(0).get<0>(0).get<1>(i));
-  }
+    for (int i = 0; i < 100; i++)
+    {
+        BOOST_REQUIRE_EQUAL(sequence_rev[i], seqs.get<0>(0).get<0>(0).get<0>(0).get<1>(i));
+    }
 
-  // Read name
-  char read_name[] = "A00684:261:HNJK2DRX2:2:2228:29044:4194";
+    // Read name
+    char read_name[] = "A00684:261:HNJK2DRX2:2:2228:29044:4194";
 
-  for (int i = 0 ; i < sizeof(read_name) ; i++) {
-    BOOST_REQUIRE_EQUAL(read_name[i],seqs.get<0>(0).get<0>(0).get<0>(0).get<2>(i));
-  }
+    for (int i = 0; i < sizeof(read_name); i++)
+    {
+        BOOST_REQUIRE_EQUAL(read_name[i], seqs.get<0>(0).get<0>(0).get<0>(0).get<2>(i));
+    }
 
-  // Check chromosome 0 mean chr1
-  BOOST_REQUIRE_EQUAL(seqs.get<0>(0).get<0>(0).get<1>(0),0);
-  // Check seed position
-  BOOST_REQUIRE_EQUAL(seqs.get<0>(0).get<0>(0).get<4>(0),2);
+    // Check chromosome 0 mean chr1
+    BOOST_REQUIRE_EQUAL(seqs.get<0>(0).get<0>(0).get<1>(0), 0);
+    // Check seed position
+    BOOST_REQUIRE_EQUAL(seqs.get<0>(0).get<0>(0).get<4>(0), 2);
 
-  // Property 2 contain the position of the read in case the event is matched
-  BOOST_REQUIRE_EQUAL(seqs.get<0>(0).get<0>(0).get<2>(0),44605914);
+    // Property 2 contain the position of the read in case the event is matched
+    BOOST_REQUIRE_EQUAL(seqs.get<0>(0).get<0>(0).get<2>(0), 44605914);
 
-  // Reset
-  map.clear();
-  seqs.clear();
-  seqs.resize(1);
+    // Reset
+    map.clear();
+    seqs.clear();
+    seqs.resize(1);
 
-  // -1 is padding left (or start of the event)
-  add_32bases_pattern(0,44605947-32,reference,map,0,-1,NO_PADDING);
-  collect_reads_for_call_evidence(test_bam2,map,calls_to_test,seqs.get<0>(0),reference,6);
+    // -1 is padding left (or start of the event)
+    add_32bases_pattern(0, 44605947 - 32, reference, map, 0, -1, NO_PADDING);
+    collect_reads_for_call_evidence(test_bam2, map, calls_to_test, seqs.get<0>(0), reference, 6);
 
-  // Check seed position
-  BOOST_REQUIRE_EQUAL(seqs.get<0>(0).get<0>(0).get<4>(0),1);
+    // Check seed position
+    BOOST_REQUIRE_EQUAL(seqs.get<0>(0).get<0>(0).get<4>(0), 1);
 
-  // Property 2 contain the position of the read in case the event is matched
-  BOOST_REQUIRE_EQUAL(seqs.get<0>(0).get<0>(0).get<2>(0),44605914);
+    // Property 2 contain the position of the read in case the event is matched
+    BOOST_REQUIRE_EQUAL(seqs.get<0>(0).get<0>(0).get<2>(0), 44605914);
 }
 
-BOOST_AUTO_TEST_CASE( CNV_caller_test_get_reference_points )
+BOOST_AUTO_TEST_CASE(CNV_caller_test_get_reference_points)
 {
-  openfpm::vector<openfpm::vector<char>> reference;
-  reference.load("reference_vector");
+    openfpm::vector<openfpm::vector<char>> reference;
+    reference.load("reference_vector");
 
-  openfpm::vector<CNVcaller::call_vcf> calls_to_test;
-  CNVcaller::read_CNV_hypothesys("test/test_one_CNV.vcf.gz",calls_to_test);
+    openfpm::vector<CNVcaller::call_vcf> calls_to_test;
+    CNVcaller::read_CNV_hypothesys("test/test_one_CNV.vcf.gz", calls_to_test);
 
-  openfpm::vector<openfpm::vector<aggregate<short int, int, int>>> un_seed;
-  un_seed.resize(calls_to_test.size()+1);
+    openfpm::vector<openfpm::vector<aggregate<short int, int, int>>> un_seed;
+    un_seed.resize(calls_to_test.size() + 1);
 
-  tsl::hopscotch_map<size_t, openfpm::vector<CNVcaller::CNV_event_link>> map;
-  size_t bases_pattern;
-  int ret = CNVcaller::get_32bases_pattern(0,44605915,reference,bases_pattern); // create the seed number
+    tsl::hopscotch_map<size_t, openfpm::vector<CNVcaller::CNV_event_link>> map;
+    size_t bases_pattern;
+    int ret = CNVcaller::get_32bases_pattern(0, 44605915, reference, bases_pattern); // create the seed number
 
-  BOOST_REQUIRE_EQUAL(ret,0);
+    BOOST_REQUIRE_EQUAL(ret, 0);
 
-  CNVcaller::seed_pos sp;
-  sp.chr = 0; // chromosome 1
-  sp.pos = 44605915;
-  sp.cid = 1;
+    CNVcaller::seed_pos sp;
+    sp.chr = 0; // chromosome 1
+    sp.pos = 44605915;
+    sp.cid = 1;
 
-  openfpm::vector<CNVcaller::seed_id> seeds;
-  CNVcaller::seed_id seed;
-  seed.seed = bases_pattern;
-  seed.calls.add(sp);
-  seeds.add(seed);
+    openfpm::vector<CNVcaller::seed_id> seeds;
+    CNVcaller::seed_id seed;
+    seed.seed = bases_pattern;
+    seed.calls.add(sp);
+    seeds.add(seed);
 
-  // Add one seed for testing
-  CNVcaller::seed_id tmp;
+    // Add one seed for testing
+    CNVcaller::seed_id tmp;
 
-  get_reference_point(seeds,reference,un_seed);
+    get_reference_point(seeds, reference, un_seed);
 
-  // Check that across the suggested positions there is 
+    // Check that across the suggested positions there is
 
-  bool found = false;
+    bool found = false;
 
-  BOOST_REQUIRE_EQUAL(un_seed.size(),2);
+    BOOST_REQUIRE_EQUAL(un_seed.size(), 2);
 
-  for (int i = 0 ; i < un_seed.get(1).size() ; i++) {
-    if (un_seed.get(1).get<0>(i) == 0 &&
-        un_seed.get(1).get<1>(i) == 44605915 &&
-        un_seed.get(1).get<2>(i) == 0) {
-      
-      // Found the original seed point
-      found = true;
+    for (int i = 0; i < un_seed.get(1).size(); i++)
+    {
+        if (un_seed.get(1).get<0>(i) == 0 &&
+            un_seed.get(1).get<1>(i) == 44605915 &&
+            un_seed.get(1).get<2>(i) == 0)
+        {
 
-    } else {
-      // Check that the seed point generate the same sequence
+            // Found the original seed point
+            found = true;
+        }
+        else
+        {
+            // Check that the seed point generate the same sequence
 
-      for (int j = 0 ; j < 32 ; j++) {
-        char base = CNVcaller::get_base_from_reference(reference,0,44605915+j);
-        char base2 = CNVcaller::get_base_from_reference(reference,0,un_seed.get(1).get<1>(i)+j);
+            for (int j = 0; j < 32; j++)
+            {
+                char base = CNVcaller::get_base_from_reference(reference, 0, 44605915 + j);
+                char base2 = CNVcaller::get_base_from_reference(reference, 0, un_seed.get(1).get<1>(i) + j);
 
-        BOOST_REQUIRE_EQUAL(base,base2);
-      }
+                BOOST_REQUIRE_EQUAL(base, base2);
+            }
+        }
     }
-  }
 
-  BOOST_REQUIRE_EQUAL(found,true);
+    BOOST_REQUIRE_EQUAL(found, true);
 }
 
-BOOST_AUTO_TEST_CASE( CNV_caller_test_collect_and_test_read )
+BOOST_AUTO_TEST_CASE(CNV_caller_test_collect_and_test_read)
 {
-  openfpm::vector<openfpm::vector<char>> reference;
-  reference.load("reference_vector");
+    openfpm::vector<openfpm::vector<char>> reference;
+    reference.load("reference_vector");
 
-  openfpm::vector<CNVcaller::call_vcf> calls_to_test;
-  CNVcaller::read_CNV_hypothesys("test/test_one_CNV.vcf.gz",calls_to_test);
-  tsl::hopscotch_map<size_t, openfpm::vector<CNVcaller::CNV_event_link>> map;
+    openfpm::vector<CNVcaller::call_vcf> calls_to_test;
+    CNVcaller::read_CNV_hypothesys("test/test_one_CNV.vcf.gz", calls_to_test);
+    tsl::hopscotch_map<size_t, openfpm::vector<CNVcaller::CNV_event_link>> map;
 
-  All_samples_call_related_relevant_read_type seqs;
+    All_samples_call_related_relevant_read_type seqs;
 
-  // remeber is 0-based index, call id is 0, padding between call-start and seed is -1
-  int offset = -1;
-  add_32bases_pattern(0,calls_to_test.get(0).start-32+offset,reference,map,0,offset,NO_PADDING);
+    // remeber is 0-based index, call id is 0, padding between call-start and seed is -1
+    int offset = -1;
+    add_32bases_pattern(0, calls_to_test.get(0).start - 32 + offset, reference, map, 0, offset, NO_PADDING);
 
-  seqs.resize(1);
+    seqs.resize(1);
 
-  std::string test_bam("test/HG002_one_read_cnv.bam");
-  collect_reads_for_call_evidence(test_bam,map,calls_to_test,seqs.get<0>(0),reference,6,0);
+    std::string test_bam("test/HG002_one_read_cnv.bam");
+    collect_reads_for_call_evidence(test_bam, map, calls_to_test, seqs.get<0>(0), reference, 6, 0);
 
-  // Here we should have one read collected for call zero
+    // Here we should have one read collected for call zero
 
-  BOOST_REQUIRE_EQUAL(seqs.get<0>(0).size(),1);
+    BOOST_REQUIRE_EQUAL(seqs.get<0>(0).size(), 1);
 
-  // The read is not relevant for the reference
-  BOOST_REQUIRE_EQUAL(seqs.get<0>(0).get<0>(0).size(),1);
+    // The read is not relevant for the reference
+    BOOST_REQUIRE_EQUAL(seqs.get<0>(0).get<0>(0).size(), 1);
 }
 
-BOOST_AUTO_TEST_CASE( CNV_caller_test_collect_and_test_read_multiple_read_multiple_calls )
+BOOST_AUTO_TEST_CASE(CNV_caller_test_collect_and_test_read_multiple_read_multiple_calls)
 {
-  openfpm::vector<openfpm::vector<char>> reference;
-  reference.load("reference_vector");
-
-  openfpm::vector<CNVcaller::call_vcf> calls_to_test;
-  CNVcaller::read_CNV_hypothesys("test/test_multiple_CNV_8shift.vcf.gz",calls_to_test);
-  tsl::hopscotch_map<size_t, openfpm::vector<CNVcaller::CNV_event_link>> map;
+    openfpm::vector<openfpm::vector<char>> reference;
+    reference.load("reference_vector");
 
-  All_samples_call_related_relevant_read_type seqs;
+    openfpm::vector<CNVcaller::call_vcf> calls_to_test;
+    CNVcaller::read_CNV_hypothesys("test/test_multiple_CNV_8shift.vcf.gz", calls_to_test);
+    tsl::hopscotch_map<size_t, openfpm::vector<CNVcaller::CNV_event_link>> map;
 
-  // remeber is 0-based index, call id is 0, padding between call-start and seed is -1
-  int offset = 0;
-  add_32bases_pattern(2,112743123-32,reference,map,0,0,NO_PADDING);
-  // padding from the start of the call to the end of the seed is 112751315-112743114+32
-  add_32bases_pattern(2,112751322,reference,map,0,112751322-112743123+32,NO_PADDING);
-  CNVcaller::add_32bases_pattern_with_gap(2, // Chromosome 3
-                                          calls_to_test.get(0).start-16, // position where to take the seed
-                                          reference, // reference
-                                          map, // hashmap where to add the seed
-                                          calls_to_test.get(0).start, // starting point of the gap
-                                          calls_to_test.get(0).stop,  // end point of the gap
-                                          0, // call id
-                                          16, // padding of the end of the seed from the start of the call (without considering the gap)
-                                          NO_PADDING);
-  add_32bases_pattern(2,195451991-32,reference,map,1,0,NO_PADDING);
-  // call start at 645514
-  add_32bases_pattern(3,64508-32,reference,map,2,-5,NO_PADDING);
+    All_samples_call_related_relevant_read_type seqs;
 
+    // remeber is 0-based index, call id is 0, padding between call-start and seed is -1
+    int offset = 0;
+    add_32bases_pattern(2, 112743123 - 32, reference, map, 0, 0, NO_PADDING);
+    // padding from the start of the call to the end of the seed is 112751315-112743114+32
+    add_32bases_pattern(2, 112751322, reference, map, 0, 112751322 - 112743123 + 32, NO_PADDING);
+    CNVcaller::add_32bases_pattern_with_gap(2,                               // Chromosome 3
+                                            calls_to_test.get(0).start - 16, // position where to take the seed
+                                            reference,                       // reference
+                                            map,                             // hashmap where to add the seed
+                                            calls_to_test.get(0).start,      // starting point of the gap
+                                            calls_to_test.get(0).stop,       // end point of the gap
+                                            0,                               // call id
+                                            16,                              // padding of the end of the seed from the start of the call (without considering the gap)
+                                            NO_PADDING);
+    add_32bases_pattern(2, 195451991 - 32, reference, map, 1, 0, NO_PADDING);
+    // call start at 645514
+    add_32bases_pattern(3, 64508 - 32, reference, map, 2, -5, NO_PADDING);
 
-  seqs.resize(3);
+    seqs.resize(3);
 
-  std::string test_bam("test/HG002_3calls_reads_cnv.bam");
-  collect_reads_for_call_evidence(test_bam,map,calls_to_test,seqs.get<0>(0),reference,6,0);
+    std::string test_bam("test/HG002_3calls_reads_cnv.bam");
+    collect_reads_for_call_evidence(test_bam, map, calls_to_test, seqs.get<0>(0), reference, 6, 0);
 
-  // Call 0 has 3 reads paired
-  BOOST_REQUIRE_EQUAL(seqs.get<0>(0).size(),3);
+    // Call 0 has 3 reads paired
+    BOOST_REQUIRE_EQUAL(seqs.get<0>(0).size(), 3);
 
-  // 4 reads for call zero
-  BOOST_REQUIRE_EQUAL(seqs.get<0>(0).get<0>(0).size(),4);
+    // 4 reads for call zero
+    BOOST_REQUIRE_EQUAL(seqs.get<0>(0).get<0>(0).size(), 4);
 
-  // 4 read for call 0
-  BOOST_REQUIRE_EQUAL(seqs.get<0>(0).get<0>(0).get<0>(0).size(),101);
-  BOOST_REQUIRE_EQUAL(seqs.get<0>(0).get<0>(0).get<0>(1).size(),99);
-  BOOST_REQUIRE_EQUAL(seqs.get<0>(0).get<0>(0).get<0>(2).size(),100);
-  BOOST_REQUIRE_EQUAL(seqs.get<0>(0).get<0>(0).get<0>(3).size(),101);
+    // 4 read for call 0
+    BOOST_REQUIRE_EQUAL(seqs.get<0>(0).get<0>(0).get<0>(0).size(), 101);
+    BOOST_REQUIRE_EQUAL(seqs.get<0>(0).get<0>(0).get<0>(1).size(), 99);
+    BOOST_REQUIRE_EQUAL(seqs.get<0>(0).get<0>(0).get<0>(2).size(), 100);
+    BOOST_REQUIRE_EQUAL(seqs.get<0>(0).get<0>(0).get<0>(3).size(), 101);
 
-  // 1 reads for call 1
-  BOOST_REQUIRE_EQUAL(seqs.get<0>(0).get<0>(1).size(),1);
+    // 1 reads for call 1
+    BOOST_REQUIRE_EQUAL(seqs.get<0>(0).get<0>(1).size(), 1);
 
-  // 1 read for call 1
-  BOOST_REQUIRE_EQUAL(seqs.get<0>(0).get<0>(1).get<0>(0).size(),101);
+    // 1 read for call 1
+    BOOST_REQUIRE_EQUAL(seqs.get<0>(0).get<0>(1).get<0>(0).size(), 101);
 
-  // 0 reads for call 2
-  BOOST_REQUIRE_EQUAL(seqs.get<0>(0).get<0>(2).size(),0);
+    // 0 reads for call 2
+    BOOST_REQUIRE_EQUAL(seqs.get<0>(0).get<0>(2).size(), 0);
 
-  // we relax to 1 base missmatch
+    // we relax to 1 base missmatch
 
-  seqs.resize(0);
-  seqs.resize(3);
+    seqs.resize(0);
+    seqs.resize(3);
 
-  collect_reads_for_call_evidence(test_bam,map,calls_to_test,seqs.get<0>(0),reference,6,1);
+    collect_reads_for_call_evidence(test_bam, map, calls_to_test, seqs.get<0>(0), reference, 6, 1);
 
-  // Call 0 has 3 reads paired
-  BOOST_REQUIRE_EQUAL(seqs.get<0>(0).size(),3);
+    // Call 0 has 3 reads paired
+    BOOST_REQUIRE_EQUAL(seqs.get<0>(0).size(), 3);
 
-  // 4 reads for call zero
-  BOOST_REQUIRE_EQUAL(seqs.get<0>(0).get<0>(0).size(),4);
+    // 4 reads for call zero
+    BOOST_REQUIRE_EQUAL(seqs.get<0>(0).get<0>(0).size(), 4);
 
-  // 4 read for call 0
-  BOOST_REQUIRE_EQUAL(seqs.get<0>(0).get<0>(0).get<0>(0).size(),101);
-  BOOST_REQUIRE_EQUAL(seqs.get<0>(0).get<0>(0).get<0>(1).size(),99);
-  BOOST_REQUIRE_EQUAL(seqs.get<0>(0).get<0>(0).get<0>(2).size(),100);
-  BOOST_REQUIRE_EQUAL(seqs.get<0>(0).get<0>(0).get<0>(3).size(),101);
+    // 4 read for call 0
+    BOOST_REQUIRE_EQUAL(seqs.get<0>(0).get<0>(0).get<0>(0).size(), 101);
+    BOOST_REQUIRE_EQUAL(seqs.get<0>(0).get<0>(0).get<0>(1).size(), 99);
+    BOOST_REQUIRE_EQUAL(seqs.get<0>(0).get<0>(0).get<0>(2).size(), 100);
+    BOOST_REQUIRE_EQUAL(seqs.get<0>(0).get<0>(0).get<0>(3).size(), 101);
 
-  // 1 reads for call 1
-  BOOST_REQUIRE_EQUAL(seqs.get<0>(0).get<0>(1).size(),3);
+    // 1 reads for call 1
+    BOOST_REQUIRE_EQUAL(seqs.get<0>(0).get<0>(1).size(), 3);
 
-  // 1 read for call 1
-  BOOST_REQUIRE_EQUAL(seqs.get<0>(0).get<0>(1).get<0>(0).size(),101);
-  BOOST_REQUIRE_EQUAL(seqs.get<0>(0).get<0>(1).get<0>(1).size(),101);
-  BOOST_REQUIRE_EQUAL(seqs.get<0>(0).get<0>(1).get<0>(2).size(),101);
+    // 1 read for call 1
+    BOOST_REQUIRE_EQUAL(seqs.get<0>(0).get<0>(1).get<0>(0).size(), 101);
+    BOOST_REQUIRE_EQUAL(seqs.get<0>(0).get<0>(1).get<0>(1).size(), 101);
+    BOOST_REQUIRE_EQUAL(seqs.get<0>(0).get<0>(1).get<0>(2).size(), 101);
 
-  // 0 reads for call 2
-  BOOST_REQUIRE_EQUAL(seqs.get<0>(0).get<0>(2).size(),1);
+    // 0 reads for call 2
+    BOOST_REQUIRE_EQUAL(seqs.get<0>(0).get<0>(2).size(), 1);
 
-  // 0 read for call 2
-  BOOST_REQUIRE_EQUAL(seqs.get<0>(0).get<0>(2).get<0>(0).size(),101);
+    // 0 read for call 2
+    BOOST_REQUIRE_EQUAL(seqs.get<0>(0).get<0>(2).get<0>(0).size(), 101);
 }
 
-BOOST_AUTO_TEST_CASE( CNV_caller_tests_calculate_event_probability_between_to_sequences )
+BOOST_AUTO_TEST_CASE(CNV_caller_tests_calculate_event_probability_between_to_sequences)
 {
-  openfpm::vector<openfpm::vector<char>> reference;
-  reference.load("reference_vector");
+    openfpm::vector<openfpm::vector<char>> reference;
+    reference.load("reference_vector");
 
-  openfpm::vector<CNVcaller::call_vcf> calls_to_test;
-  CNVcaller::read_CNV_hypothesys("test/test_multiple_CNV_8shift.vcf.gz",calls_to_test);
+    openfpm::vector<CNVcaller::call_vcf> calls_to_test;
+    CNVcaller::read_CNV_hypothesys("test/test_multiple_CNV_8shift.vcf.gz", calls_to_test);
 
-  // chromosome 3 position 112743032
-  int chr = 2;
-  int pos = 112743032;
+    // chromosome 3 position 112743032
+    int chr = 2;
+    int pos = 112743032;
 
-  auto call = calls_to_test.get(0);
+    auto call = calls_to_test.get(0);
 
-  char seq1[16384];
-  char seq2[] = "ATTGGTGACAGAGAGATGCAGGATCAAGAAGAGTATTGTTTTGTTTTGTTCTGATTTTAAGGATAGTTTACTAGTCAGGATTCCACCAGCCTGTAGGGGTG";
+    char seq1[16384];
+    char seq2[] = "ATTGGTGACAGAGAGATGCAGGATCAAGAAGAGTATTGTTTTGTTTTGTTCTGATTTTAAGGATAGTTTACTAGTCAGGATTCCACCAGCCTGTAGGGGTG";
 
-  CNVcaller::get_sequence(reference,chr,pos,pos+sizeof(seq2)+(call.stop-call.start),call.start,call.stop,seq1);
+    CNVcaller::get_sequence(reference, chr, pos, pos + sizeof(seq2) + (call.stop - call.start), call.start, call.stop, seq1);
 
-  double probability = CNVcaller::calculate_event_probability_between_to_sequences(seq2,seq1,3e-3);
-  BOOST_REQUIRE_CLOSE(-0.30345541,probability,0.01);
+    double probability = CNVcaller::calculate_event_probability_between_to_sequences(seq2, seq1, 3e-3);
+    BOOST_REQUIRE_CLOSE(-0.30345541, probability, 0.01);
 
-  char seq4[] = "ATTGGTGACAGAGAGATGCAGGATCAAGAAGAGTATTGTTTTGTTTTGTTCTTATTTTAAGGATAGTTTACTAGTCAGGATTCCACCAGCCTGTAGGGGTG";
-  probability = CNVcaller::calculate_event_probability_between_to_sequences(seq4,seq1,3e-3);
-  BOOST_REQUIRE_CLOSE(-6.10959389234,probability,0.01);
+    char seq4[] = "ATTGGTGACAGAGAGATGCAGGATCAAGAAGAGTATTGTTTTGTTTTGTTCTTATTTTAAGGATAGTTTACTAGTCAGGATTCCACCAGCCTGTAGGGGTG";
+    probability = CNVcaller::calculate_event_probability_between_to_sequences(seq4, seq1, 3e-3);
+    BOOST_REQUIRE_CLOSE(-6.10959389234, probability, 0.01);
 
-  std::cout << "Probability: " << probability << std::endl;
+    std::cout << "Probability: " << probability << std::endl;
 }
 
-BOOST_AUTO_TEST_CASE( CNV_caller_tests_calculate_event_probability )
+BOOST_AUTO_TEST_CASE(CNV_caller_tests_calculate_event_probability)
 {
-  openfpm::vector<openfpm::vector<char>> reference;
-  reference.load("reference_vector");
-
-  openfpm::vector<double> bp_insert_prob;
-  bp_insert_prob.load("insert_probability_distribution");
+    openfpm::vector<openfpm::vector<char>> reference;
+    reference.load("reference_vector");
 
-  openfpm::vector<CNVcaller::call_vcf> calls_to_test;
-  CNVcaller::read_CNV_hypothesys("test/test_multiple_CNV_8shift.vcf.gz",calls_to_test);
+    openfpm::vector<double> bp_insert_prob;
+    bp_insert_prob.load("insert_probability_distribution");
 
-  // chromosome 3 position 112743032
-  int chr = 2;
-  int pos = 112743032;
+    openfpm::vector<CNVcaller::call_vcf> calls_to_test;
+    CNVcaller::read_CNV_hypothesys("test/test_multiple_CNV_8shift.vcf.gz", calls_to_test);
 
-  auto call = calls_to_test.get(0);
+    // chromosome 3 position 112743032
+    int chr = 2;
+    int pos = 112743032;
 
-  char seq1[16384];
-  char seq2[] = "ATTGGTGACAGAGAGATGCAGGATCAAGAAGAGTATTGTTTTGTTTTGTTCTGATTTTAAGGATAGTTTACTAGTCAGGATTCCACCAGCCTGTAGGGGTG";
-  char seq3[] = "ATGCAGGATCAAGAAGAGTATTGTTTTGTTTTGTTCTGATTTTAAGGATAGTTTACTAGTCAGGATTCCACCAGCCTGTAGGGGTGGGTTGCCCCTACACA";
+    auto call = calls_to_test.get(0);
 
-  CNVcaller::get_sequence(reference,chr,pos,pos+sizeof(seq2)+(call.stop-call.start),call.start,call.stop,seq1);
+    char seq1[16384];
+    char seq2[] = "ATTGGTGACAGAGAGATGCAGGATCAAGAAGAGTATTGTTTTGTTTTGTTCTGATTTTAAGGATAGTTTACTAGTCAGGATTCCACCAGCCTGTAGGGGTG";
+    char seq3[] = "ATGCAGGATCAAGAAGAGTATTGTTTTGTTTTGTTCTGATTTTAAGGATAGTTTACTAGTCAGGATTCCACCAGCCTGTAGGGGTGGGTTGCCCCTACACA";
 
+    CNVcaller::get_sequence(reference, chr, pos, pos + sizeof(seq2) + (call.stop - call.start), call.start, call.stop, seq1);
 
-  openfpm::vector<int> chr_ins;
-  chr_ins.resize(23);
+    openfpm::vector<int> chr_ins;
+    chr_ins.resize(23);
 
-  for (int i = 0 ; i < chr_ins.size(); i++) {
-    chr_ins.get(i) = 210;
-  }
+    for (int i = 0; i < chr_ins.size(); i++)
+    {
+        chr_ins.get(i) = 210;
+    }
 
-  CNVcaller::ProbsRead probs;
-  int best_insert;
-  CNVcaller::calculate_event_probability(seq2,seq1,seq3,-1,chr,pos,3e-3,chr_ins,reference,best_insert,bp_insert_prob,probs);
-  double probability = probs.log_align_probability + probs.log_pair_probability + probs.log_insert_probability;
+    CNVcaller::ProbsRead probs;
+    int best_insert;
+    CNVcaller::calculate_event_probability(seq2, seq1, seq3, -1, chr, pos, 3e-3, chr_ins, reference, best_insert, bp_insert_prob, probs);
+    double probability = probs.log_align_probability + probs.log_pair_probability + probs.log_insert_probability;
 
-  BOOST_REQUIRE_CLOSE(probability,-13.923319055604425,0.001);
+    BOOST_REQUIRE_CLOSE(probability, -13.923319055604425, 0.001);
 }
 
-BOOST_AUTO_TEST_CASE( CNV_caller_evidence_insert_size_for_sample )
+BOOST_AUTO_TEST_CASE(CNV_caller_evidence_insert_size_for_sample)
 {
-  openfpm::vector<int> bp_insert;
-  openfpm::vector<double> bp_insert_prob;
+    openfpm::vector<int> bp_insert;
+    openfpm::vector<double> bp_insert_prob;
 
-  char bam_file[] = "/nvme/bams/batch_1/DE78NGSUKBD134462_76322.bam";
+    char bam_file[] = "/nvme/bams/batch_1/DE78NGSUKBD134462_76322.bam";
 
-  samFile *fp_in = hts_open(bam_file,"r"); //open bam file
+    samFile *fp_in = hts_open(bam_file, "r"); // open bam file
 
-  if (fp_in == 0x0) {
-    std::cerr << __FILE__ << ":" << __LINE__ << " Error opening the file " << bam_file << std::endl;
-    return;
-  }
+    if (fp_in == 0x0)
+    {
+        std::cerr << __FILE__ << ":" << __LINE__ << " Error opening the file " << bam_file << std::endl;
+        return;
+    }
 
-  size_t tot_pair = 0;
+    size_t tot_pair = 0;
 
-  bam_hdr_t *bamHdr = sam_hdr_read(fp_in); //read header
-  bam1_t *aln = bam_init1(); //initialize an alignment
+    bam_hdr_t *bamHdr = sam_hdr_read(fp_in); // read header
+    bam1_t *aln = bam_init1();               // initialize an alignment
 
-  while(sam_read1(fp_in,bamHdr,aln) > 0){
+    while (sam_read1(fp_in, bamHdr, aln) > 0)
+    {
 
-    if (aln->core.tid == -1)
-    {continue;}
+        if (aln->core.tid == -1)
+        {
+            continue;
+        }
 
-    char *chr = bamHdr->target_name[aln->core.tid];
+        char *chr = bamHdr->target_name[aln->core.tid];
 
-    short int chr_int = CNVcaller::chr_to_chr_int(chr);
-    if (chr_int == -1)  {continue;}
+        short int chr_int = CNVcaller::chr_to_chr_int(chr);
+        if (chr_int == -1)
+        {
+            continue;
+        }
 
-    if (aln->core.isize < 0) {continue;}
+        if (aln->core.isize < 0)
+        {
+            continue;
+        }
 
-    if (abs(aln->core.isize) >= bp_insert.size() ) {
-      int prev_size = bp_insert.size();
-      bp_insert.resize(abs(aln->core.isize)+1);
-      for (int i = prev_size ; i < bp_insert.size() ; i++) {
-        bp_insert.get(i) = 0;
-      }
+        if (abs(aln->core.isize) >= bp_insert.size())
+        {
+            int prev_size = bp_insert.size();
+            bp_insert.resize(abs(aln->core.isize) + 1);
+            for (int i = prev_size; i < bp_insert.size(); i++)
+            {
+                bp_insert.get(i) = 0;
+            }
+        }
+        bp_insert.get(abs(aln->core.isize)) += 1;
+        tot_pair++;
     }
-    bp_insert.get(abs(aln->core.isize)) += 1;
-    tot_pair++;
-	}
-	
-	bam_destroy1(aln);
-	sam_close(fp_in);
-
-  bp_insert_prob.resize(bp_insert.size());
-
-  for (int i = 0 ; i < bp_insert.size() ; i++) {
-    if (bp_insert.get(i) == 0) {
-      bp_insert_prob.get(i) = 1.0 / tot_pair;
-    } else {
-      bp_insert_prob.get(i) = (double)bp_insert.get(i) / tot_pair;
+
+    bam_destroy1(aln);
+    sam_close(fp_in);
+
+    bp_insert_prob.resize(bp_insert.size());
+
+    for (int i = 0; i < bp_insert.size(); i++)
+    {
+        if (bp_insert.get(i) == 0)
+        {
+            bp_insert_prob.get(i) = 1.0 / tot_pair;
+        }
+        else
+        {
+            bp_insert_prob.get(i) = (double)bp_insert.get(i) / tot_pair;
+        }
     }
-  }
 
-  bp_insert_prob.save("insert_probability_distribution");
+    bp_insert_prob.save("insert_probability_distribution");
 }
 
-BOOST_AUTO_TEST_CASE( CNV_caller_evidence_probability_for_each_event )
+BOOST_AUTO_TEST_CASE(CNV_caller_evidence_probability_for_each_event)
 {
-  openfpm::vector<openfpm::vector<char>> reference;
-  reference.load("reference_vector");
-
-  openfpm::vector<CNVcaller::call_vcf> calls_to_test;
-  CNVcaller::read_CNV_hypothesys("test/test_multiple_CNV_8shift.vcf.gz",calls_to_test);
-  tsl::hopscotch_map<size_t, openfpm::vector<CNVcaller::CNV_event_link>> map;
-
-  All_samples_call_related_relevant_read_type seqs;
-
-  // remeber is 0-based index, call id is 0, padding between call-start and seed is -1
-  int offset = 0;
-  // seed 46...
-  size_t a = add_32bases_pattern(2,112743123-32,reference,map,0,0,NO_PADDING);
-  std::cout << "Seed call 0: " << CNVcaller::string_from_32bases_pattern(a) << std::endl;
-
-  // seed 133...
-  // padding from the start of the call to the end of the seed is 112751315-112743114+32
-  a = add_32bases_pattern(2,112751322,reference,map,0,112751322-112743123+32,NO_PADDING);
-  std::cout << "Seed call 0: " << CNVcaller::string_from_32bases_pattern(a) << std::endl;
-
-  // seed 
-  a = CNVcaller::add_32bases_pattern_with_gap(2, // Chromosome 3
-                                          calls_to_test.get(0).start-16, // position where to take the seed
-                                          reference, // reference
-                                          map, // hashmap where to add the seed
-                                          calls_to_test.get(0).start, // starting point of the gap
-                                          calls_to_test.get(0).stop,  // end point of the gap
-                                          0, // call id
-                                          16, // padding of the end of the seed from the start of the call (without considering the gap)
-                                          NO_PADDING);
-  std::cout << "Seed call 0: " << CNVcaller::string_from_32bases_pattern(a) << std::endl;
-
-  // call id 1
-  a = add_32bases_pattern(2,195451991-32,reference,map,1,0,NO_PADDING);
-  std::cout << "Seed call 1: " << CNVcaller::string_from_32bases_pattern(a) << std::endl;
-  a = add_32bases_pattern(2,195452447,reference,map,1,195452447-195451991+32,NO_PADDING);
-  std::cout << "Seed call 1: " << CNVcaller::string_from_32bases_pattern(a) << std::endl;
-  // call id 2 call start at 645514
-  a = add_32bases_pattern(3,64508-32,reference,map,2,-5,NO_PADDING);
-  std::cout << "Seed call 2: " << CNVcaller::string_from_32bases_pattern(a) << std::endl;
-
-
-  seqs.resize(3);
-
-  std::string test_bam("test/HG002_3calls_reads_cnv_sort.bam");
-  collect_reads_for_call_evidence(test_bam,map,calls_to_test,seqs.get<0>(0),reference,6,3);
-
-  // We check that all read are coupled, for all elements in the map
-
-  for (int i = 0 ; i < seqs.size() ; i++) {
-    for (int j = 0 ; j < seqs.get<0>(i).size() ; j++) {
-      for (int k = 0 ; k < seqs.get<0>(i).get<0>(j).size() ; k++) {
-        auto & pair = seqs.get<0>(i).get<0>(j).get<0>(k);
-        BOOST_REQUIRE((pair.get<1>(3) == 'A' || pair.get<1>(3) == 'C' || pair.get<1>(3) == 'T' || pair.get<1>(3) == 'G'));
-      }
-    }
-  }
-
-  openfpm::vector<CNVcaller::seed_id> seed;
-  convert_seed_map_to_array(seed,map,calls_to_test);
+    openfpm::vector<openfpm::vector<char>> reference;
+    reference.load("reference_vector");
 
-  // Find all reference points
-  openfpm::vector<openfpm::vector<aggregate<short int, int, int>>> un_seed;
-//  un_seed.resize(calls_to_test.size());
-//  get_reference_point(seed,reference,un_seed);
-  un_seed.load("test/unseed_3calls_cnv");
+    openfpm::vector<CNVcaller::call_vcf> calls_to_test;
+    CNVcaller::read_CNV_hypothesys("test/test_multiple_CNV_8shift.vcf.gz", calls_to_test);
+    tsl::hopscotch_map<size_t, openfpm::vector<CNVcaller::CNV_event_link>> map;
 
+    All_samples_call_related_relevant_read_type seqs;
+
+    // remeber is 0-based index, call id is 0, padding between call-start and seed is -1
+    int offset = 0;
+    // seed 46...
+    size_t a = add_32bases_pattern(2, 112743123 - 32, reference, map, 0, 0, NO_PADDING);
+    std::cout << "Seed call 0: " << CNVcaller::string_from_32bases_pattern(a) << std::endl;
+
+    // seed 133...
+    // padding from the start of the call to the end of the seed is 112751315-112743114+32
+    a = add_32bases_pattern(2, 112751322, reference, map, 0, 112751322 - 112743123 + 32, NO_PADDING);
+    std::cout << "Seed call 0: " << CNVcaller::string_from_32bases_pattern(a) << std::endl;
+
+    // seed
+    a = CNVcaller::add_32bases_pattern_with_gap(2,                               // Chromosome 3
+                                                calls_to_test.get(0).start - 16, // position where to take the seed
+                                                reference,                       // reference
+                                                map,                             // hashmap where to add the seed
+                                                calls_to_test.get(0).start,      // starting point of the gap
+                                                calls_to_test.get(0).stop,       // end point of the gap
+                                                0,                               // call id
+                                                16,                              // padding of the end of the seed from the start of the call (without considering the gap)
+                                                NO_PADDING);
+    std::cout << "Seed call 0: " << CNVcaller::string_from_32bases_pattern(a) << std::endl;
+
+    // call id 1
+    a = add_32bases_pattern(2, 195451991 - 32, reference, map, 1, 0, NO_PADDING);
+    std::cout << "Seed call 1: " << CNVcaller::string_from_32bases_pattern(a) << std::endl;
+    a = add_32bases_pattern(2, 195452447, reference, map, 1, 195452447 - 195451991 + 32, NO_PADDING);
+    std::cout << "Seed call 1: " << CNVcaller::string_from_32bases_pattern(a) << std::endl;
+    // call id 2 call start at 645514
+    a = add_32bases_pattern(3, 64508 - 32, reference, map, 2, -5, NO_PADDING);
+    std::cout << "Seed call 2: " << CNVcaller::string_from_32bases_pattern(a) << std::endl;
+
+    seqs.resize(3);
+
+    std::string test_bam("test/HG002_3calls_reads_cnv_sort.bam");
+    collect_reads_for_call_evidence(test_bam, map, calls_to_test, seqs.get<0>(0), reference, 6, 3);
+
+    // We check that all read are coupled, for all elements in the map
+
+    for (int i = 0; i < seqs.size(); i++)
+    {
+        for (int j = 0; j < seqs.get<0>(i).size(); j++)
+        {
+            for (int k = 0; k < seqs.get<0>(i).get<0>(j).size(); k++)
+            {
+                auto &pair = seqs.get<0>(i).get<0>(j).get<0>(k);
+                BOOST_REQUIRE((pair.get<1>(3) == 'A' || pair.get<1>(3) == 'C' || pair.get<1>(3) == 'T' || pair.get<1>(3) == 'G'));
+            }
+        }
+    }
 
-  // Calculate evidence for each of the read pair
+    openfpm::vector<CNVcaller::seed_id> seed;
+    convert_seed_map_to_array(seed, map, calls_to_test);
 
-  int seed_pos = seqs.get<0>(0).get<0>(0).get<4>(0);
-  openfpm::vector<int> chr_ins;
-  chr_ins.resize(23);
+    // Find all reference points
+    openfpm::vector<openfpm::vector<aggregate<short int, int, int>>> un_seed;
+    //  un_seed.resize(calls_to_test.size());
+    //  get_reference_point(seed,reference,un_seed);
+    un_seed.load("test/unseed_3calls_cnv");
 
-  for (int i = 0 ; i < chr_ins.size(); i++) {
-    chr_ins.get(i) = 210;
-  }
+    // Calculate evidence for each of the read pair
 
-  // Load insert size probability
-  
-  openfpm::vector<double> bp_insert_prob;
-  bp_insert_prob.load("insert_probability_distribution");
+    int seed_pos = seqs.get<0>(0).get<0>(0).get<4>(0);
+    openfpm::vector<int> chr_ins;
+    chr_ins.resize(23);
 
-  // Get the seed number associated to the call
-  int seed_num = 0;
+    for (int i = 0; i < chr_ins.size(); i++)
+    {
+        chr_ins.get(i) = 210;
+    }
 
-  // For rach read
-  for (int j = 0 ; j < seqs.get<0>(0).size() ; j++) {
-    for (int i = 0 ; i < seqs.get<0>(0).get<0>(j).size() ; i++) {
+    // Load insert size probability
 
-      seed_pos = seqs.get<0>(0).get<0>(j).get<4>(i);
+    openfpm::vector<double> bp_insert_prob;
+    bp_insert_prob.load("insert_probability_distribution");
 
-      Eigen::ArrayXd insert;
-      Eigen::ArrayXd eml3 = Evidence_matrix_log(reference,
-                                                seqs.get<0>(0).get<0>(j).get<0>(i),
-                                                un_seed.get(j),
-                                                calls_to_test.get(j),
-                                                -6,
-                                                seqs.get<0>(0).get<0>(j).get<1>(i),
-                                                seqs.get<0>(0).get<0>(j).get<2>(i),
-                                                seed_pos,
-                                                chr_ins,
-                                                insert,
-                                                bp_insert_prob);
+    // Get the seed number associated to the call
+    int seed_num = 0;
 
-      std::cout << "Probability: " << eml3 << std::endl;
+    // For rach read
+    for (int j = 0; j < seqs.get<0>(0).size(); j++)
+    {
+        for (int i = 0; i < seqs.get<0>(0).get<0>(j).size(); i++)
+        {
 
-      BOOST_REQUIRE(eml3(59) > -20.0 );
-      BOOST_REQUIRE(eml3(126) > -20.0);
+            seed_pos = seqs.get<0>(0).get<0>(j).get<4>(i);
+
+            Eigen::ArrayXd insert;
+            Eigen::ArrayXd eml3 = Evidence_matrix_log(reference,
+                                                      seqs.get<0>(0).get<0>(j).get<0>(i),
+                                                      un_seed.get(j),
+                                                      calls_to_test.get(j),
+                                                      -6,
+                                                      seqs.get<0>(0).get<0>(j).get<1>(i),
+                                                      seqs.get<0>(0).get<0>(j).get<2>(i),
+                                                      seed_pos,
+                                                      chr_ins,
+                                                      insert,
+                                                      bp_insert_prob);
+
+            std::cout << "Probability: " << eml3 << std::endl;
+
+            BOOST_REQUIRE(eml3(59) > -20.0);
+            BOOST_REQUIRE(eml3(126) > -20.0);
+        }
     }
-  }
-
-
 }
 
-
-BOOST_AUTO_TEST_CASE( CNV_caller_evidence_probability_for_each_event_with_variability )
+BOOST_AUTO_TEST_CASE(CNV_caller_evidence_probability_for_each_event_with_variability)
 {
-  openfpm::vector<openfpm::vector<char>> reference;
-  reference.load("reference_vector");
+    openfpm::vector<openfpm::vector<char>> reference;
+    reference.load("reference_vector");
 
-  openfpm::vector<CNVcaller::call_vcf> calls_to_test;
-  CNVcaller::read_CNV_hypothesys("test/test_multiple_CNV_MUC20.vcf.gz",calls_to_test);
-  tsl::hopscotch_map<size_t, openfpm::vector<CNVcaller::CNV_event_link>> map;
+    openfpm::vector<CNVcaller::call_vcf> calls_to_test;
+    CNVcaller::read_CNV_hypothesys("test/test_multiple_CNV_MUC20.vcf.gz", calls_to_test);
+    tsl::hopscotch_map<size_t, openfpm::vector<CNVcaller::CNV_event_link>> map;
 
-  All_samples_call_related_relevant_read_type seqs;
+    All_samples_call_related_relevant_read_type seqs;
 
-  // remeber is 0-based index, call id is 0, padding between call-start and seed is -1
-  int offset = 0;
+    // remeber is 0-based index, call id is 0, padding between call-start and seed is -1
+    int offset = 0;
 
-  // call id 1
-  add_32bases_pattern_with_variability(2,195452561,reference,map,"test/gnomad_variants_variability_test.vcf.gz",1,195452561-195451991+32,NO_PADDING);
+    // call id 1
+    add_32bases_pattern_with_variability(2, 195452561, reference, map, "test/gnomad_variants_variability_test.vcf.gz", 1, 195452561 - 195451991 + 32, NO_PADDING);
 
-  auto i = map.begin();
+    auto i = map.begin();
 
-  while (i != map.end()) {
-    std::cout << CNVcaller::string_from_32bases_pattern(i->first) << std::endl;
-    i++;
-  }
+    while (i != map.end())
+    {
+        std::cout << CNVcaller::string_from_32bases_pattern(i->first) << std::endl;
+        i++;
+    }
 
-  seqs.resize(3);
+    seqs.resize(3);
 
-  std::string test_bam("test/HG002_3calls_reads_cnv_sort.bam");
-  collect_reads_for_call_evidence(test_bam,map,calls_to_test,seqs.get<0>(0),reference,6,3);
+    std::string test_bam("test/HG002_3calls_reads_cnv_sort.bam");
+    collect_reads_for_call_evidence(test_bam, map, calls_to_test, seqs.get<0>(0), reference, 6, 3);
 
-  // We check that all read are coupled, for all elements in the map
+    // We check that all read are coupled, for all elements in the map
 
-  for (int i = 0 ; i < seqs.size() ; i++) {
-    for (int j = 0 ; j < seqs.get<0>(i).size() ; j++) {
-      for (int k = 0 ; k < seqs.get<0>(i).get<0>(j).size() ; k++) {
-        auto & pair = seqs.get<0>(i).get<0>(j).get<0>(k);
-        BOOST_REQUIRE((pair.get<1>(3) == 'A' || pair.get<1>(3) == 'C' || pair.get<1>(3) == 'T' || pair.get<1>(3) == 'G'));
-      }
+    for (int i = 0; i < seqs.size(); i++)
+    {
+        for (int j = 0; j < seqs.get<0>(i).size(); j++)
+        {
+            for (int k = 0; k < seqs.get<0>(i).get<0>(j).size(); k++)
+            {
+                auto &pair = seqs.get<0>(i).get<0>(j).get<0>(k);
+                BOOST_REQUIRE((pair.get<1>(3) == 'A' || pair.get<1>(3) == 'C' || pair.get<1>(3) == 'T' || pair.get<1>(3) == 'G'));
+            }
+        }
     }
-  }
-
-  openfpm::vector<CNVcaller::seed_id> seed;
-  convert_seed_map_to_array(seed,map,calls_to_test);
-
-  // Find all reference points
-  openfpm::vector<openfpm::vector<aggregate<short int, int, int>>> un_seed;
-//  un_seed.resize(calls_to_test.size());
-//  get_reference_point(seed,reference,un_seed);
-  un_seed.load("test/unseed_3calls_cnv_variability");
 
-  // Calculate evidence for each of the read pair
+    openfpm::vector<CNVcaller::seed_id> seed;
+    convert_seed_map_to_array(seed, map, calls_to_test);
 
-  openfpm::vector<int> chr_ins;
-  chr_ins.resize(23);
+    // Find all reference points
+    openfpm::vector<openfpm::vector<aggregate<short int, int, int>>> un_seed;
+    //  un_seed.resize(calls_to_test.size());
+    //  get_reference_point(seed,reference,un_seed);
+    un_seed.load("test/unseed_3calls_cnv_variability");
 
-  for (int i = 0 ; i < chr_ins.size(); i++) {
-    chr_ins.get(i) = 210;
-  }
+    // Calculate evidence for each of the read pair
 
-  // Load insert size probability
-  
-  openfpm::vector<double> bp_insert_prob;
-  bp_insert_prob.load("insert_probability_distribution");
+    openfpm::vector<int> chr_ins;
+    chr_ins.resize(23);
 
-  // Get the seed number associated to the call
-  int seed_num = 0;
+    for (int i = 0; i < chr_ins.size(); i++)
+    {
+        chr_ins.get(i) = 210;
+    }
 
-  // For rach read
-  for (int j = 0 ; j < seqs.get<0>(0).size() ; j++) {
-    for (int i = 0 ; i < seqs.get<0>(0).get<0>(j).size() ; i++) {
+    // Load insert size probability
 
-      std::cout << "j " << j << "/" << seqs.get<0>(0).size() << "   i " << "/" << seqs.get<0>(0).get<0>(j).size() << std::endl;
+    openfpm::vector<double> bp_insert_prob;
+    bp_insert_prob.load("insert_probability_distribution");
 
-      size_t seed_pos = seqs.get<0>(0).get<0>(j).get<4>(i);
+    // Get the seed number associated to the call
+    int seed_num = 0;
 
-      Eigen::ArrayXd insert;
-      Eigen::ArrayXd eml3 = Evidence_matrix_log(reference,
-                                                seqs.get<0>(0).get<0>(j).get<0>(i),
-                                                un_seed.get(j),
-                                                calls_to_test.get(j),
-                                                6,
-                                                seqs.get<0>(0).get<0>(j).get<1>(i),
-                                                seqs.get<0>(0).get<0>(j).get<2>(i),
-                                                seed_pos,
-                                                chr_ins,
-                                                insert,
-                                                bp_insert_prob);
+    // For rach read
+    for (int j = 0; j < seqs.get<0>(0).size(); j++)
+    {
+        for (int i = 0; i < seqs.get<0>(0).get<0>(j).size(); i++)
+        {
 
-      BOOST_REQUIRE(eml3(59) > -20.0 );
-      BOOST_REQUIRE(eml3(121) < -20.0);
+            std::cout << "j " << j << "/" << seqs.get<0>(0).size() << "   i " << "/" << seqs.get<0>(0).get<0>(j).size() << std::endl;
+
+            size_t seed_pos = seqs.get<0>(0).get<0>(j).get<4>(i);
+
+            Eigen::ArrayXd insert;
+            Eigen::ArrayXd eml3 = Evidence_matrix_log(reference,
+                                                      seqs.get<0>(0).get<0>(j).get<0>(i),
+                                                      un_seed.get(j),
+                                                      calls_to_test.get(j),
+                                                      6,
+                                                      seqs.get<0>(0).get<0>(j).get<1>(i),
+                                                      seqs.get<0>(0).get<0>(j).get<2>(i),
+                                                      seed_pos,
+                                                      chr_ins,
+                                                      insert,
+                                                      bp_insert_prob);
+
+            BOOST_REQUIRE(eml3(59) > -20.0);
+            BOOST_REQUIRE(eml3(121) < -20.0);
+        }
     }
-  }
-
-
 }
 
 // Many read events
-BOOST_AUTO_TEST_CASE( CNV_caller_evidence_probability_for_each_event_with_variability_many_reads )
+BOOST_AUTO_TEST_CASE(CNV_caller_evidence_probability_for_each_event_with_variability_many_reads)
 {
-  openfpm::vector<openfpm::vector<char>> reference;
-  reference.load("reference_vector");
-
-  openfpm::vector<CNVcaller::call_vcf> calls_to_test;
-  CNVcaller::read_CNV_hypothesys("test/DGV_variants_MUC20.vcf.gz",calls_to_test);
-  tsl::hopscotch_map<size_t, openfpm::vector<CNVcaller::CNV_event_link>> map;
+    openfpm::vector<openfpm::vector<char>> reference;
+    reference.load("reference_vector");
 
-  All_samples_call_related_relevant_read_type seqs;
+    openfpm::vector<CNVcaller::call_vcf> calls_to_test;
+    CNVcaller::read_CNV_hypothesys("test/DGV_variants_MUC20.vcf.gz", calls_to_test);
+    tsl::hopscotch_map<size_t, openfpm::vector<CNVcaller::CNV_event_link>> map;
 
-  // remeber is 0-based index, call id is 0, padding between call-start and seed is -1
-  int offset = 0;
+    All_samples_call_related_relevant_read_type seqs;
 
-  // call id 1
-  add_32bases_pattern_with_variability_range_shift(2,195452504,195452504+32,8,reference,map,"test/gnomad_variants_variability_test.vcf.gz",76,195452504-195451992+32,NO_PADDING);
+    // remeber is 0-based index, call id is 0, padding between call-start and seed is -1
+    int offset = 0;
 
-  std::cout << "CALL " << calls_to_test.get(76).chromosome << ":" << calls_to_test.get(76).start << "-" << calls_to_test.get(76).stop << std::endl;
+    // call id 1
+    add_32bases_pattern_with_variability_range_shift(2, 195452504, 195452504 + 32, 8, reference, map, "test/gnomad_variants_variability_test.vcf.gz", 76, 195452504 - 195451992 + 32, NO_PADDING);
 
-  auto i = map.begin();
+    std::cout << "CALL " << calls_to_test.get(76).chromosome << ":" << calls_to_test.get(76).start << "-" << calls_to_test.get(76).stop << std::endl;
 
-  while (i != map.end()) {
-    std::cout << CNVcaller::string_from_32bases_pattern(i->first) << std::endl;
-    i++;
-  }
+    auto i = map.begin();
 
-  seqs.resize(3);
+    while (i != map.end())
+    {
+        std::cout << CNVcaller::string_from_32bases_pattern(i->first) << std::endl;
+        i++;
+    }
 
-  std::string test_bam("test/HG002_reads_cnv_MUC20.bam");
-  collect_reads_for_call_evidence(test_bam,map,calls_to_test,seqs.get<0>(0),reference,6,3);
+    seqs.resize(3);
 
-  // We check that all read are coupled, for all elements in the map
+    std::string test_bam("test/HG002_reads_cnv_MUC20.bam");
+    collect_reads_for_call_evidence(test_bam, map, calls_to_test, seqs.get<0>(0), reference, 6, 3);
 
-  for (int i = 0 ; i < seqs.size() ; i++) {
-    for (int j = 0 ; j < seqs.get<0>(i).size() ; j++) {
-      for (int k = 0 ; k < seqs.get<0>(i).get<0>(j).size() ; k++) {
-        auto & pair = seqs.get<0>(i).get<0>(j).get<0>(k);
+    // We check that all read are coupled, for all elements in the map
 
-        if (pair.get<1>(3) != 'A' && pair.get<1>(3) != 'C' && pair.get<1>(3) != 'T' && pair.get<1>(3) != 'G')
+    for (int i = 0; i < seqs.size(); i++)
+    {
+        for (int j = 0; j < seqs.get<0>(i).size(); j++)
         {
-          seqs.get<0>(i).get<0>(j).remove(k);
-          k--;
-          std::cout << "Error: " << pair.get<1>(3) << std::endl;
+            for (int k = 0; k < seqs.get<0>(i).get<0>(j).size(); k++)
+            {
+                auto &pair = seqs.get<0>(i).get<0>(j).get<0>(k);
+
+                if (pair.get<1>(3) != 'A' && pair.get<1>(3) != 'C' && pair.get<1>(3) != 'T' && pair.get<1>(3) != 'G')
+                {
+                    seqs.get<0>(i).get<0>(j).remove(k);
+                    k--;
+                    std::cout << "Error: " << pair.get<1>(3) << std::endl;
+                }
+
+                BOOST_REQUIRE((pair.get<1>(3) == 'A' || pair.get<1>(3) == 'C' || pair.get<1>(3) == 'T' || pair.get<1>(3) == 'G'));
+            }
         }
-
-        BOOST_REQUIRE((pair.get<1>(3) == 'A' || pair.get<1>(3) == 'C' || pair.get<1>(3) == 'T' || pair.get<1>(3) == 'G'));
-      }
     }
-  }
-
-  openfpm::vector<CNVcaller::seed_id> seed;
-  convert_seed_map_to_array(seed,map,calls_to_test);
-
-  // Find all reference points
-  openfpm::vector<openfpm::vector<aggregate<short int, int, int>>> un_seed;
-  un_seed.resize(calls_to_test.size());
-//  get_reference_point(seed,reference,un_seed);
-//  un_seed.save("test/MUC20_cnv_variability");
-  un_seed.load("test/MUC20_cnv_variability");
-
-  // Calculate evidence for each of the read pair
-
-  openfpm::vector<int> chr_ins;
-  chr_ins.resize(23);
-
-  for (int i = 0 ; i < chr_ins.size(); i++) {
-    chr_ins.get(i) = 210;
-  }
-
-  // Load insert size probability
-  
-  openfpm::vector<double> bp_insert_prob;
-  bp_insert_prob.load("insert_probability_distribution");
-
-  // Get the seed number associated to the call
-  int seed_num = 0;
-
-  int padding = 6;
-
-  // For rach read
-  int n_read_check = 0;
-  for (int j = 0 ; j < seqs.get<0>(0).size() ; j++) {
-    for (int i = 0 ; i < seqs.get<0>(0).get<0>(j).size() ; i++) {
-
-      size_t seed_pos = seqs.get<0>(0).get<0>(j).get<4>(i);
-
-      Eigen::ArrayXd insert;
-      Eigen::ArrayXd eml3 = Evidence_matrix_log(reference,
-                                                seqs.get<0>(0).get<0>(j).get<0>(i),
-                                                un_seed.get(j),
-                                                calls_to_test.get(j),
-                                                padding,
-                                                seqs.get<0>(0).get<0>(j).get<1>(i),
-                                                seqs.get<0>(0).get<0>(j).get<2>(i),
-                                                seed_pos,
-                                                chr_ins,
-                                                insert,
-                                                bp_insert_prob);
-
-      double best_event = -1000.0;
-      int k = 0;
-      double best_ref = -1000.0;
-      int best_ref_seed_pos = -1;
-
-      for (int i = 0 ; i < (2*padding+1)*(2*padding+1) ; i++) {
-        if (eml3(i) > best_event) {
-          best_event = eml3(i);
-        }
-      }
 
-      for (int i = (2*padding+1)*(2*padding+1) ; i < eml3.size() ; i++) {
-        if (eml3(i) > best_ref) {
-          best_ref = eml3(i);
-          k = i;
-          best_ref_seed_pos = un_seed.get(j).get<1>(i-(2*padding+1)*(2*padding+1));
-        }
-      }
-
-      char seq[64];
-      memset(seq,0,64);
-
-      for (int k = 0 ; seqs.get<0>(0).get<0>(j).get<0>(i).get<2>(k) != 0 ; k++) {
-        seq[k] = seqs.get<0>(0).get<0>(j).get<0>(i).get<2>(k);
-      }
-
-      std::cout << "  j=" << j << "/" << seqs.get<0>(0).size() << " i=" << i << "/" << seqs.get<0>(0).get<0>(j).size() << 
-                   "    Event vs Reference " << best_event << "/" << best_ref << "  " << "  best ref seed pos: " << best_ref_seed_pos << "  "
-                   << ((best_event > best_ref)?"#":"") << std::endl;
-
-      if (strcmp("A00684:261:HNJK2DRX2:1:2264:6659:10332",&seq[0]) == 0) {
-        BOOST_REQUIRE(best_event > best_ref);
-        n_read_check++;
-      } else if (strcmp("A00684:261:HNJK2DRX2:1:2150:3233:9878",&seq[0]) == 0) {
-        BOOST_REQUIRE(best_event > best_ref);
-        n_read_check++;
-      } else if (strcmp("A00684:261:HNJK2DRX2:2:2205:4806:33144",&seq[0]) == 0) {
-        BOOST_REQUIRE(best_event > best_ref);
-        n_read_check++;
-      } else if (strcmp("A00684:261:HNJK2DRX2:2:2245:6406:36198",&seq[0]) == 0) {
-        BOOST_REQUIRE(best_event > best_ref);
-        n_read_check++;
-      } else if (strcmp("A00684:261:HNJK2DRX2:2:2250:27896:15702",&seq[0]) == 0) {
-        BOOST_REQUIRE(best_event > best_ref);
-        n_read_check++;
-      }
+    openfpm::vector<CNVcaller::seed_id> seed;
+    convert_seed_map_to_array(seed, map, calls_to_test);
+
+    // Find all reference points
+    openfpm::vector<openfpm::vector<aggregate<short int, int, int>>> un_seed;
+    un_seed.resize(calls_to_test.size());
+    //  get_reference_point(seed,reference,un_seed);
+    //  un_seed.save("test/MUC20_cnv_variability");
+    un_seed.load("test/MUC20_cnv_variability");
+
+    // Calculate evidence for each of the read pair
 
+    openfpm::vector<int> chr_ins;
+    chr_ins.resize(23);
 
+    for (int i = 0; i < chr_ins.size(); i++)
+    {
+        chr_ins.get(i) = 210;
     }
-  }
 
-  BOOST_REQUIRE_EQUAL(n_read_check,5);
+    // Load insert size probability
+
+    openfpm::vector<double> bp_insert_prob;
+    bp_insert_prob.load("insert_probability_distribution");
+
+    // Get the seed number associated to the call
+    int seed_num = 0;
+
+    int padding = 6;
 
+    // For rach read
+    int n_read_check = 0;
+    for (int j = 0; j < seqs.get<0>(0).size(); j++)
+    {
+        for (int i = 0; i < seqs.get<0>(0).get<0>(j).size(); i++)
+        {
+
+            size_t seed_pos = seqs.get<0>(0).get<0>(j).get<4>(i);
+
+            Eigen::ArrayXd insert;
+            Eigen::ArrayXd eml3 = Evidence_matrix_log(reference,
+                                                      seqs.get<0>(0).get<0>(j).get<0>(i),
+                                                      un_seed.get(j),
+                                                      calls_to_test.get(j),
+                                                      padding,
+                                                      seqs.get<0>(0).get<0>(j).get<1>(i),
+                                                      seqs.get<0>(0).get<0>(j).get<2>(i),
+                                                      seed_pos,
+                                                      chr_ins,
+                                                      insert,
+                                                      bp_insert_prob);
+
+            double best_event = -1000.0;
+            int k = 0;
+            double best_ref = -1000.0;
+            int best_ref_seed_pos = -1;
+
+            for (int i = 0; i < (2 * padding + 1) * (2 * padding + 1); i++)
+            {
+                if (eml3(i) > best_event)
+                {
+                    best_event = eml3(i);
+                }
+            }
+
+            for (int i = (2 * padding + 1) * (2 * padding + 1); i < eml3.size(); i++)
+            {
+                if (eml3(i) > best_ref)
+                {
+                    best_ref = eml3(i);
+                    k = i;
+                    best_ref_seed_pos = un_seed.get(j).get<1>(i - (2 * padding + 1) * (2 * padding + 1));
+                }
+            }
+
+            char seq[64];
+            memset(seq, 0, 64);
+
+            for (int k = 0; seqs.get<0>(0).get<0>(j).get<0>(i).get<2>(k) != 0; k++)
+            {
+                seq[k] = seqs.get<0>(0).get<0>(j).get<0>(i).get<2>(k);
+            }
+
+            std::cout << "  j=" << j << "/" << seqs.get<0>(0).size() << " i=" << i << "/" << seqs.get<0>(0).get<0>(j).size() << "    Event vs Reference " << best_event << "/" << best_ref << "  " << "  best ref seed pos: " << best_ref_seed_pos << "  "
+                      << ((best_event > best_ref) ? "#" : "") << std::endl;
+
+            if (strcmp("A00684:261:HNJK2DRX2:1:2264:6659:10332", &seq[0]) == 0)
+            {
+                BOOST_REQUIRE(best_event > best_ref);
+                n_read_check++;
+            }
+            else if (strcmp("A00684:261:HNJK2DRX2:1:2150:3233:9878", &seq[0]) == 0)
+            {
+                BOOST_REQUIRE(best_event > best_ref);
+                n_read_check++;
+            }
+            else if (strcmp("A00684:261:HNJK2DRX2:2:2205:4806:33144", &seq[0]) == 0)
+            {
+                BOOST_REQUIRE(best_event > best_ref);
+                n_read_check++;
+            }
+            else if (strcmp("A00684:261:HNJK2DRX2:2:2245:6406:36198", &seq[0]) == 0)
+            {
+                BOOST_REQUIRE(best_event > best_ref);
+                n_read_check++;
+            }
+            else if (strcmp("A00684:261:HNJK2DRX2:2:2250:27896:15702", &seq[0]) == 0)
+            {
+                BOOST_REQUIRE(best_event > best_ref);
+                n_read_check++;
+            }
+        }
+    }
+
+    BOOST_REQUIRE_EQUAL(n_read_check, 5);
 }
 
 BOOST_AUTO_TEST_CASE(write_a_bam_file)
 {
     std::string bam_file("test/HG002_reads_cnv_MUC20.bam");
 
-  samFile *fp_in = hts_open(bam_file.c_str(),"r");
-    samFile *fp_out = hts_open("test.bam","wb"); //open bam file
-    bam_hdr_t *bamHdr = sam_hdr_read(fp_in); //read header
+    samFile *fp_in = hts_open(bam_file.c_str(), "r");
+    samFile *fp_out = hts_open("test.bam", "wb"); // open bam file
+    bam_hdr_t *bamHdr = sam_hdr_read(fp_in);      // read header
     int r;
     r = sam_hdr_write(fp_out, bamHdr);
-    bam1_t *aln = bam_init1(); //initialize an alignment
+    bam1_t *aln = bam_init1(); // initialize an alignment
 
     const char *qname = "q1";
-    const uint32_t cigar[] = { 6 << BAM_CIGAR_SHIFT | BAM_CMATCH, 2 << BAM_CIGAR_SHIFT | BAM_CINS, 2 << BAM_CIGAR_SHIFT | BAM_CMATCH };
+    const uint32_t cigar[] = {6 << BAM_CIGAR_SHIFT | BAM_CMATCH, 2 << BAM_CIGAR_SHIFT | BAM_CINS, 2 << BAM_CIGAR_SHIFT | BAM_CMATCH};
     const char *seq = "TGGACTACGA";
     const char *qual = "FFFFFFFFFF";
 
     bam_set1(aln, strlen(qname), qname,
-                 BAM_FPAIRED | BAM_FPROPER_PAIR | BAM_FMREVERSE | BAM_FREAD2, 2, 195452541, 42,
-                 sizeof(cigar) / 4, cigar, 2, 195452561, 42,
-                 strlen(seq), seq, qual, 64);
+             BAM_FPAIRED | BAM_FPROPER_PAIR | BAM_FMREVERSE | BAM_FREAD2, 2, 195452541, 42,
+             sizeof(cigar) / 4, cigar, 2, 195452561, 42,
+             strlen(seq), seq, qual, 64);
 
     r = sam_write1(fp_out, bamHdr, aln);
 
     bam_set1(aln, strlen(qname), qname,
-                 BAM_FPAIRED | BAM_FPROPER_PAIR | BAM_FREVERSE | BAM_FREAD1, 2, 195452561, 42,
-                 sizeof(cigar) / 4, cigar, 2, 195452541, 42,
-                 strlen(seq), seq, qual, 64);
+             BAM_FPAIRED | BAM_FPROPER_PAIR | BAM_FREVERSE | BAM_FREAD1, 2, 195452561, 42,
+             sizeof(cigar) / 4, cigar, 2, 195452541, 42,
+             strlen(seq), seq, qual, 64);
 
     r = sam_write1(fp_out, bamHdr, aln);
 
@@ -1260,324 +1298,385 @@ BOOST_AUTO_TEST_CASE(write_a_bam_file)
 }
 
 // Many read events
-BOOST_AUTO_TEST_CASE( CNV_caller_evidence_probability_for_each_event_with_variability_many_reads_2calls )
+BOOST_AUTO_TEST_CASE(CNV_caller_evidence_probability_for_each_event_with_variability_many_reads_2calls)
 {
-  //
-  std::string bam_file("test/HG002_reads_cnv_MUC20.bam");
-
-  samFile *fp_in = hts_open(bam_file.c_str(),"r");
+    //
+    std::string bam_file("test/HG002_reads_cnv_MUC20.bam");
 
-  samFile *fp_out77_best = hts_open("call77_best.bam","wb"); //open bam file
-  samFile *fp_out78_best = hts_open("call78_best.bam","wb"); //open bam file
-  samFile *fp_out79_best = hts_open("call79_best.bam","wb"); //open bam file
+    samFile *fp_in = hts_open(bam_file.c_str(), "r");
 
-  samFile *fp_out77_event = hts_open("call77_event.bam","wb"); //open bam file
-  samFile *fp_out78_event = hts_open("call78_event.bam","wb"); //open bam file
-  samFile *fp_out79_event = hts_open("call79_event.bam","wb"); //open bam file  
+    samFile *fp_out77_best = hts_open("call77_best.bam", "wb"); // open bam file
+    samFile *fp_out78_best = hts_open("call78_best.bam", "wb"); // open bam file
+    samFile *fp_out79_best = hts_open("call79_best.bam", "wb"); // open bam file
 
-  samFile *fp_out77_ref = hts_open("call77_ref.bam","wb"); //open bam file
-  samFile *fp_out78_ref = hts_open("call78_ref.bam","wb"); //open bam file
-  samFile *fp_out79_ref = hts_open("call79_ref.bam","wb"); //open bam file  
+    samFile *fp_out77_event = hts_open("call77_event.bam", "wb"); // open bam file
+    samFile *fp_out78_event = hts_open("call78_event.bam", "wb"); // open bam file
+    samFile *fp_out79_event = hts_open("call79_event.bam", "wb"); // open bam file
 
-  bam_hdr_t *bamHdr = sam_hdr_read(fp_in); //read header
-  int r;
+    samFile *fp_out77_ref = hts_open("call77_ref.bam", "wb"); // open bam file
+    samFile *fp_out78_ref = hts_open("call78_ref.bam", "wb"); // open bam file
+    samFile *fp_out79_ref = hts_open("call79_ref.bam", "wb"); // open bam file
 
-  r = sam_hdr_write(fp_out77_best, bamHdr);
-  r = sam_hdr_write(fp_out78_best, bamHdr);
-  r = sam_hdr_write(fp_out79_best, bamHdr);
+    bam_hdr_t *bamHdr = sam_hdr_read(fp_in); // read header
+    int r;
 
-  r = sam_hdr_write(fp_out77_event, bamHdr);
-  r = sam_hdr_write(fp_out78_event, bamHdr);
-  r = sam_hdr_write(fp_out79_event, bamHdr);
+    r = sam_hdr_write(fp_out77_best, bamHdr);
+    r = sam_hdr_write(fp_out78_best, bamHdr);
+    r = sam_hdr_write(fp_out79_best, bamHdr);
 
-  r = sam_hdr_write(fp_out77_ref, bamHdr);
-  r = sam_hdr_write(fp_out78_ref, bamHdr);
-  r = sam_hdr_write(fp_out79_ref, bamHdr);
+    r = sam_hdr_write(fp_out77_event, bamHdr);
+    r = sam_hdr_write(fp_out78_event, bamHdr);
+    r = sam_hdr_write(fp_out79_event, bamHdr);
 
-  bam1_t *aln = bam_init1(); //initialize an alignment
+    r = sam_hdr_write(fp_out77_ref, bamHdr);
+    r = sam_hdr_write(fp_out78_ref, bamHdr);
+    r = sam_hdr_write(fp_out79_ref, bamHdr);
 
-  openfpm::vector<openfpm::vector<char>> reference;
-  reference.load("reference_vector");
+    bam1_t *aln = bam_init1(); // initialize an alignment
 
-  openfpm::vector<CNVcaller::call_vcf> calls_to_test;
-  CNVcaller::read_CNV_hypothesys("test/DGV_variants_MUC20_2calls.vcf.gz",calls_to_test);
-  tsl::hopscotch_map<size_t, openfpm::vector<CNVcaller::CNV_event_link>> map;
+    openfpm::vector<openfpm::vector<char>> reference;
+    reference.load("reference_vector");
 
-  All_samples_call_related_relevant_read_type seqs;
+    openfpm::vector<CNVcaller::call_vcf> calls_to_test;
+    CNVcaller::read_CNV_hypothesys("test/DGV_variants_MUC20_2calls.vcf.gz", calls_to_test);
+    tsl::hopscotch_map<size_t, openfpm::vector<CNVcaller::CNV_event_link>> map;
 
-  // remeber is 0-based index, call id is 0, padding between call-start and seed is -1
-  int offset = 0;
+    All_samples_call_related_relevant_read_type seqs;
 
-  // call id 1
-  add_32bases_pattern_with_variability_range_shift(2,195452504,195452504+32,8,reference,map,"test/gnomad_variants_variability_test.vcf.gz",77,195452504-195451992+32,NO_PADDING);
-  add_32bases_pattern_with_variability_range_shift(2,195452561,195452561+32,8,reference,map,"test/gnomad_variants_variability_test.vcf.gz",78,195452561-195451992+32,NO_PADDING);
-  add_32bases_pattern_with_variability_range_shift(2,195452447,195452447+32,8,reference,map,"test/gnomad_variants_variability_test.vcf.gz",79,195452447-195451992+32,NO_PADDING);
+    // remeber is 0-based index, call id is 0, padding between call-start and seed is -1
+    int offset = 0;
 
-  std::cout << "CALL " << calls_to_test.get(77).chromosome << ":" << calls_to_test.get(77).start << "-" << calls_to_test.get(77).stop << std::endl;
-  std::cout << "CALL " << calls_to_test.get(78).chromosome << ":" << calls_to_test.get(78).start << "-" << calls_to_test.get(78).stop << std::endl;
-  std::cout << "CALL " << calls_to_test.get(79).chromosome << ":" << calls_to_test.get(79).start << "-" << calls_to_test.get(79).stop << std::endl;
+    // call id 1
+    add_32bases_pattern_with_variability_range_shift(2, 195452504, 195452504 + 32, 8, reference, map, "test/gnomad_variants_variability_test.vcf.gz", 77, 195452504 - 195451992 + 32, NO_PADDING);
+    add_32bases_pattern_with_variability_range_shift(2, 195452561, 195452561 + 32, 8, reference, map, "test/gnomad_variants_variability_test.vcf.gz", 78, 195452561 - 195451992 + 32, NO_PADDING);
+    add_32bases_pattern_with_variability_range_shift(2, 195452447, 195452447 + 32, 8, reference, map, "test/gnomad_variants_variability_test.vcf.gz", 79, 195452447 - 195451992 + 32, NO_PADDING);
 
-  auto i = map.begin();
+    std::cout << "CALL " << calls_to_test.get(77).chromosome << ":" << calls_to_test.get(77).start << "-" << calls_to_test.get(77).stop << std::endl;
+    std::cout << "CALL " << calls_to_test.get(78).chromosome << ":" << calls_to_test.get(78).start << "-" << calls_to_test.get(78).stop << std::endl;
+    std::cout << "CALL " << calls_to_test.get(79).chromosome << ":" << calls_to_test.get(79).start << "-" << calls_to_test.get(79).stop << std::endl;
 
-  while (i != map.end()) {
-    std::cout << CNVcaller::string_from_32bases_pattern(i->first) << std::endl;
-    i++;
-  }
+    auto i = map.begin();
 
-  seqs.resize(3);
+    while (i != map.end())
+    {
+        std::cout << CNVcaller::string_from_32bases_pattern(i->first) << std::endl;
+        i++;
+    }
 
-  std::string test_bam("test/HG002_reads_cnv_MUC20.bam");
-  collect_reads_for_call_evidence(test_bam,map,calls_to_test,seqs.get<0>(0),reference,6,3);
+    seqs.resize(3);
 
-  // We check that all read are coupled, for all elements in the map
+    std::string test_bam("test/HG002_reads_cnv_MUC20.bam");
+    collect_reads_for_call_evidence(test_bam, map, calls_to_test, seqs.get<0>(0), reference, 6, 3);
 
-  for (int i = 0 ; i < seqs.size() ; i++) {
-    for (int j = 0 ; j < seqs.get<0>(i).size() ; j++) {
-      for (int k = 0 ; k < seqs.get<0>(i).get<0>(j).size() ; k++) {
-        auto & pair = seqs.get<0>(i).get<0>(j).get<0>(k);
+    // We check that all read are coupled, for all elements in the map
 
-        if (pair.get<1>(3) != 'A' && pair.get<1>(3) != 'C' && pair.get<1>(3) != 'T' && pair.get<1>(3) != 'G')
+    for (int i = 0; i < seqs.size(); i++)
+    {
+        for (int j = 0; j < seqs.get<0>(i).size(); j++)
         {
-          seqs.get<0>(i).get<0>(j).remove(k);
-          k--;
-          std::cout << "Error: " << i << "  " << j << "  " << k << "  " << pair.get<1>(3) << std::endl;
+            for (int k = 0; k < seqs.get<0>(i).get<0>(j).size(); k++)
+            {
+                auto &pair = seqs.get<0>(i).get<0>(j).get<0>(k);
+
+                if (pair.get<1>(3) != 'A' && pair.get<1>(3) != 'C' && pair.get<1>(3) != 'T' && pair.get<1>(3) != 'G')
+                {
+                    seqs.get<0>(i).get<0>(j).remove(k);
+                    k--;
+                    std::cout << "Error: " << i << "  " << j << "  " << k << "  " << pair.get<1>(3) << std::endl;
+                }
+
+                BOOST_REQUIRE((pair.get<1>(3) == 'A' || pair.get<1>(3) == 'C' || pair.get<1>(3) == 'T' || pair.get<1>(3) == 'G'));
+            }
         }
-
-        BOOST_REQUIRE((pair.get<1>(3) == 'A' || pair.get<1>(3) == 'C' || pair.get<1>(3) == 'T' || pair.get<1>(3) == 'G'));
-      }
     }
-  }
-
-  openfpm::vector<CNVcaller::seed_id> seed;
-  convert_seed_map_to_array(seed,map,calls_to_test);
 
-  // Find all reference points
-  openfpm::vector<openfpm::vector<aggregate<short int, int, int>>> un_seed;
-  un_seed.resize(calls_to_test.size());
-//  get_reference_point(seed,reference,un_seed);
-//  un_seed.save("test/MUC20_cnv_variability_2_calls");
-  un_seed.load("test/MUC20_cnv_variability_2_calls");
+    openfpm::vector<CNVcaller::seed_id> seed;
+    convert_seed_map_to_array(seed, map, calls_to_test);
 
-  // Calculate evidence for each of the read pair
+    // Find all reference points
+    openfpm::vector<openfpm::vector<aggregate<short int, int, int>>> un_seed;
+    un_seed.resize(calls_to_test.size());
+    //  get_reference_point(seed,reference,un_seed);
+    //  un_seed.save("test/MUC20_cnv_variability_2_calls");
+    un_seed.load("test/MUC20_cnv_variability_2_calls");
 
-  openfpm::vector<int> chr_ins;
-  chr_ins.resize(23);
+    // Calculate evidence for each of the read pair
 
-  for (int i = 0 ; i < chr_ins.size(); i++) {
-    chr_ins.get(i) = 210;
-  }
+    openfpm::vector<int> chr_ins;
+    chr_ins.resize(23);
 
-  // Load insert size probability
-  
-  openfpm::vector<double> bp_insert_prob;
-  bp_insert_prob.load("insert_probability_distribution");
-
-  // Get the seed number associated to the call
-  int seed_num = 0;
-
-  int padding = 6;
-
-  int n_read_check = 0;
-
-  // For rach read
-  for (int j = 0 ; j < seqs.get<0>(0).size() ; j++) {
-
-    samFile *fp_out_best = NULL;
-    if (j == 77) {fp_out_best = fp_out77_best;}
-    if (j == 78) {fp_out_best = fp_out78_best;}
-    if (j == 79) {fp_out_best = fp_out79_best;}
-
-    auto call = calls_to_test.get(j);
-
-    for (int i = 0 ; i < seqs.get<0>(0).get<0>(j).size() ; i++) {
+    for (int i = 0; i < chr_ins.size(); i++)
+    {
+        chr_ins.get(i) = 210;
+    }
 
-      size_t seed_pos = seqs.get<0>(0).get<0>(j).get<4>(i);
+    // Load insert size probability
 
-      Eigen::ArrayXd insert_;
-      Eigen::ArrayXd eml3 = Evidence_matrix_log(reference,
-                                                seqs.get<0>(0).get<0>(j).get<0>(i),
-                                                un_seed.get(j),
-                                                calls_to_test.get(j),
-                                                padding,
-                                                seqs.get<0>(0).get<0>(j).get<1>(i),
-                                                seqs.get<0>(0).get<0>(j).get<2>(i),
-                                                seed_pos,
-                                                chr_ins,
-                                                insert_,
-                                                bp_insert_prob);
+    openfpm::vector<double> bp_insert_prob;
+    bp_insert_prob.load("insert_probability_distribution");
 
-      const Pair_read_type & seq = seqs.get<0>(0).get<0>(j).get<0>(i);
+    // Get the seed number associated to the call
+    int seed_num = 0;
 
-      double best_event = -1000.0;
-      double best_ref = -1000.0;
-      int best_ref_seed_pos = -1;
-      int best_ei = -1;
+    int padding = 6;
 
-      for (int i = 0 ; i < (2*padding+1)*(2*padding+1) ; i++) {
-        if (eml3(i) > best_event) {
-          best_event = eml3(i);
-          best_ei = i;
-        }
-      }
+    int n_read_check = 0;
 
-      int best_ri = -1;
+    // For rach read
+    for (int j = 0; j < seqs.get<0>(0).size(); j++)
+    {
 
-      for (int i = (2*padding+1)*(2*padding+1) ; i < eml3.size() ; i++) {
-        if (eml3(i) > best_ref) {
-          best_ref = eml3(i);
-          best_ref_seed_pos = un_seed.get(j).get<1>(i-(2*padding+1)*(2*padding+1));
-          best_ri = i;
-        }
-      }
-
-      char seq1[16384];
-      char seq2[16384];
-      char name[16384];
-      memset(seq1,0,16384);
-      int kf = 0;
-      int kr = 0;
-      int kn = 0;
-
-      {
-        auto & seq = seqs.get<0>(0).get<0>(j).get<0>(i);
-        for ( ; kf < seq.size() && seq.get<0>(kf) != 0 ; kf++) {
-          seq1[kf] = seq.get<0>(kf);
+        samFile *fp_out_best = NULL;
+        if (j == 77)
+        {
+            fp_out_best = fp_out77_best;
         }
-
-        for ( ; kr < seq.size() && seq.get<1>(kr) != 0; kr++) {
-          seq2[kr] = seq.get<1>(kr);
+        if (j == 78)
+        {
+            fp_out_best = fp_out78_best;
         }
-
-        for ( ; kn < seq.size() && seq.get<2>(kn) != 0  ; kn++) {
-          name[kn] = seq.get<2>(kn);
+        if (j == 79)
+        {
+            fp_out_best = fp_out79_best;
         }
-      }
-
-      int chr = seqs.get<0>(0).get<0>(j).get<1>(i);
-      int pos = seqs.get<0>(0).get<0>(j).get<2>(i);
 
-      char qual[16384];
-      memset(seq1,'F',16384);
+        auto call = calls_to_test.get(j);
 
-      int pos_event;
-      int i_shift = best_ei/(2*padding+1) - padding;
-      int j_shift = best_ei%(2*padding+1) - padding;
-
-      if (best_ref_seed_pos == 195452504 || best_ref_seed_pos == 195452561 || best_ref_seed_pos == 195452447) {
-        int debug = 0;
-        debug++;
-      }
-
-      CNVcaller::adjust_pos_by_event(pos,pos_event,call,i_shift,j_shift);
-
-      int overlap_1 = std::max(pos,call.start+i_shift);
-      int overlap_2 = std::min(pos+(int)seq.size(),call.stop+j_shift);
-      if (overlap_2-overlap_1 > 0) {
-
-        int end = kf - (call.start+i_shift - pos_event);
-
-        CNVcaller::get_sequence(reference,chr,pos_event,call.stop+j_shift+end,call.start+i_shift,call.stop+j_shift,seq1);
-
-        // create event CIGAR
-
-        openfpm::vector<uint32_t> cigar;
-
-        int diff = abs((best_event - best_ref)*10.0);
+        for (int i = 0; i < seqs.get<0>(0).get<0>(j).size(); i++)
+        {
 
-        if (diff > 255) {
-          diff = 255;
+            int kf = 0;
+            int kr = 0;
+            int kn = 0;
+
+            char name[16384];
+            memset(name, 0, 16384);
+
+            {
+                auto &seq = seqs.get<0>(0).get<0>(j).get<0>(i);
+                for (; kn < seq.size() && seq.get<2>(kn) != 0; kn++)
+                {
+                    name[kn] = seq.get<2>(kn);
+                }
+            }
+
+            size_t seed_pos = seqs.get<0>(0).get<0>(j).get<4>(i);
+
+            Eigen::ArrayXd insert_;
+            Eigen::ArrayXd eml3 = Evidence_matrix_log(reference,
+                                                      seqs.get<0>(0).get<0>(j).get<0>(i),
+                                                      un_seed.get(j),
+                                                      calls_to_test.get(j),
+                                                      padding,
+                                                      seqs.get<0>(0).get<0>(j).get<1>(i),
+                                                      seqs.get<0>(0).get<0>(j).get<2>(i),
+                                                      seed_pos,
+                                                      chr_ins,
+                                                      insert_,
+                                                      bp_insert_prob);
+
+            const Pair_read_type &seq = seqs.get<0>(0).get<0>(j).get<0>(i);
+
+            double best_event = -1000.0;
+            double best_ref = -1000.0;
+            double best_ref_2 = -1000.0;
+            int best_ref_seed_pos = -1;
+            int best_ei = -1;
+
+            for (int i = 0; i < (2 * padding + 1) * (2 * padding + 1); i++)
+            {
+                if (eml3(i) > best_event)
+                {
+                    best_event = eml3(i);
+                    best_ei = i;
+                }
+            }
+
+            int best_ri = -1;
+
+            for (int i = (2 * padding + 1) * (2 * padding + 1); i < eml3.size(); i++)
+            {
+                if (eml3(i) > best_ref)
+                {
+                    best_ref_2 = best_ref;
+                    best_ref = eml3(i);
+                    best_ref_seed_pos = un_seed.get(j).get<1>(i - (2 * padding + 1) * (2 * padding + 1));
+                    best_ri = i;
+                }
+            }
+
+            char seq1[16384];
+            char seq2[16384];
+            memset(seq1, 0, 16384);
+
+            {
+                auto &seq = seqs.get<0>(0).get<0>(j).get<0>(i);
+                for (; kf < seq.size() && seq.get<0>(kf) != 0; kf++)
+                {
+                    seq1[kf] = seq.get<0>(kf);
+                }
+
+                for (; kr < seq.size() && seq.get<1>(kr) != 0; kr++)
+                {
+                    seq2[kr] = seq.get<1>(kr);
+                }
+            }
+
+            int chr = seqs.get<0>(0).get<0>(j).get<1>(i);
+            int pos = seqs.get<0>(0).get<0>(j).get<2>(i);
+
+            char qual[16384];
+            memset(qual, 'F', 16384);
+
+            int pos_event;
+            int i_shift = best_ei / (2 * padding + 1) - padding;
+            int j_shift = best_ei % (2 * padding + 1) - padding;
+
+            CNVcaller::adjust_pos_by_event(pos, pos_event, call, i_shift, j_shift);
+
+            int overlap_1 = std::max(pos, call.start + i_shift);
+            int overlap_2 = std::min(pos + (int)seq.size(), call.stop + j_shift);
+            if (overlap_2 - overlap_1 > 0)
+            {
+
+                int end = kf - (call.start + i_shift - pos_event);
+
+                // create event CIGAR
+
+                openfpm::vector<uint32_t> cigar;
+
+                if (best_event > best_ref)
+                {
+                    int diff = abs((best_event - best_ref) * 10.0);
+
+                    if (diff > 255)
+                    {
+                        diff = 255;
+                    }
+
+                    CNVcaller::create_event_cigar(cigar, i_shift, j_shift, pos_event, end, call);
+
+                    int insert = insert_(best_ei);
+
+                    // write forward read
+                    bam_set1(aln, kn, name,
+                             BAM_FPAIRED | BAM_FPROPER_PAIR | BAM_FMREVERSE | BAM_FREAD2, chr, pos_event, diff,
+                             cigar.size(), &cigar.get(0), chr, pos + insert, insert,
+                             kf, seq1, qual, 64);
+
+                    r = sam_write1(fp_out_best, bamHdr, aln);
+
+                    // write reverse read
+
+                    CNVcaller::create_ref_cigar(cigar, kr);
+
+                    bam_set1(aln, kn, name,
+                             BAM_FPAIRED | BAM_FPROPER_PAIR | BAM_FREVERSE | BAM_FREAD1, chr, pos + insert, diff,
+                             cigar.size(), &cigar.get(0), chr, pos, insert,
+                             kr, seq2, qual, 64);
+
+                    r = sam_write1(fp_out_best, bamHdr, aln);
+                }
+                else
+                {
+                    int diff = abs((best_ref - best_ref_2) * 10.0);
+
+                    if (diff > 255)
+                    {
+                        diff = 255;
+                    }
+
+                    CNVcaller::create_ref_cigar(cigar, kf);
+
+                    int insert = insert_(best_ri);
+                    int pos = un_seed.get(j).get<1>(best_ri - (2 * padding + 1) * (2 * padding + 1)) - seed_pos;
+
+                    // write forward read
+                    bam_set1(aln, kn, name,
+                             BAM_FPAIRED | BAM_FPROPER_PAIR | BAM_FMREVERSE | BAM_FREAD2, chr, pos, diff,
+                             cigar.size(), &cigar.get(0), chr, pos + insert, insert,
+                             kf, seq1, qual, 64);
+
+                    r = sam_write1(fp_out_best, bamHdr, aln);
+
+                    // write reverse read
+
+                    CNVcaller::create_ref_cigar(cigar, kr);
+
+                    bam_set1(aln, kn, name,
+                             BAM_FPAIRED | BAM_FPROPER_PAIR | BAM_FREVERSE | BAM_FREAD1, chr, pos + insert + 1, diff,
+                             cigar.size(), &cigar.get(0), chr, pos, insert,
+                             kr, seq2, qual, 64);
+
+                    r = sam_write1(fp_out_best, bamHdr, aln);
+                }
+            }
+
+            if (strcmp("A00684:261:HNJK2DRX2:1:2264:6659:10332", &name[0]) == 0)
+            {
+                BOOST_REQUIRE(best_event > best_ref);
+                n_read_check++;
+            }
+            else if (strcmp("A00684:261:HNJK2DRX2:1:2150:3233:9878", &name[0]) == 0)
+            {
+                BOOST_REQUIRE(best_event > best_ref);
+                n_read_check++;
+            }
+            else if (strcmp("A00684:261:HNJK2DRX2:2:2205:4806:33144", &name[0]) == 0)
+            {
+                BOOST_REQUIRE(best_event > best_ref);
+                n_read_check++;
+            }
+            else if (strcmp("A00684:261:HNJK2DRX2:2:2245:6406:36198", &name[0]) == 0)
+            {
+                BOOST_REQUIRE(best_event > best_ref);
+                n_read_check++;
+            }
+            else if (strcmp("A00684:261:HNJK2DRX2:2:2250:27896:15702", &name[0]) == 0)
+            {
+                BOOST_REQUIRE(best_event > best_ref);
+                n_read_check++;
+            }
+
+            std::cout << "  j=" << j << "/" << seqs.get<0>(0).size() << " i=" << i << "/" << seqs.get<0>(0).get<0>(j).size() << "    Event vs Reference " << best_event << "/" << best_ref << "  " << "  best ref seed pos: " << best_ref_seed_pos << "  "
+                      << ((best_ref_seed_pos == 195452504 || best_ref_seed_pos == 195452561 || best_ref_seed_pos == 195452447) ? "*" : "")
+                      << ((best_event > best_ref) ? "#" : "") << std::endl;
         }
+    }
 
-        if (best_event > best_ref) {
-          CNVcaller::create_event_cigar(cigar,i_shift,j_shift,pos_event,end,call);
-
-          int insert = insert_(best_ei);
-
-          // write forward read
-          bam_set1(aln, kn, name,
-                  BAM_FPAIRED | BAM_FPROPER_PAIR | BAM_FMREVERSE | BAM_FREAD2, chr, pos_event, diff,
-                  cigar.size(), &cigar.get(0), chr, pos + insert, insert,
-                  kf, seq1, qual, 64);
-
-
-          r = sam_write1(fp_out_best, bamHdr, aln);
-
-          // write reverse read
-
-          CNVcaller::create_ref_cigar(cigar,kr);
-
-          bam_set1(aln, kn, name,
-                  BAM_FPAIRED | BAM_FPROPER_PAIR | BAM_FREVERSE | BAM_FREAD1, chr, pos + insert, 42,
-                  cigar.size(), &cigar.get(0), chr, pos, insert,
-                  kr, seq2, qual, 64);
-
-          r = sam_write1(fp_out_best, bamHdr, aln);
-
-        } else {
-          CNVcaller::create_ref_cigar(cigar,kf);
-
-          int insert = insert_(best_ri);
-          int pos = un_seed.get<1>(best_ri - (2*padding+1)*(2*padding+1))-distance_from_seed
-
-          // write forward read
-          bam_set1(aln, kn, name,
-                  BAM_FPAIRED | BAM_FPROPER_PAIR | BAM_FMREVERSE | BAM_FREAD2, chr, pos_event, diff,
-                  cigar.size(), &cigar.get(0), chr, pos + insert, insert,
-                  kf, seq1, qual, 64);
+    // Close all files
 
+    bam_destroy1(aln);
 
-          r = sam_write1(fp_out_best, bamHdr, aln);
+    // close file
 
-          // write reverse read
+    hts_close(fp_in);
 
-          CNVcaller::create_ref_cigar(cigar,kr);
+    hts_close(fp_out77_best);
+    hts_close(fp_out78_best);
+    hts_close(fp_out79_best);
 
-          bam_set1(aln, kn, name,
-                  BAM_FPAIRED | BAM_FPROPER_PAIR | BAM_FREVERSE | BAM_FREAD1, chr, pos + insert, 42,
-                  cigar.size(), &cigar.get(0), chr, pos, insert,
-                  kr, seq2, qual, 64);
+    hts_close(fp_out77_event);
+    hts_close(fp_out78_event);
+    hts_close(fp_out79_event);
 
-          r = sam_write1(fp_out_best, bamHdr, aln);
-        }
-      }
-
-      if (strcmp("A00684:261:HNJK2DRX2:1:2264:6659:10332",&name[0]) == 0) {
-        BOOST_REQUIRE(best_event > best_ref);
-        n_read_check++;
-      } else if (strcmp("A00684:261:HNJK2DRX2:1:2150:3233:9878",&name[0]) == 0) {
-        BOOST_REQUIRE(best_event > best_ref);
-        n_read_check++;
-      } else if (strcmp("A00684:261:HNJK2DRX2:2:2205:4806:33144",&name[0]) == 0) {
-        BOOST_REQUIRE(best_event > best_ref);
-        n_read_check++;
-      } else if (strcmp("A00684:261:HNJK2DRX2:2:2245:6406:36198",&name[0]) == 0) {
-        BOOST_REQUIRE(best_event > best_ref);
-        n_read_check++;
-      } else if (strcmp("A00684:261:HNJK2DRX2:2:2250:27896:15702",&name[0]) == 0) {
-        BOOST_REQUIRE(best_event > best_ref);
-        n_read_check++;
-      }
-
-      std::cout << "  j=" << j << "/" << seqs.get<0>(0).size() << " i=" << i << "/" << seqs.get<0>(0).get<0>(j).size() << 
-                   "    Event vs Reference " << best_event << "/" << best_ref << "  " << "  best ref seed pos: " << best_ref_seed_pos << "  " 
-                   << ((best_ref_seed_pos == 195452504 || best_ref_seed_pos == 195452561 || best_ref_seed_pos == 195452447)?"*":"")
-                   << ((best_event > best_ref)?"#":"") << std::endl;
-    }
-  }
+    hts_close(fp_out77_ref);
+    hts_close(fp_out78_ref);
+    hts_close(fp_out79_ref);
+}
 
 
-}
 
 BOOST_AUTO_TEST_SUITE_END()
 
 // initialization function:
 bool init_unit_test()
 {
-  return true;
+    return true;
 }
 
 // entry point:
-int main(int argc, char* argv[])
+int main(int argc, char *argv[])
 {
-	return boost::unit_test::unit_test_main( &init_unit_test, argc, argv );
+    return boost::unit_test::unit_test_main(&init_unit_test, argc, argv);
 }
\ No newline at end of file
-- 
GitLab