Beispiel #1
0
// 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,
	}
}
Beispiel #2
0
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
	}
}
Beispiel #3
0
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
}
Beispiel #4
0
// 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
}