Assemble sequences concurrently.
[lightning.git] / diff.go
1 package main
2
3 import (
4         "bufio"
5         "bytes"
6         "flag"
7         "fmt"
8         "io"
9         "os"
10
11         "github.com/arvados/lightning/hgvs"
12 )
13
14 type diffFasta struct{}
15
16 func (cmd *diffFasta) RunCommand(prog string, args []string, stdin io.Reader, stdout, stderr io.Writer) int {
17         var err error
18         defer func() {
19                 if err != nil {
20                         fmt.Fprintf(stderr, "%s\n", err)
21                 }
22         }()
23         flags := flag.NewFlagSet("", flag.ContinueOnError)
24         flags.SetOutput(stderr)
25         offset := flags.Int("offset", 0, "coordinate offset")
26         sequence := flags.String("sequence", "chr1", "sequence label")
27         timeout := flags.Duration("timeout", 0, "timeout (examples: \"1s\", \"1ms\")")
28         err = flags.Parse(args)
29         if err == flag.ErrHelp {
30                 err = nil
31                 return 0
32         } else if err != nil {
33                 return 2
34         }
35         if len(flags.Args()) != 2 {
36                 err = fmt.Errorf("usage: %s [options] a.fasta b.fasta", prog)
37                 return 2
38         }
39
40         var fasta [2][]byte
41         errs := make(chan error, 2)
42         for idx, fnm := range flags.Args() {
43                 idx, fnm := idx, fnm
44                 go func() {
45                         f, err := os.Open(fnm)
46                         if err != nil {
47                                 errs <- err
48                                 return
49                         }
50                         defer f.Close()
51                         scanner := bufio.NewScanner(f)
52                         scanner.Buffer(nil, 64*1024*1024)
53                         for scanner.Scan() {
54                                 buf := scanner.Bytes()
55                                 if len(buf) > 0 && buf[0] != '>' {
56                                         fasta[idx] = append(fasta[idx], bytes.ToUpper(buf)...)
57                                 }
58                         }
59                         errs <- scanner.Err()
60                 }()
61         }
62         for range flags.Args() {
63                 if err = <-errs; err != nil {
64                         return 1
65                 }
66         }
67
68         variants, timedOut := hgvs.Diff(string(fasta[0]), string(fasta[1]), *timeout)
69         if *offset != 0 {
70                 for i := range variants {
71                         variants[i].Position += *offset
72                 }
73         }
74         for _, v := range variants {
75                 fmt.Fprintf(stdout, "%s:g.%s\t%s\t%d\t%s\t%s\t%v\n", *sequence, v.String(), *sequence, v.Position, v.Ref, v.New, timedOut)
76         }
77         return 0
78 }