Beispiel #1
0
func (self *Reader) commentMetaline(line string) (f *feat.Feature, err error) {
	// Load these into a slice in a MetaField of the Feature
	fields := strings.Split(string(line), " ")
	switch fields[0] {
	case "gff-version":
		if self.Version, err = strconv.Atoi(fields[1]); err != nil {
			self.Version = DefaultVersion
		}
		return self.Read()
	case "source-version":
		if len(fields) > 1 {
			self.SourceVersion = strings.Join(fields[1:], " ")
			return self.Read()
		} else {
			return nil, bio.NewError("Incomplete source-version metaline", 0, fields)
		}
	case "date":
		if len(fields) > 1 {
			self.Date, err = time.Parse(self.TimeFormat, strings.Join(fields[1:], " "))
			return self.Read()
		} else {
			return nil, bio.NewError("Incomplete date metaline", 0, fields)
		}
	case "Type":
		if len(fields) > 1 {
			self.Type = bio.ParseMoltype(fields[1])
			return self.Read()
		} else {
			return nil, bio.NewError("Incomplete Type metaline", 0, fields)
		}
	case "sequence-region":
		if len(fields) > 3 {
			var start, end int
			if start, err = strconv.Atoi(fields[2]); err != nil {
				return nil, err
			} else {
				if self.OneBased {
					start = bio.OneToZero(start)
				}
			}
			if end, err = strconv.Atoi(fields[3]); err != nil {
				return nil, err
			}
			f = &feat.Feature{
				Meta: &feat.Feature{
					ID:    fields[1],
					Start: start,
					End:   end,
				},
			}
		} else {
			return nil, bio.NewError("Incomplete sequence-region metaline", 0, fields)
		}
	case "DNA", "RNA", "Protein":
		if len(fields) > 1 {
			var s *seq.Seq
			if s, err = self.metaSequence(fields[0], fields[1]); err != nil {
				return
			} else {
				f = &feat.Feature{Meta: s}
			}
		} else {
			return nil, bio.NewError("Incomplete sequence metaline", 0, fields)
		}
	default:
		f = &feat.Feature{Meta: line}
	}

	return
}
Beispiel #2
0
// Read a single feature or part and return it or an error.
func (self *Reader) Read() (f *feat.Feature, err error) {
	var (
		line  string
		elems []string
		s     int8
		ok    bool
	)

	for {
		if line, err = self.r.ReadString('\n'); err == nil {
			if len(line) > 0 && line[len(line)-1] == '\r' {
				line = line[:len(line)-1]
			}
			line = strings.TrimSpace(line)
			if len(line) == 0 { // ignore blank lines
				continue
			} else if strings.HasPrefix(line, "##") {
				f, err = self.commentMetaline(line[2:])
				return
			} else if line[0] != '#' { // ignore comments
				elems = strings.SplitN(line, "\t", 10)
				break
			}
		} else {
			return
		}
	}

	if s, ok = charToStrand[elems[strandField]]; !ok {
		s = 0
	}

	startPos, se := strconv.Atoi(elems[startField])
	if se != nil {
		startPos = 0
	} else {
		if self.OneBased {
			startPos = bio.OneToZero(startPos)
		}
	}

	endPos, se := strconv.Atoi(elems[endField])
	if se != nil {
		endPos = 0
	}

	fr, se := strconv.Atoi(elems[frameField])
	if se != nil {
		fr = -1
	}

	score, se := strconv.ParseFloat(elems[scoreField], 64)
	if se != nil {
		score = math.NaN()
	}

	f = &feat.Feature{
		ID:       elems[nameField] + ":" + strconv.Itoa(startPos) + ".." + strconv.Itoa(endPos),
		Location: elems[nameField],
		Source:   elems[sourceField],
		Start:    startPos,
		End:      endPos,
		Feature:  elems[featureField],
		Score:    score,
		Frame:    int8(fr),
		Strand:   s,
		Moltype:  self.Type, // currently we default to bio.DNA
	}

	if len(elems) > attributeField {
		f.Attributes = elems[attributeField]
	}
	if len(elems) > commentField {
		f.Comments = elems[commentField]
	}

	return
}