// calcInChunck does calculation in a chunck of SNPs. func (cmd *cmdCt) calcInChunck(snpChan chan *pileup.SNP) *calc.Calculator { // Create job channel. // Each job is a array of SNPs, which we will calculate // correlations of the first SNP with the rest ones. jobChan := make(chan []*pileup.SNP) go func() { defer close(jobChan) arr := []*pileup.SNP{} for s := range snpChan { arr = append(arr, s) lag := s.Pos - arr[0].Pos if lag < 0 { cmd.panic("SNPs are not in order.") } if lag >= cmd.maxl { jobChan <- arr arr = arr[1:] } } jobChan <- arr }() // Make ncpu workers. // For each worker, do the calculation, // and push the result into a channel. ncpu := runtime.GOMAXPROCS(0) c := make(chan *calc.Calculator) for i := 0; i < ncpu; i++ { go func() { covs := calc.New(cmd.maxl) maxN := 10000 xArr := make([]float64, maxN) yArr := make([]float64, maxN) for arr := range jobChan { cmd.calcSNPArr(arr, covs, xArr, yArr) } c <- covs }() } // Wait for all the worker, // and collect their results. var covs *calc.Calculator for i := 0; i < ncpu; i++ { cc := <-c if i == 0 { covs = cc } else { covs.Append(cc) } } return covs }
// calcSNPArr calculate correlation of the first SNP with the rest. // It finds pairs of bases that are from the same read, // compare every two pairs of bases, // and compute several correlations, which is contained in a calculator. // A calculator here is a black box. // calcSNPArr only push inputs into the calculator. func (cmd *cmdCt) calcSNPArr(snpArr []*pileup.SNP, calculator *calc.Calculator, xArr, yArr []float64) { s1 := snpArr[0] m := make(map[string]pileup.Allele) for _, a := range s1.Alleles { if isATGC(a.Base) { m[a.QName] = a } } pairs := make([]AllelePair, len(m)) for k := 0; k < len(snpArr); k++ { s2 := snpArr[k] // double check the lag. // it expects an order array of SNPs. l := s2.Pos - s1.Pos if l >= cmd.maxl { break } else if l < 0 { cmd.panic("SNPs is not in order.") } numPair := cmd.findPairs(m, s2.Alleles, pairs) // check the coverage. // if less than min coverage, skip. if numPair < cmd.minCoverage { continue } k := 0 for i := 0; i < numPair && k < len(xArr); i++ { p1 := pairs[i] for j := i + 1; j < numPair && k < len(xArr); j++ { p2 := pairs[j] x := cmd.diffBases(p1.A.Base, p2.A.Base) y := cmd.diffBases(p1.B.Base, p2.B.Base) xArr[k] = x yArr[k] = y k++ } } calculator.Increment(xArr[:k], yArr[:k], l) } }