// File: schneebergerlab[P]GameteBinning/asPollinator_1.0.cpp
// Function: correct_haplotype3_with_pmClusterCnt(std::map<int, POLLEN, std::less<int>, std::allocator<std::pair<int const, POLLEN>>>, std::map<int, POLLEN, std::less<int>, std::allocator<std::pair<int const, POLLEN>>>, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>>*, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>>*)
bool correct_haplotype3_with_pmClusterCnt(map<int, POLLEN> maCluster,
                                          map<int, POLLEN> paCluster,
                                          string*          matGT,
                                          string*          patGT)
{
    // this is stage 3 correction: use 'P/M' counts in Paternal and Maternal clusters to correct point phasing    
    /*
        1) WITHOUT CORRECTION:    
             Paternal cluster at position i: P=50, M=02, u=200
             Maternal cluster at position i: P=03, M=45, u=250           
        2) WITH    CORRECTION:
             Paternal cluster at position i: P=02, M=50, u=200
             Maternal cluster at position i: P=45, M=03, u=250  
        
        struct CLUSCNT
        {
            int Pcnt;
            int Mcnt;
            int ucnt;
        };               
    */
    if((*patGT).size() != (*matGT).size() )
    {
        cout << "   Error: inconsistency in haplotype lengths. " << endl;
        return false;
    } 
    unsigned long markerNum = (*patGT).size();
    // 0. initialization on counts for two clusters
    map<int, CLUSCNT> maClusterCnt;
    map<int, CLUSCNT> paClusterCnt;        
    for(int ci = 0; ci < markerNum; ci ++)
    {
        CLUSCNT posCNT;
        posCNT.Pcnt = 0;
        posCNT.Mcnt = 0;
        posCNT.ucnt = 0;
        paClusterCnt.insert(std::pair<int, CLUSCNT>(ci, posCNT));
        maClusterCnt.insert(std::pair<int, CLUSCNT>(ci, posCNT));        
    }
    //
    map<int, POLLEN>::iterator ppitr;
    map<int, POLLEN>::iterator ppitr_end;
    map<int, CLUSCNT>::iterator cntitr;
    // 1. check maternal cluster attached to 0_m_mkr: matGT
    ppitr     = maCluster.begin();
    ppitr_end = maCluster.end();
    while(ppitr != ppitr_end)
    {
        POLLEN ptmp         = (*ppitr).second;
        string this_pattern = ptmp.poPat; // MMMMPPMMMMMMuM...MMMuMMMM
        // check P/M/u
        for(int ci = 0; ci < markerNum; ci ++)
        {
            // get "P" or "M" at current position
            string posPattern = this_pattern.substr(ci, 1);
            CLUSCNT posCNT;
            get_PM_count(posPattern, &posCNT);            
            // 
            cntitr = maClusterCnt.find(ci);
            // update
            (*cntitr).second.Pcnt += posCNT.Pcnt;
            (*cntitr).second.Mcnt += posCNT.Mcnt;
            (*cntitr).second.ucnt += posCNT.ucnt;
        }
        //
        ppitr ++;
    }
    // 2. check paternal cluster attached to 0_p_mkr: patGT
    ppitr     = paCluster.begin();
    ppitr_end = paCluster.end();
    while(ppitr != ppitr_end)
    {
        POLLEN ptmp         = (*ppitr).second;
        string this_pattern = ptmp.poPat; // PPPPMMPPPuPPPP...PPPPPuPP
        // check P/M/u
        for(int ci = 0; ci < markerNum; ci ++)
        {
            // get "P" or "M" at current position
            string posPattern = this_pattern.substr(ci, 1);
            CLUSCNT posCNT;
            get_PM_count(posPattern, &posCNT);            
            // 
            cntitr = paClusterCnt.find(ci);
            // update
            (*cntitr).second.Pcnt += posCNT.Pcnt;
            (*cntitr).second.Mcnt += posCNT.Mcnt;
            (*cntitr).second.ucnt += posCNT.ucnt;
        }
        //
        ppitr ++;
    }
    // 3. correct haplotypes according to counts
    for(int ci=0; ci<markerNum; ci ++)
    {
        // get counts on P/M in paternal cluster for current position
        map<int, CLUSCNT>::iterator pacitr = paClusterCnt.find(ci);
        assert(pacitr != paClusterCnt.end() );
        CLUSCNT paPosCNT = (*pacitr).second;
        // get counts on P/M in maternal cluster for current position
        map<int, CLUSCNT>::iterator macitr = maClusterCnt.find(ci);
        assert(macitr != maClusterCnt.end() );
        CLUSCNT maPosCNT = (*macitr).second;     
        // swap paternal/maternal haplotypes
        if( (paPosCNT.Pcnt<paPosCNT.Mcnt) && 
            (maPosCNT.Pcnt>maPosCNT.Mcnt)    )
        {
            string mattype = (*matGT).substr(ci, 1); // "P/M" at maternal pattern
            string pattype = (*patGT).substr(ci, 1); // "P/M" at paternal pattern
            (*matGT).replace(ci, 1, pattype);
            (*patGT).replace(ci, 1, mattype);
        }
    }  
    cout << "   Check: 3rd corrected haplotypes: " << endl
         << "\t"  << *matGT                        << endl
         << "\t"  << *patGT                        << endl;
    //    
    return true;
}

// Assembly:
subq $0x468, %rsp            # imm = 0x468
movq %rdi, 0xa0(%rsp)
movq %rsi, 0xa8(%rsp)
movq %rdi, 0x458(%rsp)
movq %rsi, 0x450(%rsp)
movq %rdx, 0x448(%rsp)
movq %rcx, 0x440(%rsp)
movq 0x440(%rsp), %rdi
callq 0x3250
movq %rax, 0xb0(%rsp)
movq 0x448(%rsp), %rdi
callq 0x3250
movq %rax, %rcx
movq 0xb0(%rsp), %rax
cmpq %rcx, %rax
je 0x12258
movq 0x26da8(%rip), %rdi     # 0x38fd8
leaq 0x199b6(%rip), %rsi     # 0x2bbed
callq 0x3320
movq %rax, %rdi
movq 0x26d82(%rip), %rsi     # 0x38fc8
callq 0x3370
movb $0x0, 0x467(%rsp)
jmp 0x12cd0
movq 0x440(%rsp), %rdi
callq 0x3250
movq %rax, 0x438(%rsp)
leaq 0x408(%rsp), %rdi
callq 0x19ea0
leaq 0x3d8(%rsp), %rdi
callq 0x19ea0
movl $0x0, 0x3d4(%rsp)
movslq 0x3d4(%rsp), %rax
cmpq 0x438(%rsp), %rax
jae 0x123be
movl $0x0, 0x3c8(%rsp)
movl $0x0, 0x3cc(%rsp)
movl $0x0, 0x3d0(%rsp)
leaq 0x3b8(%rsp), %rdi
leaq 0x3d4(%rsp), %rsi
leaq 0x3c8(%rsp), %rdx
callq 0x19f00
jmp 0x122e8
leaq 0x3d8(%rsp), %rdi
leaq 0x3b8(%rsp), %rsi
callq 0x19eb0
movb %dl, 0x97(%rsp)
movq %rax, 0x98(%rsp)
jmp 0x1230e
movb 0x97(%rsp), %al
movq 0x98(%rsp), %rcx
movq %rcx, 0x398(%rsp)
movb %al, 0x3a0(%rsp)
leaq 0x388(%rsp), %rdi
leaq 0x3d4(%rsp), %rsi
leaq 0x3c8(%rsp), %rdx
callq 0x19f00
jmp 0x1234b
leaq 0x408(%rsp), %rdi
leaq 0x388(%rsp), %rsi
callq 0x19eb0
movb %dl, 0x87(%rsp)
movq %rax, 0x88(%rsp)
jmp 0x12371
movb 0x87(%rsp), %al
movq 0x88(%rsp), %rcx
movq %rcx, 0x378(%rsp)
movb %al, 0x380(%rsp)
movl 0x3d4(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x3d4(%rsp)
jmp 0x12292
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x3b0(%rsp)
movl %eax, 0x3ac(%rsp)
jmp 0x12cb4
leaq 0x370(%rsp), %rdi
callq 0x19200
leaq 0x368(%rsp), %rdi
callq 0x19200
leaq 0x360(%rsp), %rdi
callq 0x19f30
movq 0xa0(%rsp), %rdi
callq 0x19220
movq 0xa0(%rsp), %rdi
movq %rax, 0x358(%rsp)
movq 0x358(%rsp), %rax
movq %rax, 0x370(%rsp)
callq 0x19250
movq %rax, 0x350(%rsp)
movq 0x350(%rsp), %rax
movq %rax, 0x368(%rsp)
leaq 0x370(%rsp), %rdi
leaq 0x368(%rsp), %rsi
callq 0x19280
testb $0x1, %al
jne 0x1244d
jmp 0x12693
leaq 0x370(%rsp), %rdi
callq 0x192a0
movq %rax, %rsi
addq $0x8, %rsi
leaq 0x2d8(%rsp), %rdi
callq 0x192c0
jmp 0x12470
leaq 0x318(%rsp), %rsi
leaq 0x2b8(%rsp), %rdi
callq 0x3160
jmp 0x12487
movl $0x0, 0x2b4(%rsp)
movslq 0x2b4(%rsp), %rax
cmpq 0x438(%rsp), %rax
jae 0x1263e
movslq 0x2b4(%rsp), %rdx
leaq 0x290(%rsp), %rdi
leaq 0x2b8(%rsp), %rsi
movl $0x1, %ecx
callq 0x3350
jmp 0x124cc
leaq 0x260(%rsp), %rdi
leaq 0x290(%rsp), %rsi
callq 0x3160
jmp 0x124e3
leaq 0x260(%rsp), %rdi
leaq 0x284(%rsp), %rsi
callq 0x17d00
jmp 0x124fa
leaq 0x260(%rsp), %rdi
callq 0x31e0
leaq 0x408(%rsp), %rdi
leaq 0x2b4(%rsp), %rsi
callq 0x19f50
movq %rax, 0x78(%rsp)
jmp 0x12523
movq 0x78(%rsp), %rax
movq %rax, 0x258(%rsp)
movq 0x258(%rsp), %rax
movq %rax, 0x360(%rsp)
movl 0x284(%rsp), %eax
movl %eax, 0x6c(%rsp)
leaq 0x360(%rsp), %rdi
callq 0x19f80
movl 0x6c(%rsp), %ecx
addl 0x4(%rax), %ecx
movl %ecx, 0x4(%rax)
movl 0x288(%rsp), %eax
movl %eax, 0x70(%rsp)
leaq 0x360(%rsp), %rdi
callq 0x19f80
movl 0x70(%rsp), %ecx
addl 0x8(%rax), %ecx
movl %ecx, 0x8(%rax)
movl 0x28c(%rsp), %eax
movl %eax, 0x74(%rsp)
leaq 0x360(%rsp), %rdi
callq 0x19f80
movl 0x74(%rsp), %ecx
addl 0xc(%rax), %ecx
movl %ecx, 0xc(%rax)
leaq 0x290(%rsp), %rdi
callq 0x31e0
movl 0x2b4(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x2b4(%rsp)
jmp 0x12492
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x3b0(%rsp)
movl %eax, 0x3ac(%rsp)
jmp 0x12681
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x3b0(%rsp)
movl %eax, 0x3ac(%rsp)
jmp 0x12674
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x3b0(%rsp)
movl %eax, 0x3ac(%rsp)
jmp 0x1262f
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x3b0(%rsp)
movl %eax, 0x3ac(%rsp)
leaq 0x260(%rsp), %rdi
callq 0x31e0
leaq 0x290(%rsp), %rdi
callq 0x31e0
jmp 0x12674
leaq 0x370(%rsp), %rdi
xorl %esi, %esi
callq 0x193a0
movq %rax, 0x250(%rsp)
leaq 0x2b8(%rsp), %rdi
callq 0x31e0
leaq 0x2d8(%rsp), %rdi
callq 0x18df0
jmp 0x1242f
leaq 0x2b8(%rsp), %rdi
callq 0x31e0
leaq 0x2d8(%rsp), %rdi
callq 0x18df0
jmp 0x12cb4
movq 0xa8(%rsp), %rdi
callq 0x19220
movq 0xa8(%rsp), %rdi
movq %rax, 0x248(%rsp)
movq 0x248(%rsp), %rax
movq %rax, 0x370(%rsp)
callq 0x19250
movq %rax, 0x240(%rsp)
movq 0x240(%rsp), %rax
movq %rax, 0x368(%rsp)
leaq 0x370(%rsp), %rdi
leaq 0x368(%rsp), %rsi
callq 0x19280
testb $0x1, %al
jne 0x126fb
jmp 0x12941
leaq 0x370(%rsp), %rdi
callq 0x192a0
movq %rax, %rsi
addq $0x8, %rsi
leaq 0x1c8(%rsp), %rdi
callq 0x192c0
jmp 0x1271e
leaq 0x208(%rsp), %rsi
leaq 0x1a8(%rsp), %rdi
callq 0x3160
jmp 0x12735
movl $0x0, 0x1a4(%rsp)
movslq 0x1a4(%rsp), %rax
cmpq 0x438(%rsp), %rax
jae 0x128ec
movslq 0x1a4(%rsp), %rdx
leaq 0x180(%rsp), %rdi
leaq 0x1a8(%rsp), %rsi
movl $0x1, %ecx
callq 0x3350
jmp 0x1277a
leaq 0x150(%rsp), %rdi
leaq 0x180(%rsp), %rsi
callq 0x3160
jmp 0x12791
leaq 0x150(%rsp), %rdi
leaq 0x174(%rsp), %rsi
callq 0x17d00
jmp 0x127a8
leaq 0x150(%rsp), %rdi
callq 0x31e0
leaq 0x3d8(%rsp), %rdi
leaq 0x1a4(%rsp), %rsi
callq 0x19f50
movq %rax, 0x60(%rsp)
jmp 0x127d1
movq 0x60(%rsp), %rax
movq %rax, 0x148(%rsp)
movq 0x148(%rsp), %rax
movq %rax, 0x360(%rsp)
movl 0x174(%rsp), %eax
movl %eax, 0x54(%rsp)
leaq 0x360(%rsp), %rdi
callq 0x19f80
movl 0x54(%rsp), %ecx
addl 0x4(%rax), %ecx
movl %ecx, 0x4(%rax)
movl 0x178(%rsp), %eax
movl %eax, 0x58(%rsp)
leaq 0x360(%rsp), %rdi
callq 0x19f80
movl 0x58(%rsp), %ecx
addl 0x8(%rax), %ecx
movl %ecx, 0x8(%rax)
movl 0x17c(%rsp), %eax
movl %eax, 0x5c(%rsp)
leaq 0x360(%rsp), %rdi
callq 0x19f80
movl 0x5c(%rsp), %ecx
addl 0xc(%rax), %ecx
movl %ecx, 0xc(%rax)
leaq 0x180(%rsp), %rdi
callq 0x31e0
movl 0x1a4(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x1a4(%rsp)
jmp 0x12740
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x3b0(%rsp)
movl %eax, 0x3ac(%rsp)
jmp 0x1292f
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x3b0(%rsp)
movl %eax, 0x3ac(%rsp)
jmp 0x12922
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x3b0(%rsp)
movl %eax, 0x3ac(%rsp)
jmp 0x128dd
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x3b0(%rsp)
movl %eax, 0x3ac(%rsp)
leaq 0x150(%rsp), %rdi
callq 0x31e0
leaq 0x180(%rsp), %rdi
callq 0x31e0
jmp 0x12922
leaq 0x370(%rsp), %rdi
xorl %esi, %esi
callq 0x193a0
movq %rax, 0x140(%rsp)
leaq 0x1a8(%rsp), %rdi
callq 0x31e0
leaq 0x1c8(%rsp), %rdi
callq 0x18df0
jmp 0x126dd
leaq 0x1a8(%rsp), %rdi
callq 0x31e0
leaq 0x1c8(%rsp), %rdi
callq 0x18df0
jmp 0x12cb4
movl $0x0, 0x13c(%rsp)
movslq 0x13c(%rsp), %rax
cmpq 0x438(%rsp), %rax
jae 0x12bd1
leaq 0x3d8(%rsp), %rdi
leaq 0x13c(%rsp), %rsi
callq 0x19f50
movq %rax, 0x48(%rsp)
jmp 0x1297e
movq 0x48(%rsp), %rax
movq %rax, 0x130(%rsp)
leaq 0x3d8(%rsp), %rdi
callq 0x19fc0
movq %rax, 0x128(%rsp)
leaq 0x130(%rsp), %rdi
leaq 0x128(%rsp), %rsi
callq 0x19fa0
testb $0x1, %al
jne 0x129bb
jmp 0x129bd
jmp 0x129dc
leaq 0x19258(%rip), %rdi     # 0x2bc1c
leaq 0x19098(%rip), %rsi     # 0x2ba63
movl $0x6a5, %edx            # imm = 0x6A5
leaq 0x19262(%rip), %rcx     # 0x2bc39
callq 0x3210
leaq 0x130(%rsp), %rdi
callq 0x19f80
movl 0xc(%rax), %ecx
movl %ecx, 0x120(%rsp)
movq 0x4(%rax), %rax
movq %rax, 0x118(%rsp)
leaq 0x408(%rsp), %rdi
leaq 0x13c(%rsp), %rsi
callq 0x19f50
movq %rax, 0x40(%rsp)
jmp 0x12a1b
movq 0x40(%rsp), %rax
movq %rax, 0x110(%rsp)
leaq 0x408(%rsp), %rdi
callq 0x19fc0
movq %rax, 0x108(%rsp)
leaq 0x110(%rsp), %rdi
leaq 0x108(%rsp), %rsi
callq 0x19fa0
testb $0x1, %al
jne 0x12a58
jmp 0x12a5a
jmp 0x12a79
leaq 0x1923a(%rip), %rdi     # 0x2bc9b
leaq 0x18ffb(%rip), %rsi     # 0x2ba63
movl $0x6a9, %edx            # imm = 0x6A9
leaq 0x191c5(%rip), %rcx     # 0x2bc39
callq 0x3210
leaq 0x110(%rsp), %rdi
callq 0x19f80
movq 0x4(%rax), %rcx
movq %rcx, 0xfc(%rsp)
movl 0xc(%rax), %eax
movl %eax, 0x104(%rsp)
movl 0x118(%rsp), %eax
cmpl 0x11c(%rsp), %eax
jge 0x12bb9
movl 0xfc(%rsp), %eax
cmpl 0x100(%rsp), %eax
jle 0x12bb9
movq 0x448(%rsp), %rsi
movslq 0x13c(%rsp), %rdx
leaq 0xd8(%rsp), %rdi
movl $0x1, %ecx
callq 0x3350
jmp 0x12ae8
movq 0x440(%rsp), %rsi
movslq 0x13c(%rsp), %rdx
leaq 0xb8(%rsp), %rdi
movl $0x1, %ecx
callq 0x3350
jmp 0x12b0c
movq 0x448(%rsp), %rdi
movslq 0x13c(%rsp), %rsi
movl $0x1, %edx
leaq 0xb8(%rsp), %rcx
callq 0x3130
jmp 0x12b30
movq 0x440(%rsp), %rdi
movslq 0x13c(%rsp), %rsi
movl $0x1, %edx
leaq 0xd8(%rsp), %rcx
callq 0x3130
jmp 0x12b54
leaq 0xb8(%rsp), %rdi
callq 0x31e0
leaq 0xd8(%rsp), %rdi
callq 0x31e0
jmp 0x12bb9
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x3b0(%rsp)
movl %eax, 0x3ac(%rsp)
jmp 0x12ba7
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x3b0(%rsp)
movl %eax, 0x3ac(%rsp)
leaq 0xb8(%rsp), %rdi
callq 0x31e0
leaq 0xd8(%rsp), %rdi
callq 0x31e0
jmp 0x12cb4
jmp 0x12bbb
movl 0x13c(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x13c(%rsp)
jmp 0x1294c
movq 0x26400(%rip), %rdi     # 0x38fd8
leaq 0x190d9(%rip), %rsi     # 0x2bcb8
callq 0x3320
movq %rax, 0x38(%rsp)
jmp 0x12beb
movq 0x38(%rsp), %rdi
movq 0x263d1(%rip), %rsi     # 0x38fc8
callq 0x3370
movq %rax, 0x30(%rsp)
jmp 0x12c03
movq 0x30(%rsp), %rdi
leaq 0x19251(%rip), %rsi     # 0x2be60
callq 0x3320
movq %rax, 0x28(%rsp)
jmp 0x12c1b
movq 0x28(%rsp), %rdi
movq 0x448(%rsp), %rsi
callq 0x32e0
movq %rax, 0x20(%rsp)
jmp 0x12c34
movq 0x20(%rsp), %rdi
movq 0x26388(%rip), %rsi     # 0x38fc8
callq 0x3370
movq %rax, 0x18(%rsp)
jmp 0x12c4c
movq 0x18(%rsp), %rdi
leaq 0x19208(%rip), %rsi     # 0x2be60
callq 0x3320
movq %rax, 0x10(%rsp)
jmp 0x12c64
movq 0x10(%rsp), %rdi
movq 0x440(%rsp), %rsi
callq 0x32e0
movq %rax, 0x8(%rsp)
jmp 0x12c7d
movq 0x8(%rsp), %rdi
movq 0x2633f(%rip), %rsi     # 0x38fc8
callq 0x3370
jmp 0x12c90
movb $0x1, 0x467(%rsp)
leaq 0x3d8(%rsp), %rdi
callq 0x19ff0
leaq 0x408(%rsp), %rdi
callq 0x19ff0
jmp 0x12cd0
leaq 0x3d8(%rsp), %rdi
callq 0x19ff0
leaq 0x408(%rsp), %rdi
callq 0x19ff0
jmp 0x12ce1
movb 0x467(%rsp), %al
andb $0x1, %al
addq $0x468, %rsp            # imm = 0x468
retq
movq 0x3b0(%rsp), %rdi
callq 0x3560
nop