// Create a new KmerRainbow defined by the rectangle r, kmerindex index and background color. func NewKmerRainbow(r image.Rectangle, index *kmerindex.Index, background color.HSVA) *KmerRainbow { // should generalise the BG color h := r.Dy() kmers := make([]int, h) kmask := util.Pow4(index.GetK()) kmaskf := float64(kmask) f := func(index *kmerindex.Index, _, kmer int) { kmers[int(float64(kmer)*float64(h)/kmaskf)]++ } index.ForEachKmerOf(index.Seq, 0, index.Seq.Len(), f) max := util.Max(kmers...) return &KmerRainbow{ RGBA: image.NewRGBA(r), Index: index, Max: max, BackGround: background, } }
func processServer(index interval.Tree, queue, output chan *feat.Feature, wg *sync.WaitGroup) { defer wg.Done() var ( buffer []byte = make([]byte, 0, annotationLength) annotations Matches = make(Matches, 0, maxAnnotations+1) o *Overlap = &Overlap{&annotations} prefix string = ` ; Annot "` blank string = prefix + strings.Repeat("-", mapLength) overlap int ) for feature := range queue { annotations = annotations[:0] heap.Init(&Overlap{&annotations}) buffer = buffer[:0] buffer = append(buffer, []byte(blank)...) if query, err := interval.New(string(feature.Location), feature.Start, feature.End, 0, nil); err != nil { fmt.Fprintf(os.Stderr, "Feature has end < start: %v\n", feature) continue } else { overlap = int(float64(feature.Len()) * minOverlap) if results := index.Intersect(query, overlap); results != nil { for hit := range results { o.Push(Match{ Interval: hit, Overlap: util.Min(hit.End(), query.End()) - util.Max(hit.Start(), query.Start()), Strand: feature.Strand, }) if len(annotations) > maxAnnotations { o.Pop() } } } } if len(annotations) > 0 { sort.Sort(&Start{&annotations}) buffer = makeAnnotation(feature, annotations, len(prefix), buffer) } buffer = append(buffer, '"') feature.Attributes += string(buffer) output <- feature } }
func makeAnnotation(feature *feat.Feature, annotations Matches, prefixLen int, buffer []byte) []byte { var ( annot []byte = buffer[prefixLen:] repRecord RepeatRecord repLocation *interval.Interval start, end, length int repStart, repEnd, repLeft, repLength int leftMargin, rightMargin float64 leftEnd, rightEnd bool mapStart, mapEnd int fullRepLength, repMissing int i int cLower, cUpper byte p string ) length = feature.Len() for annotIndex, repeat := range annotations { repRecord = repeat.Interval.Meta.(RepeatRecord) repLocation = repeat.Interval start = util.Max(repLocation.Start(), feature.Start) end = util.Min(repLocation.End(), feature.End) if repStart = repRecord.Start; repStart != -1 { repEnd = repRecord.End repLeft = repRecord.Left repLength = repStart + repLeft - 1 if repLength <= 0 { repLength = 9999 } if repLocation.Start() < feature.Start { repStart += feature.Start - repLocation.Start() } if repLocation.End() > feature.End { repEnd -= repLocation.End() - feature.End } leftMargin = float64(repStart) / float64(repLength) rightMargin = float64(repLeft) / float64(repLength) leftEnd = (leftMargin <= maxMargin) rightEnd = (rightMargin <= maxMargin) } mapStart = ((start - feature.Start) * mapLength) / length mapEnd = ((end - feature.Start) * mapLength) / length if feature.Strand == -1 { mapStart, mapEnd = mapLength-mapEnd-1, mapLength-mapStart-1 } if mapStart < 0 || mapStart >= mapLength || mapEnd < 0 || mapEnd >= mapLength { fmt.Printf("mapStart: %d, mapEnd: %d, mapLength: %d\n", mapStart, mapEnd, mapLength) panic("MakeAnnot: failed to map") } cLower = 'a' + byte(annotIndex) cUpper = 'A' + byte(annotIndex) if leftEnd { annot[mapStart] = cUpper } else { annot[mapStart] = cLower } for i = mapStart + 1; i <= mapEnd-1; i++ { annot[i] = cLower } if rightEnd { annot[mapEnd] = cUpper } else { annot[mapEnd] = cLower } buffer = append(buffer, ' ') buffer = append(buffer, []byte(repRecord.Name)...) if repRecord.Start >= 0 { fullRepLength = repRecord.End + repLeft repMissing = repRecord.Start + repLeft if feature.Start > repLocation.Start() { repMissing += feature.Start - repLocation.Start() } if repLocation.End() > feature.End { repMissing += repLocation.End() - feature.End } p = fmt.Sprintf("(%.0f%%)", ((float64(fullRepLength)-float64(repMissing))*100)/float64(fullRepLength)) buffer = append(buffer, []byte(p)...) } } return buffer }
// Method to align two sequences using the Smith-Waterman algorithm. Returns an alignment or an error // if the scoring matrix is not square. func (self *Aligner) Align(reference, query *seq.Seq) (aln seq.Alignment, err error) { gap := len(self.Matrix) - 1 for _, row := range self.Matrix { if len(row) != gap+1 { return nil, bio.NewError("Scoring matrix is not square.", 0, self.Matrix) } } r, c := reference.Len()+1, query.Len()+1 table := make([][]int, r) for i := range table { table[i] = make([]int, c) } var scores [3]int for i := 1; i < r; i++ { for j := 1; j < c; j++ { if rVal, qVal := self.LookUp.ValueToCode[reference.Seq[i-1]], self.LookUp.ValueToCode[query.Seq[j-1]]; rVal < 0 || qVal < 0 { continue } else { scores[diag] = table[i-1][j-1] + self.Matrix[rVal][qVal] scores[up] = table[i-1][j] + self.Matrix[rVal][gap] scores[left] = table[i][j-1] + self.Matrix[gap][qVal] table[i][j] = util.Max(scores[:]...) } } } refAln := &seq.Seq{ID: reference.ID, Seq: make([]byte, 0, reference.Len())} queryAln := &seq.Seq{ID: query.ID, Seq: make([]byte, 0, query.Len())} i, j := r-1, c-1 for i > 0 && j > 0 { if rVal, qVal := self.LookUp.ValueToCode[reference.Seq[i-1]], self.LookUp.ValueToCode[query.Seq[j-1]]; rVal < 0 || qVal < 0 { continue } else { scores[diag] = table[i-1][j-1] + self.Matrix[rVal][qVal] scores[up] = table[i-1][j] + self.Matrix[gap][qVal] scores[left] = table[i][j-1] + self.Matrix[rVal][gap] switch d := maxIndex(scores[:]); d { case diag: i-- j-- refAln.Seq = append(refAln.Seq, reference.Seq[i]) queryAln.Seq = append(queryAln.Seq, query.Seq[j]) case up: i-- refAln.Seq = append(refAln.Seq, reference.Seq[i]) queryAln.Seq = append(queryAln.Seq, self.GapChar) case left: j-- queryAln.Seq = append(queryAln.Seq, query.Seq[j]) refAln.Seq = append(refAln.Seq, self.GapChar) } } } for ; i > 0; i-- { refAln.Seq = append(refAln.Seq, reference.Seq[i-1]) queryAln.Seq = append(queryAln.Seq, self.GapChar) } for ; j > 0; j-- { refAln.Seq = append(refAln.Seq, self.GapChar) queryAln.Seq = append(queryAln.Seq, query.Seq[j-1]) } for i, j := 0, len(refAln.Seq)-1; i < j; i, j = i+1, j-1 { refAln.Seq[i], refAln.Seq[j] = refAln.Seq[j], refAln.Seq[i] } for i, j := 0, len(queryAln.Seq)-1; i < j; i, j = i+1, j-1 { queryAln.Seq[i], queryAln.Seq[j] = queryAln.Seq[j], queryAln.Seq[i] } aln = seq.Alignment{refAln, queryAln} return }