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) }
// 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 }
// 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 }
func (self *Quality) Stitch(f feat.FeatureSet) (q *Quality, 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) } } span, err := interval.New(emptyString, self.Start(), self.End(), 0, nil) if err != nil { panic("Seq.End() < Seq.Start()") } fs, _ := t.Flatten(span, 0, 0) if self.Inplace { q = self q.Qual = self.stitch(fs) q.Offset = 0 q.Circular = false } else { q = &Quality{ ID: self.ID, Qual: self.stitch(fs), Offset: 0, Strand: self.Strand, Circular: false, } } return }
func (self *Seq) Stitch(f feat.FeatureSet) (s *Seq, err error) { if !self.Inplace && self.Quality != nil && self.Quality.Inplace { return nil, bio.NewError("Inplace operation on Quality with non-Inplace operation on parent Seq.", 0, self) } 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) } } span, err := interval.New(emptyString, self.Start(), self.End(), 0, nil) if err != nil { panic("Seq.End() < Seq.Start()") } fs, _ := t.Flatten(span, 0, 0) if self.Inplace { self.Seq = self.stitch(fs) self.Offset = 0 self.Circular = false if self.Quality != nil { var q *Quality if !self.Quality.Inplace { q = &Quality{ID: self.Quality.ID} } q.Qual = self.Quality.stitch(fs) q.Offset = 0 q.Circular = false self.Quality = q } s = self } else { var q *Quality if self.Quality != nil { q = &Quality{ ID: self.Quality.ID, Qual: self.Quality.stitch(fs), Offset: 0, Circular: false, } } s = &Seq{ ID: self.ID, Seq: self.stitch(fs), Offset: 0, Strand: self.Strand, Circular: false, Moltype: self.Moltype, Quality: q, } } return }
func (self Alignment) Stitch(f feat.FeatureSet) (a Alignment, err error) { for _, s := range self { if !s.Inplace && s.Quality != nil && s.Quality.Inplace { return nil, bio.NewError("Inplace operation on Quality with non-Inplace operation on parent Seq.", 0, s) } } t := interval.NewTree() var i *interval.Interval for _, feature := range f { i, err = interval.New("", feature.Start, feature.End, 0, nil) if err != nil { return } else { t.Insert(i) } } start := self.Start() a = make(Alignment, len(self)) span, err := interval.New("", start, self.End(), 0, nil) if err != nil { panic("Seq.End() < Seq.Start()") } fs, _ := t.Flatten(span, 0, 0) var offset int for i, s := range self { if s.Inplace { s.Seq = s.stitch(fs) if s.Offset -= fs[0].Start(); offset < 0 { s.Offset = 0 } s.Circular = false if s.Quality != nil { var q *Quality if s.Quality.Inplace { q = s.Quality } else { q = &Quality{ID: s.Quality.ID} } q.Qual = s.Quality.stitch(fs) if q.Offset = s.Quality.Offset - fs[0].Start(); q.Offset < 0 { q.Offset = 0 } q.Circular = false s.Quality = q } a[i] = s } else { var q *Quality if s.Quality != nil { if offset = s.Quality.Offset - fs[0].Start(); offset < 0 { offset = 0 } q = &Quality{ ID: s.Quality.ID, Qual: s.Quality.stitch(fs), Offset: offset, Circular: false, } } if offset = s.Offset - fs[0].Start(); offset < 0 { offset = 0 } a[i] = &Seq{ ID: s.ID, Seq: s.stitch(fs), Offset: offset, Strand: s.Strand, Circular: false, Moltype: s.Moltype, Quality: q, } } } return }