// Read a single sequence and return it or an error. // TODO: Does not read multi-line fastq. func (self *Reader) Read() (s seq.Sequence, err error) { var ( buff, line, label []byte isPrefix bool seqBuff []alphabet.QLetter t seqio.SequenceAppender ) inQual := false for { if buff, isPrefix, err = self.r.ReadLine(); err == nil { if isPrefix { line = append(line, buff...) continue } else { line = buff } line = bytes.TrimSpace(line) if len(line) == 0 { continue } switch { case !inQual && line[0] == '@': t = self.readHeader(line) label, line = line, nil case !inQual && line[0] == '+': if len(label) == 0 { return nil, bio.NewError("fastq: no header line parsed before +line in fastq format", 0) } if len(line) > 1 && bytes.Compare(label[1:], line[1:]) != 0 { return nil, bio.NewError("fastq: quality header does not match sequence header", 0) } inQual = true case !inQual: line = bytes.Join(bytes.Fields(line), nil) seqBuff = make([]alphabet.QLetter, len(line)) for i := range line { seqBuff[i].L = alphabet.Letter(line[i]) } case inQual: line = bytes.Join(bytes.Fields(line), nil) if len(line) != len(seqBuff) { return nil, bio.NewError("fastq: sequence/quality length mismatch", 0) } for i := range line { seqBuff[i].Q = alphabet.DecodeToQphred(line[i], self.enc) } t.AppendQLetters(seqBuff...) return t, nil } } else { return } } panic("cannot reach") }
// Decode a quality letter to a phred score based on the sequence encoding setting. func (self *QSeq) QDecode(l byte) alphabet.Qphred { return alphabet.DecodeToQphred(l, self.encoding) }