// PostAnnotate happens after everything is done. func (a *Annotator) PostAnnotate(chrom string, start int, end int, info interfaces.Info, prefix string) error { var e, err error vals := make([]interface{}, 0, 2) fields := make([]string, 0, 2) missing := make([]string, 0, 2) var val interface{} for i := range a.PostAnnos { post := a.PostAnnos[i] vals = vals[:0] fields = fields[:0] missing = missing[:0] // lua code if post.code != "" { for _, field := range post.Fields { val, e = info.Get(field) if val != nil { vals = append(vals, val) fields = append(fields, field) } else { missing = append(missing, field) } if e != nil { err = e } } // we need to try even if it didn't get all values. if len(vals) == 0 && len(post.Fields) > 0 { continue } k := 0 out: // could also use fanIn where all channels send to a single // channel and pull from that. for { select { case k = <-post.mus[0]: break out case k = <-post.mus[1]: break out case k = <-post.mus[2]: break out case k = <-post.mus[3]: break out case k = <-post.mus[4]: break out case k = <-post.mus[5]: break out case k = <-post.mus[6]: break out case k = <-post.mus[7]: break out default: } } for i, val := range vals { post.Vms[k].SetGlobal(fields[i], val) } post.Vms[k].SetGlobal("chrom", chrom) post.Vms[k].SetGlobal("start", start) post.Vms[k].SetGlobal("stop", end) // need to unset missing values so we don't use those // from previous run. for _, miss := range missing { post.Vms[k].SetGlobal(miss, nil) } value, e := post.Vms[k].Run(post.code) post.mus[k] <- k if value == nil { if e != nil { code := post.code if len(code) > 40 { code = code[:37] + "..." } log.Printf("ERROR: in lua postannotation at %s:%d for %s.\n%s\nempty values were: %+v\nvalues were: %+v\ncode is: %s", chrom, start+1, post.Name, e, missing, vals, code) } continue } if e != nil { err = e } val := fmt.Sprintf("%v", value) if post.Type == "Flag" { if !(strings.ToLower(val) == "false" || val == "0" || val == "") { e := info.Set(post.Name, true) if e != nil { err = e } } } else { if e := info.Set(prefix+post.Name, val); e != nil { err = e } } } else { // built in function. // re-use vals var e error for _, field := range post.Fields { // ignore error when field isnt found. we expect that to occur a lot. val, e = info.Get(field) if val != nil { vals = append(vals, val) } else { if e != nil { err = e } } } // run this as long as we found any of the values. if len(vals) != 0 { fn := Reducers[post.Op] info.Set(prefix+post.Name, fn(vals)) } } } return err }
func (a *Annotator) PostAnnotate(info interfaces.Info) error { var err error vals := make([]interface{}, 0, 2) for i := range a.PostAnnos { post := a.PostAnnos[i] // built in function vals = vals[:0] if post.code != "" { for _, field := range post.Fields { val, _ := info.Get(field) // ignore the error as it means the field is not present. if val != nil { vals = append(vals, val) } } if len(vals) != len(post.Fields) { continue } post.mu.Lock() for i, val := range vals { post.Vm.SetGlobal(post.Fields[i], val) } value, e := post.Vm.Run(post.code) post.mu.Unlock() if e != nil { err = e } val := fmt.Sprintf("%v", value) if post.Type == "Flag" { if !(strings.ToLower(val) == "false" || val == "0" || val == "") { e := info.Set(post.Name, true) if e != nil { err = e } } } else { if e := info.Set(post.Name, val); e != nil { err = e } } } else { // built in function. // re-use vals for _, field := range post.Fields { // ignore error when field isnt found. we expect that to occur a lot. val, _ := info.Get(field) if val != nil { vals = append(vals, val) } } if len(vals) == len(post.Fields) { fn := Reducers[post.Op] info.Set(post.Name, fn(vals)) } } } return err }