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 }