10 "golang.org/x/crypto/blake2b"
13 type tileVariantID int32 // 1-based
15 type tileLibRef struct {
20 type tileSeq map[string][]tileLibRef
22 type tileLibrary struct {
24 variant [][][blake2b.Size]byte
26 // seq map[[blake2b.Size]byte][]byte
31 func (tilelib *tileLibrary) TileFasta(filelabel string, rdr io.Reader) (tileSeq, error) {
37 todo := make(chan jobT)
38 scanner := bufio.NewScanner(rdr)
44 buf := scanner.Bytes()
45 if len(buf) == 0 || buf[0] == '>' {
46 todo <- jobT{seqlabel, fasta}
47 seqlabel, fasta = string(buf[1:]), nil
48 log.Printf("%s %s reading fasta", filelabel, seqlabel)
50 fasta = append(fasta, bytes.ToLower(buf)...)
53 todo <- jobT{seqlabel, fasta}
55 for job := range todo {
56 if len(job.fasta) == 0 {
59 log.Printf("%s %s tiling", filelabel, job.label)
61 tilestart := -1 // position in fasta of tile that ends here
62 tiletagid := tagID(-1) // tag id starting tile that ends here
63 tilelib.taglib.FindAll(job.fasta, func(id tagID, pos int) {
65 path = append(path, tilelib.getRef(tiletagid, job.fasta[tilestart:pos]))
71 path = append(path, tilelib.getRef(tiletagid, job.fasta[tilestart:]))
74 log.Printf("%s %s tiled with path len %d", filelabel, job.label, len(path))
76 return ret, scanner.Err()
79 // Return a tileLibRef for a tile with the given tag and sequence,
80 // adding the sequence to the library if needed.
81 func (tilelib *tileLibrary) getRef(tag tagID, seq []byte) tileLibRef {
83 defer tilelib.mtx.Unlock()
84 // if tilelib.seq == nil {
85 // tilelib.seq = map[[blake2b.Size]byte][]byte{}
87 if len(tilelib.variant) <= int(tag) {
88 tilelib.variant = append(tilelib.variant, make([][][blake2b.Size]byte, int(tag)-len(tilelib.variant)+1)...)
90 hash, err := blake2b.New(32, nil)
94 _, err = hash.Write(seq)
98 var seqhash [blake2b.Size]byte
99 copy(seqhash[:], hash.Sum(nil))
100 for i, varhash := range tilelib.variant[tag] {
101 if varhash == seqhash {
102 return tileLibRef{tag: tag, variant: tileVariantID(i + 1)}
105 tilelib.variant[tag] = append(tilelib.variant[tag], seqhash)
106 // tilelib.seq[seqhash] = append([]byte(nil), seq...)
107 return tileLibRef{tag: tag, variant: tileVariantID(len(tilelib.variant[tag]))}