Пример #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())
	}
}
Пример #2
0
// Write a single feature and return the number of bytes written and any error.
func (w *Writer) Write(f feat.Feature) (n int, err error) {
	defer func() {
		if err != nil {
			return
		}
		_, err = w.w.Write([]byte{'\n'})
		if err != nil {
			return
		}
		n++
	}()

	// Handle Bed types.
	if f, ok := f.(Bed); ok {
		if !f.canBed(w.BedType) {
			return 0, ErrBadBedType
		}
		return fmt.Fprintf(w.w, "%*s", w.BedType, f)
	}

	// Handle other feature types.
	if f.Location() == nil {
		return 0, ErrNoChromField
	}

	// Bed3
	n, err = fmt.Fprintf(w.w, "%s\t%d\t%d", f.Location(), f.Start(), f.End())
	if w.BedType == 3 {
		return n, err
	}

	// Bed4
	_n, err := fmt.Fprintf(w.w, "\t%s", f.Name())
	n += _n
	if w.BedType == 4 || err != nil {
		return n, err
	}

	// Bed5
	if f, ok := f.(Scorer); ok {
		_n, err := fmt.Fprintf(w.w, "\t%d", f.Score())
		n += _n
		if err != nil {
			return n, err
		}
	} else {
		_n, err := fmt.Fprintf(w.w, "\t0")
		n += _n
		if err != nil {
			return n, err
		}
	}
	if w.BedType == 5 {
		return
	}

	// Bed6
	if f, ok := f.(feat.Orienter); ok {
		_n, err := fmt.Fprintf(w.w, "\t%s", seq.Strand(f.Orientation()))
		n += _n
		if err != nil {
			return n, err
		}
	} else {
		_n, err := fmt.Fprintf(w.w, "\t.")
		n += _n
		if err != nil {
			return n, err
		}
	}
	if w.BedType == 6 || w.BedType == 0 {
		return
	}

	// Don't handle Bed12.
	_n, err = w.w.Write([]byte{'\n'})
	n += _n
	return n, ErrBadBedType
}