예제 #1
0
파일: map.go 프로젝트: frogs/biogo
// Map routines to iterate a function over an array, potentially splitting the array slice into
// chunks so that each chunk is processed concurrently. When using concurrent processing the
// Chunk size is either the nearest even division of the total array over the chosen concurrent
// processing goroutines or a specified maximum chunk size, whichever is smaller. Reducing
// chunk size can reduce the impact of divergence in time for processing chunks, but may add
// to overhead.
func Map(set Mapper, threads, maxChunkSize int) (results []interface{}, err error) {
	queue := make(chan Operator, 1)
	p := NewProcessor(queue, 0, threads)
	defer p.Stop()

	chunkSize := util.Min(int(math.Ceil(float64(set.Len())/float64(threads))), maxChunkSize)

	quit := make(chan struct{})

	go func() {
		for s := 0; s*chunkSize < set.Len(); s++ {
			select {
			case <-quit:
				break
			default:
				endChunk := util.Min(chunkSize*(s+1), set.Len())
				queue <- set.Slice(chunkSize*s, endChunk)
			}
		}
	}()

	for r := 0; r*chunkSize < set.Len(); r++ {
		result := <-p.out
		if result.Err != nil {
			err = bio.NewError("Map failed", 0, err)
			close(quit)
			break
		}
		results = append(results, result.Value)
	}

	return
}
예제 #2
0
파일: utils.go 프로젝트: frogs/biogo
// Stitch provides a function that may be used by polymer types to implement Stitcher.
// It makes use of reflection and so may be slower than type-specific implementations.
// This is the reference implementation and should be used to compare type-specific
// implementation against in testing.
func Stitch(pol interface{}, offset int, f feat.FeatureSet) (s interface{}, err error) {
	t := interval.NewTree()
	var i *interval.Interval

	for _, feature := range f {
		i, err = interval.New(emptyString, feature.Start, feature.End, 0, nil)
		if err != nil {
			return
		} else {
			t.Insert(i)
		}
	}

	pv := reflect.ValueOf(pol)
	pLen := pv.Len()
	end := pLen + offset
	span, err := interval.New(emptyString, offset, end, 0, nil)
	if err != nil {
		panic("Sequence.End() < Sequence.Start()")
	}
	fs, _ := t.Flatten(span, 0, 0)
	l := 0

	for _, seg := range fs {
		l += util.Min(seg.End(), end) - util.Max(seg.Start(), offset)
	}
	tv := reflect.MakeSlice(pv.Type(), 0, l)

	for _, seg := range fs {
		tv = reflect.AppendSlice(tv, pv.Slice(util.Max(seg.Start()-offset, 0), util.Min(seg.End()-offset, pLen)))
	}

	return tv.Interface(), nil
}
예제 #3
0
파일: packed.go 프로젝트: frogs/biogo
// Join segments of the sequence, returning any error.
func (self *Seq) Compose(f feat.FeatureSet) (err error) {
	l := 0
	for _, seg := range f {
		if seg.End < seg.Start {
			return bio.NewError("Feature end < start", 0, seg)
		}
		l += util.Min(seg.End, self.End()) - util.Max(seg.Start, self.Start())
	}

	t := &Seq{}
	*t = *self
	t.S = &Packing{Letters: make([]alphabet.Pack, 0, (l+3)/4)}

	var tseg seq.Sequence
	for _, seg := range f {
		tseg, err = self.Subseq(util.Max(seg.Start, self.Start()), util.Min(seg.End, self.End()))
		if err != nil {
			return
		}
		tseg := tseg.(*Seq)
		if seg.Strand == -1 {
			tseg.RevComp()
		}
		tseg.S.Align(seq.Start)
		t.S.Align(seq.End)
		t.S.Letters = append(t.S.Letters, tseg.S.Letters...)
		t.S.RightPad = tseg.S.RightPad
	}

	*self = *t

	return
}
예제 #4
0
파일: interval.go 프로젝트: frogs/biogo
func (self *Interval) adjustRange() {
	if self.left != nil && self.right != nil {
		self.minStart = util.Min(self.start, self.left.minStart)
		self.maxEnd = util.Max(self.end, self.left.maxEnd, self.right.maxEnd)
	} else if self.left != nil {
		self.minStart = util.Min(self.start, self.left.minStart)
		self.maxEnd = util.Max(self.end, self.left.maxEnd)
	} else if self.right != nil {
		self.minStart = util.Min(self.start, self.right.minStart)
		self.maxEnd = util.Max(self.end, self.right.maxEnd)
	}
}
예제 #5
0
파일: multi.go 프로젝트: frogs/biogo
func (self *Multi) Stitch(f feat.FeatureSet) (err error) {
	tr := interval.NewTree()
	var i *interval.Interval

	for _, feature := range f {
		i, err = interval.New(emptyString, feature.Start, feature.End, 0, nil)
		if err != nil {
			return
		} else {
			tr.Insert(i)
		}
	}

	span, err := interval.New(emptyString, self.Start(), self.End(), 0, nil)
	if err != nil {
		panic("Sequence.End() < Sequence.Start()")
	}
	fs, _ := tr.Flatten(span, 0, 0)

	ff := feat.FeatureSet{}
	for _, seg := range fs {
		ff = append(ff, &feat.Feature{
			Start: util.Max(seg.Start(), self.Start()),
			End:   util.Min(seg.End(), self.End()),
		})
	}

	return self.Compose(ff)
}
예제 #6
0
파일: seq.go 프로젝트: frogs/biogo
func (self *Seq) stitch(f []*interval.Interval) (ts []byte) {
	for _, seg := range f {
		ts = append(ts, self.Seq[util.Max(seg.Start()-self.Offset, 0):util.Min(seg.End()-self.Offset, len(self.Seq))]...)
	}

	return
}
예제 #7
0
파일: packseqs.go 프로젝트: frogs/biogo
// Pack a sequence into the Packed sequence. Returns a string giving diagnostic information.
func (pa *Packer) Pack(sequence *seq.Seq) string {
	m := pa.Packed.Meta.(seqMap)

	c := contig{seq: sequence}

	padding := binSize - sequence.Len()%binSize
	if padding < minPadding {
		padding += binSize
	}

	pa.length += pa.lastPad
	c.from = pa.length
	pa.length += sequence.Len()
	pa.lastPad = padding

	bins := make([]int, (padding+sequence.Len())/binSize)
	for i := 0; i < len(bins); i++ {
		bins[i] = len(m.contigs)
	}

	m.binMap = append(m.binMap, bins...)
	m.contigs = append(m.contigs, c)
	pa.Packed.Meta = m

	return fmt.Sprintf("%20s\t%10d\t%7d-%-d", sequence.ID[:util.Min(20, len(sequence.ID))], sequence.Len(), len(m.binMap)-len(bins), len(m.binMap)-1)
}
예제 #8
0
파일: interval.go 프로젝트: frogs/biogo
// Merge a range of intervals provided by r. Returns merged intervals in a slice and
// intervals contributing to merged intervals groups in a slice of slices.
func (self *Interval) flatten(r chan *Interval, tolerance int) (flat []*Interval, rich [][]*Interval) {
	flat = []*Interval{}
	rich = [][]*Interval{{}}

	min, max := util.MaxInt, util.MinInt
	var last *Interval
	for current := range r {
		if last != nil && current.start-tolerance > max {
			n, _ := New(current.seg, min, max, 0, nil)
			flat = append(flat, n)
			min = current.start
			max = current.end
			rich = append(rich, []*Interval{})
		} else {
			min = util.Min(min, current.start)
			max = util.Max(max, current.end)
		}
		rich[len(rich)-1] = append(rich[len(rich)-1], current)
		last = current
	}
	n, _ := New(last.seg, min, max, 0, nil)
	flat = append(flat, n)

	return
}
예제 #9
0
파일: qual.go 프로젝트: frogs/biogo
func (self *Quality) stitch(fs []*interval.Interval) (tq []Qsanger) {
	for _, seg := range fs {
		tq = append(tq, self.Qual[util.Max(seg.Start()-self.Offset, 0):util.Min(seg.End()-self.Offset, len(self.Qual))]...)
	}

	return
}
예제 #10
0
파일: packed.go 프로젝트: frogs/biogo
// Join sequentially order disjunct segments of the sequence, returning any error.
func (self *Seq) Stitch(f feat.FeatureSet) (err error) {
	tr := interval.NewTree()
	var i *interval.Interval

	for _, feature := range f {
		i, err = interval.New(emptyString, feature.Start, feature.End, 0, nil)
		if err != nil {
			return
		} else {
			tr.Insert(i)
		}
	}

	span, err := interval.New(emptyString, self.offset, self.End(), 0, nil)
	if err != nil {
		panic("packed: Sequence.End() < Sequence.Start()")
	}
	fs, _ := tr.Flatten(span, 0, 0)
	l := 0

	for _, seg := range fs {
		l += util.Min(seg.End(), self.End()) - util.Max(seg.Start(), self.Start())
	}

	t := &Seq{}
	*t = *self
	t.S = &Packing{Letters: make([]alphabet.Pack, 0, (l+3)/4)}

	var tseg seq.Sequence
	for _, seg := range fs {
		tseg, err = self.Subseq(util.Max(seg.Start(), self.Start()), util.Min(seg.End(), self.End()))
		if err != nil {
			return
		}
		s := tseg.(*Seq).S
		s.Align(seq.Start)
		t.S.Align(seq.End)
		t.S.Letters = append(t.S.Letters, s.Letters...)
		t.S.RightPad = s.RightPad
	}

	*self = *t

	return
}
예제 #11
0
파일: utils.go 프로젝트: frogs/biogo
// Compose provides a function that may be used by polymer types to implement Composer.
// It makes use of reflection and so may be slower than type-specific implementations.
// This is the reference implementation and should be used to compare type-specific
// implementation against in testing.
func Compose(pol interface{}, offset int, f feat.FeatureSet) (s []interface{}, err error) {
	pv := reflect.ValueOf(pol)
	pLen := pv.Len()
	end := pLen + offset

	tv := make([]reflect.Value, len(f))
	for i, seg := range f {
		if seg.End < seg.Start {
			return nil, bio.NewError("Feature End < Start", 0, f)
		}
		l := util.Min(seg.End, end) - util.Max(seg.Start, offset)
		tv[i] = reflect.MakeSlice(pv.Type(), l, l)
		reflect.Copy(tv[i], pv.Slice(util.Max(seg.Start-offset, 0), util.Min(seg.End-offset, pLen)))
	}

	s = make([]interface{}, len(tv))
	for i := range tv {
		s[i] = tv[i].Interface()
	}

	return
}
예제 #12
0
파일: interval.go 프로젝트: frogs/biogo
func (self *Interval) merge(i *Interval, overlap int) (inserted *Interval, removed []*Interval) {
	r := make(chan *Interval)
	removed = []*Interval{}
	wait := make(chan struct{})

	go func() {
		defer close(wait)
		min, max := util.MaxInt, util.MinInt
		for old := range r {
			min, max = util.Min(min, old.start), util.Max(max, old.end)
			removed = append(removed, old)
		}
		i.start, i.end = util.Min(i.start, min), util.Max(i.end, max)
		inserted = i
		// TODO: Do something sensible when only one interval is found and the only action is to extend or ignore
	}()
	self.intersect(i, overlap, r)
	close(r)
	<-wait

	return
}
예제 #13
0
파일: fasta.go 프로젝트: frogs/biogo
// Write a single sequence and return the number of bytes written and any error.
func (self *Writer) Write(s *seq.Seq) (n int, err error) {
	var ln int
	n, err = self.w.WriteString(string(self.IDPrefix) + s.ID + "\n")
	if err == nil {
		for i := 0; i*self.Width <= s.Len(); i++ {
			endLinePos := util.Min(self.Width*(i+1), s.Len())
			for _, elem := range [][]byte{self.SeqPrefix, s.Seq[self.Width*i : endLinePos], {'\n'}} {
				ln, err = self.w.Write(elem)
				if n += ln; err != nil {
					return
				}
			}
		}
	}

	return
}
예제 #14
0
파일: kmercolor.go 프로젝트: frogs/biogo
// Render the rainbow based on block of sequence in the index with the given size. Left and right define the extent of the rendering.
// Vary specifies which color values change in response to kmer frequency.
func (self *KmerRainbow) Paint(vary int, block, size, left, right int) (i *image.RGBA, err error) {
	right = util.Min(right, self.Rect.Dx())
	kmers := make([]uint32, self.RGBA.Rect.Dy())
	kmask := util.Pow4(self.Index.GetK())
	kmaskf := float64(kmask)
	f := func(index *kmerindex.Index, _, kmer int) {
		kmers[int(float64(kmer)*float64(self.RGBA.Rect.Dy())/kmaskf)]++
	}
	self.Index.ForEachKmerOf(self.Index.Seq, block*size, (block+1)*size-1, f)
	c := color.HSVA{}
	lf := float64(len(kmers)) / 360
	var val float64
	scale := 1 / float64(self.Max)
	for y, v := range kmers {
		val = float64(v) / scale
		c.H = float64(y) / lf
		if vary&S != 0 {
			c.S = val
		} else {
			c.S = self.BackGround.S
		}
		if vary&V != 0 {
			c.V = val
		} else {
			c.V = self.BackGround.V
		}
		if vary&A != 0 {
			c.A = val
		} else {
			c.A = self.BackGround.A
		}
		if left >= 0 && right > left {
			for x := left; x < right; x++ {
				self.Set(x, y, c)
			}
		} else {
			println(left, right)
			for x := 0; x < self.Rect.Dx(); x++ {
				self.Set(x, y, c)
			}
		}
	}

	return self.RGBA, nil
}