Пример #1
0
// Write writes a single feature and return the number of bytes written and any error.
// gff.Features are written as a canonical GFF line, seq.Sequences are written as inline
// sequence in GFF format (note that only sequences of feat.Moltype DNA, RNA and Protein
// are supported). gff.Sequences are not handled as they have a zero length. All other
// feat.Feature are written as sequence region metadata lines.
func (w *Writer) Write(f feat.Feature) (n int, err error) {
	if f.Start() >= f.End() {
		return 0, ErrBadFeature
	}
	w.header = true
	switch f := f.(type) {
	case *Feature:
		defer func() {
			if err != nil {
				return
			}
			_, err = w.w.Write([]byte{'\n'})
			if err != nil {
				return
			}
			n++
		}()
		n, err = fmt.Fprintf(w.w, "%s\t%s\t%s\t%d\t%d\t",
			f.SeqName,
			f.Source,
			f.Feature,
			feat.ZeroToOne(f.FeatStart),
			f.FeatEnd,
		)
		if err != nil {
			return n, err
		}
		var _n int
		if f.FeatScore != nil && !math.IsNaN(*f.FeatScore) {
			if w.Precision < 0 {
				_n, err = fmt.Fprintf(w.w, "%v", *f.FeatScore)
			} else {
				_n, err = fmt.Fprintf(w.w, "%.*f", w.Precision, *f.FeatScore)
			}
			if err != nil {
				return n, err
			}
			n += _n
		} else {
			_, err = w.w.Write([]byte{'.'})
			if err != nil {
				return n, err
			}
			n++
		}
		_n, err = fmt.Fprintf(w.w, "\t%s\t%s",
			f.FeatStrand,
			f.FeatFrame,
		)
		n += _n
		if err != nil {
			return n, err
		}
		if f.FeatAttributes != nil {
			_n, err = fmt.Fprintf(w.w, "\t%v", f.FeatAttributes)
			if err != nil {
				return n, err
			}
			n += _n
		} else if f.Comments != "" {
			_, err = w.w.Write([]byte{'\t'})
			if err != nil {
				return
			}
			n++
		}
		if f.Comments != "" {
			_n, err = fmt.Fprintf(w.w, "\t%s", f.Comments)
			n += _n
		}
		return n, err
	case seq.Sequence:
		sw := fasta.NewWriter(w.w, w.Width)
		moltype := f.Alphabet().Moltype()
		if moltype < feat.DNA || moltype > feat.Protein {
			return 0, ErrNotHandled
		}
		sw.IDPrefix = [...][]byte{
			feat.DNA:     []byte("##DNA "),
			feat.RNA:     []byte("##RNA "),
			feat.Protein: []byte("##Protein "),
		}[moltype]
		sw.SeqPrefix = []byte("##")
		n, err = sw.Write(f)
		if err != nil {
			return n, err
		}
		var _n int
		_n, err = w.w.Write([...][]byte{
			feat.DNA:     []byte("##end-DNA\n"),
			feat.RNA:     []byte("##end-RNA\n"),
			feat.Protein: []byte("##end-Protein\n"),
		}[moltype])
		return n + _n, err
	case Sequence:
		return 0, ErrNotHandled
	case *Region:
		return fmt.Fprintf(w.w, "##sequence-region %s %d %d\n", f.SeqName, feat.ZeroToOne(f.RegionStart), f.RegionEnd)
	default:
		return fmt.Fprintf(w.w, "##sequence-region %s %d %d\n", f.Name(), feat.ZeroToOne(f.Start()), f.End())
	}
}