github.com/vertgenlab/gonomics@v1.0.0/genomeGraph/path.go (about)

     1  package genomeGraph
     2  
     3  import (
     4  	"bytes"
     5  	"fmt"
     6  	"github.com/vertgenlab/gonomics/cigar"
     7  	"github.com/vertgenlab/gonomics/dna"
     8  	"github.com/vertgenlab/gonomics/giraf"
     9  	"github.com/vertgenlab/gonomics/numbers/parse"
    10  	"github.com/vertgenlab/gonomics/sam"
    11  	"strings"
    12  )
    13  
    14  func PathToSeq(p giraf.Path, genome *GenomeGraph) []dna.Base {
    15  	if len(p.Nodes) == 1 {
    16  		answer := make([]dna.Base, p.TEnd-p.TStart)
    17  		copy(answer, genome.Nodes[p.Nodes[0]].Seq[p.TStart:p.TEnd])
    18  		return answer
    19  	} else {
    20  		answer := make([]dna.Base, len(genome.Nodes[p.Nodes[0]].Seq)-p.TStart)
    21  		copy(answer, genome.Nodes[p.Nodes[0]].Seq[p.TStart:])
    22  		for i := 1; i < len(p.Nodes)-1; i++ {
    23  			answer = append(answer, genome.Nodes[p.Nodes[i]].Seq...)
    24  		}
    25  		answer = append(answer, genome.Nodes[p.Nodes[len(p.Nodes)-1]].Seq[:p.TEnd]...)
    26  		return answer
    27  	}
    28  }
    29  
    30  func ViewGraphAlignment(g *giraf.Giraf, genome *GenomeGraph) string {
    31  	var seqOne, seqTwo bytes.Buffer
    32  	var i int = g.Path.TStart
    33  	var j int = g.QStart
    34  
    35  	var count int
    36  	var alpha []dna.Base = PathToSeq(g.Path, genome)
    37  	var beta []dna.Base = g.Seq
    38  	for _, operation := range g.Cigar {
    39  		for count = 0; count < int(operation.RunLen); count++ {
    40  			switch operation.Op {
    41  			case 'M':
    42  				seqOne.WriteRune(dna.BaseToRune(alpha[i]))
    43  				seqTwo.WriteRune(dna.BaseToRune(beta[j]))
    44  				i, j = i+1, j+1
    45  			case 'I':
    46  				seqOne.WriteRune('-')
    47  				seqTwo.WriteRune(dna.BaseToRune(beta[j]))
    48  				j++
    49  			case 'D':
    50  				seqOne.WriteRune(dna.BaseToRune(alpha[i]))
    51  				seqTwo.WriteRune('-')
    52  				i++
    53  			case 'S':
    54  				seqOne.WriteRune('-')
    55  				seqTwo.WriteRune('-')
    56  			}
    57  		}
    58  	} /*
    59  		var lineLength int64 = 50
    60  		var k, pos int
    61  		var prettySeq string = ""
    62  		pos = addStartChrPos(samLine) + samLine.Pos
    63  		for k = 0; k < int64(len(seqOne.String())); k += lineLength {
    64  
    65  			if k+lineLength > int64(len(seqOne.String())) && k+lineLength > int64(len(seqTwo.String())) {
    66  
    67  				prettySeq += fmt.Sprintf("%s:\t[%d-%d]\n", samLine.RName, k+pos, k+lineLength+pos) + fmt.Sprintf("%s\n", seqOne.String()[k:]) + fmt.Sprintf("%s\n", seqTwo.String()[k:])
    68  			} else {
    69  				prettySeq += fmt.Sprintf("%s:\t[%d-%d]\n", samLine.RName, k+pos, k+lineLength+pos) + fmt.Sprintf("%s\n", seqOne.String()[k:k+lineLength]) + fmt.Sprintf("%s\n", seqTwo.String()[k:k+lineLength])
    70  			}
    71  		}*/
    72  	//return fmt.Sprintf("%s\n%s", ModifySamToString(samLine, false, true, true, false, true, false, false, false, false, false, true), prettySeq)
    73  	return fmt.Sprintf("%s\n%s", seqOne.String(), seqTwo.String())
    74  }
    75  
    76  /*
    77  func StringToPath(allPaths string) []uint32 {
    78  	words := strings.Split(allPaths[5:], ":")
    79  	answer := make([]uint32, len(words))
    80  	if strings.Compare(words[0], "-1") == 0 {
    81  		return nil
    82  	} else {
    83  		for i := 0; i < len(words); i++ {
    84  			answer[i] = common.StringToUint32(words[i])
    85  		}
    86  	}
    87  	return answer
    88  }*/
    89  
    90  func addStartChrPos(samfile sam.Sam) int {
    91  	var answer int = 0
    92  	if strings.Contains(samfile.Extra, "XO:i:") {
    93  		words := strings.Split(samfile.Extra, "\t")
    94  		answer = parse.StringToInt(words[2][5:])
    95  	}
    96  	return answer
    97  }
    98  
    99  func ModifySamToString(aln sam.Sam, samflag bool, rname bool, pos bool, mapq bool, cig bool, rnext bool, pnext bool, tlen bool, seq bool, qual bool, extra bool) string {
   100  	var answer string = fmt.Sprintf("%s\n\n", aln.QName)
   101  	if samflag {
   102  		answer += fmt.Sprintf("%d\n", aln.Flag)
   103  	}
   104  	if rname {
   105  		answer += fmt.Sprintf("%s\t", aln.RName)
   106  	}
   107  	if pos {
   108  		aln.Pos += uint32(addStartChrPos(aln))
   109  		answer += fmt.Sprintf("%d\t", aln.Pos)
   110  	}
   111  	if mapq {
   112  		answer += fmt.Sprintf("%d\t", aln.MapQ)
   113  	}
   114  	if cig {
   115  		answer += fmt.Sprintf("%s\t", cigar.ToString(aln.Cigar))
   116  	}
   117  	if rnext {
   118  		answer += fmt.Sprintf("%s\t", aln.RNext)
   119  	}
   120  	if pnext {
   121  		answer += fmt.Sprintf("%d\t", aln.PNext)
   122  	}
   123  	if tlen {
   124  		answer += fmt.Sprintf("%d\t", aln.TLen)
   125  	}
   126  	if seq {
   127  		answer += fmt.Sprintf("%s\t", dna.BasesToString(aln.Seq))
   128  	}
   129  	if qual {
   130  		answer += fmt.Sprintf("%s\t", string(aln.Qual))
   131  	}
   132  	if extra {
   133  		words := strings.Split(aln.Extra, "\t")
   134  		for _, text := range words[:len(words)-1] {
   135  			if strings.Contains(text, "GP:Z:") {
   136  				answer += fmt.Sprintf("GP:Z:\n%s", pathPrettyString(text[5:]))
   137  			} else {
   138  				answer += fmt.Sprintf("%s\t", text)
   139  			}
   140  		}
   141  	}
   142  	return answer
   143  }
   144  
   145  func pathPrettyString(graphPath string) string {
   146  	var s string = ""
   147  	words := strings.Split(graphPath, ":")
   148  	var i, j int
   149  	for i = 0; i < len(words); i += 8 {
   150  		var line string = ""
   151  		if i+8 > len(words) {
   152  			line += words[i]
   153  			for j = i + 1; j < len(words)-1; j++ {
   154  				line += words[j]
   155  			}
   156  			s += fmt.Sprintf("%s\n", line)
   157  		} else {
   158  			line += words[i]
   159  			for j = i + 1; j < i+8; j++ {
   160  				line += fmt.Sprintf(":%s", words[j])
   161  			}
   162  			s += fmt.Sprintf("%s\n", line)
   163  		}
   164  	}
   165  	return s
   166  }
   167  
   168  func AddPath(allPaths []uint32, newPath uint32) []uint32 {
   169  	if len(allPaths) == 0 {
   170  		allPaths = append(allPaths, newPath)
   171  	} else if allPaths[len(allPaths)-1] == newPath {
   172  		return allPaths
   173  	} else {
   174  		allPaths = append(allPaths, newPath)
   175  	}
   176  	return allPaths
   177  }
   178  
   179  func CatPaths(currPaths []uint32, newPaths []uint32) []uint32 {
   180  	if len(newPaths) == 0 {
   181  		return currPaths
   182  	} else if len(currPaths) == 0 {
   183  		return newPaths
   184  	} else {
   185  		currPaths = AddPath(currPaths, newPaths[0])
   186  		currPaths = append(currPaths, newPaths[1:]...)
   187  		return currPaths
   188  	}
   189  }
   190  
   191  func reversePath(alpha []uint32) {
   192  	for i, j := 0, len(alpha)-1; i < j; i, j = i+1, j-1 {
   193  		alpha[i], alpha[j] = alpha[j], alpha[i]
   194  	}
   195  }
   196  
   197  func PathToString(allPaths []uint32) string {
   198  	var s string = ""
   199  	if allPaths == nil {
   200  		return s
   201  	} else {
   202  		s += fmt.Sprint(allPaths[0])
   203  		if len(allPaths) > 1 {
   204  			for i := 1; i < len(allPaths); i++ {
   205  				s += ":" + fmt.Sprint(allPaths[i])
   206  			}
   207  		}
   208  	}
   209  	return s
   210  }
   211  
   212  func getSeedPath(seed *SeedDev) []uint32 {
   213  	var path []uint32 = []uint32{seed.TargetId}
   214  	if seed.NextPart == nil {
   215  		return path
   216  	} else {
   217  		path = append(path, getSeedPath(seed.NextPart)...)
   218  	}
   219  	return path
   220  }
   221  
   222  func getStartRead(aln *sam.Sam) int64 {
   223  	var alignedPos int = 0
   224  	if aln.Cigar[0].Op == 'S' {
   225  		alignedPos += aln.Cigar[0].RunLength
   226  	}
   227  	return int64(alignedPos)
   228  }