Пример #1
0
// AnnotateOne annotates a relatable with the Sources in an Annotator.
// In most cases, no need to specify end (it should always be a single
// arugment indicting LEFT, RIGHT, or INTERVAL, used from AnnotateEnds
func (a *Annotator) AnnotateOne(r interfaces.Relatable, strict bool, end ...string) error {
	if len(r.Related()) == 0 {
		return nil
	}
	prefix := ""
	if len(end) > 0 {
		prefix = end[0]
		if len(end) > 1 {
			log.Fatalf("too many ends in AnnotateOne")
		}
	}

	parted := a.partition(r)
	var v interfaces.IVariant
	v, ok := r.(interfaces.IVariant)
	if !ok {
		log.Fatal("can't annotate non-IVariant", r)
	}

	var src *Source
	for i := range a.Sources {
		src = a.Sources[i]
		if len(parted) <= src.Index {
			continue
		}

		related := parted[src.Index]
		if len(related) == 0 {
			continue
		}
		vals := collect(v, related, src, strict)
		src.AnnotateOne(v, vals, prefix)
	}
	return nil
}
Пример #2
0
// partition separates the relateds for a relatable so it reduces running over the data multiple times for each file.
func (a *Annotator) partition(r interfaces.Relatable) [][]interfaces.Relatable {
	parted := make([][]interfaces.Relatable, 0, 0)
	for _, o := range r.Related() {
		s := int(o.Source()) - 1
		for len(parted) <= s {
			parted = append(parted, make([]interfaces.Relatable, 0))
		}
		parted[s] = append(parted[s], o)
	}
	return parted
}
Пример #3
0
// AnnotateEnds makes a new 1-base interval for the left and one for the right end
// so that it can use the same machinery to annotate the ends and the entire interval.
// Output into the info field is prefixed with "left_" or "right_".
func (a *Annotator) AnnotateEnds(v interfaces.Relatable, ends string) error {

	var err error
	// if Both, call the interval, left, and right version to annotate.
	if ends == BOTH {
		if e := a.AnnotateOne(v, a.Strict); e != nil {
			err = e
		}
		if e := a.PostAnnotate(v.Chrom(), int(v.Start()), int(v.End()), v.(interfaces.IVariant).Info(), ""); e != nil {
			err = e
		}
		if e := a.AnnotateEnds(v, LEFT); e != nil {
			err = e
		}
		if e := a.AnnotateEnds(v, RIGHT); e != nil {
			err = e
		}
	}
	if ends == INTERVAL {
		err := a.AnnotateOne(v, a.Strict)
		err2 := a.PostAnnotate(v.Chrom(), int(v.Start()), int(v.End()), v.(interfaces.IVariant).Info(), "")
		if err != nil {
			return err
		}
		return err2
	}
	// hack:
	// modify the variant in-place to create a 1-base variant at the end of
	// the interval. annotate that end and then change the position back to what it was.
	if ends == LEFT || ends == RIGHT {
		// the end is determined by the SVLEN, so we have to make sure it has length 1.
		variant := v.(*parsers.Variant).IVariant
		var l, r uint32
		var ok bool
		if ends == LEFT {
			l, r, ok = variant.CIPos()
		} else {
			l, r, ok = variant.CIEnd()
		}
		// dont reannotate same interval
		if !ok && (l == v.Start() && r == v.End()) {
			return nil
		}

		m := vcfgo.NewInfoByte([]byte(fmt.Sprintf("SVLEN=%d;END=%d", r-l-1, r)), variant.(*vcfgo.Variant).Header)
		v2 := parsers.NewVariant(&vcfgo.Variant{Chromosome: v.Chrom(), Pos: uint64(l + 1),
			Reference: "A", Alternate: []string{"<DEL>"}, Info_: m}, v.Source(), v.Related())

		err = a.AnnotateOne(v2, false, ends)
		var val interface{}
		for _, key := range v2.Info().Keys() {
			if key == "SVLEN" || key == "END" {
				continue
			}
			val, err = v2.Info().Get(key)
			variant.Info().Set(key, val)
		}
		err2 := a.PostAnnotate(v.Chrom(), int(l), int(r), variant.Info(), ends)
		if err2 != nil {
			err = err2
		}
	}
	return err
}