Exemple #1
0
// Stitch produces a subsequence of the receiver defined by fs. The result is stored in the receiver
// and all contributing sequences are modified.
func (m *Multi) Stitch(fs feat.Set) error {
	ff := fs.Features()
	for _, f := range ff {
		if f.End() < f.Start() {
			return errors.New("multi: feature end < feature start")
		}
	}
	ff = append(fts(nil), ff...)
	sort.Sort(fts(ff))

	var (
		fsp = make(fts, 0, len(ff))
		csp *ft
	)
	for i, f := range ff {
		if s := f.Start(); i == 0 || s > csp.e {
			csp = &ft{s: s, e: f.End()}
			fsp = append(fsp, csp)
		} else {
			csp.e = max(csp.e, f.End())
		}
	}

	return m.Compose(fsp)
}
Exemple #2
0
// TranscriptsOf scans a feat.Set and returns any Transcripts that it finds.
func TranscriptsOf(s feat.Set) []Transcript {
	var ts []Transcript
	for _, f := range s.Features() {
		if t, ok := f.(Transcript); ok {
			ts = append(ts, t)
		}
	}
	return ts
}
Exemple #3
0
// Compose produces a composition of src defined by the features in fs. The subparts of
// the composition may be out of order and if features in fs specify orientation may be
// reversed or reverse complemented depending on the src - if src is a SliceReverser and
// its alphabet is a Complementor the segment will be reverse complemented, if the alphabte
// is not a Complementor these segments will only be reversed. If src is not a SliceREverser
// and a reverse segment is specified an error is returned.
// Composing a circular sequence returns a linear sequence.
func Compose(dst, src Sliceable, fs feat.Set) error {
	var (
		sl     = src.Slice()
		offset = src.Start()
		ff     = feats(fs.Features())
	)

	pLen := sl.Len()
	end := pLen + offset

	t := make([]alphabet.Slice, len(ff))
	var tl int
	for i, f := range ff {
		if f.End() < f.Start() {
			return errors.New("sequtils: feature end < feature start")
		}
		l := min(f.End(), end) - max(f.Start(), offset)
		tl += l
		t[i] = sl.Make(l, l)
		t[i].Copy(sl.Slice(max(f.Start()-offset, 0), min(f.End()-offset, pLen)))
	}

	c := sl.Make(0, tl)
	var r SliceReverser
	for i, ts := range t {
		if f, ok := ff[i].(feat.Orienter); ok && f.Orientation() == feat.Reverse {
			switch src := src.(type) {
			case SliceReverser:
				if r == nil {
					r = src.New().(SliceReverser)
					if _, ok := src.Alphabet().(alphabet.Complementor); ok {
						r.SetAlphabet(src.Alphabet())
						r.SetSlice(ts)
						r.RevComp()
					} else {
						r.SetSlice(ts)
						r.Reverse()
					}
				}
			default:
				return errors.New("sequtils: unable to reverse segment during compose")
			}
			c = c.Append(r.Slice())
		} else {
			c = c.Append(ts)
		}
	}

	dst.SetSlice(c)
	if dst, ok := dst.(seq.ConformationSetter); ok {
		dst.SetConformation(feat.Linear)
	}
	dst.SetOffset(0)

	return nil
}
Exemple #4
0
// Stitch produces a subsequence of src defined by fs and places the the result in dst.
// The subsequences are guaranteed to be in order and non-overlapping even if not provided as such.
// Stitching a circular sequence returns a linear sequence.
func Stitch(dst, src Sliceable, fs feat.Set) error {
	var (
		sl     = src.Slice()
		offset = src.Start()
		ff     = feats(fs.Features())
	)
	for _, f := range ff {
		if f.End() < f.Start() {
			return errors.New("sequtils: feature end < feature start")
		}
	}
	ff = append(feats(nil), ff...)
	sort.Sort(ff)
	// FIXME Does not correctly deal with circular sequences and feature sets.
	// Range over ff if src is circular and  and trunc at start and end, do checks to
	// see if feature splits on origin and rearrange tail to front.

	pLen := sl.Len()
	end := pLen + offset

	type fi struct{ s, e int }
	var (
		fsp = make([]*fi, 0, len(ff))
		csp *fi
	)
	for i, f := range ff {
		if s := f.Start(); i == 0 || s > csp.e {
			csp = &fi{s: s, e: f.End()}
			fsp = append(fsp, csp)
		} else {
			csp.e = max(csp.e, f.End())
		}
	}

	var l int
	for _, f := range fsp {
		l += max(0, min(f.e, end)-max(f.s, offset))
	}
	t := sl.Make(0, l)

	for _, f := range fsp {
		fs, fe := max(f.s-offset, 0), min(f.e-offset, pLen)
		if fs >= fe {
			continue
		}
		t = t.Append(sl.Slice(fs, fe))
	}

	dst.SetSlice(t)
	if dst, ok := dst.(seq.ConformationSetter); ok {
		dst.SetConformation(feat.Linear)
	}
	dst.SetOffset(0)

	return nil
}