Check for unparsed command line args.
[lightning.git] / plot.go
1 // Copyright (C) The Lightning Authors. All rights reserved.
2 //
3 // SPDX-License-Identifier: AGPL-3.0
4
5 package lightning
6
7 import (
8         _ "embed"
9         "flag"
10         "fmt"
11         "io"
12         _ "net/http/pprof"
13         "os/exec"
14         "strings"
15
16         "git.arvados.org/arvados.git/sdk/go/arvados"
17 )
18
19 type pythonPlot struct{}
20
21 //go:embed plot.py
22 var plotscript string
23
24 func (cmd *pythonPlot) RunCommand(prog string, args []string, stdin io.Reader, stdout, stderr io.Writer) int {
25         var err error
26         defer func() {
27                 if err != nil {
28                         fmt.Fprintf(stderr, "%s\n", err)
29                 }
30         }()
31         flags := flag.NewFlagSet("", flag.ContinueOnError)
32         flags.SetOutput(stderr)
33         projectUUID := flags.String("project", "", "project `UUID` for output data")
34         inputFilename := flags.String("i", "-", "input `file`")
35         outputFilename := flags.String("o", "", "output `filename` (e.g., './plot.png')")
36         sampleListFilename := flags.String("samples", "", "use second column of `samples.csv` as complete list of sample IDs")
37         phenotypeFilename := flags.String("phenotype", "", "use `phenotype.csv` as id->phenotype mapping (column 0 is sample id)")
38         cat1Column := flags.Int("phenotype-cat1-column", 1, "0-based column `index` of 1st category in phenotype.csv file")
39         cat2Column := flags.Int("phenotype-cat2-column", -1, "0-based column `index` of 2nd category in phenotype.csv file")
40         xComponent := flags.Int("x", 1, "1-based PCA component to plot on x axis")
41         yComponent := flags.Int("y", 2, "1-based PCA component to plot on y axis")
42         priority := flags.Int("priority", 500, "container request priority")
43         runlocal := flags.Bool("local", false, "run on local host (default: run in an arvados container)")
44         err = flags.Parse(args)
45         if err == flag.ErrHelp {
46                 err = nil
47                 return 0
48         } else if err != nil {
49                 return 2
50         } else if flags.NArg() > 0 {
51                 err = fmt.Errorf("errant command line arguments after parsed flags: %v", flags.Args())
52                 return 2
53         }
54
55         runner := arvadosContainerRunner{
56                 Name:        "lightning plot",
57                 Client:      arvados.NewClientFromEnv(),
58                 ProjectUUID: *projectUUID,
59                 RAM:         4 << 30,
60                 VCPUs:       1,
61                 Priority:    *priority,
62                 Mounts: map[string]map[string]interface{}{
63                         "/plot.py": map[string]interface{}{
64                                 "kind":    "text",
65                                 "content": plotscript,
66                         },
67                 },
68         }
69         if !*runlocal {
70                 err = runner.TranslatePaths(inputFilename, sampleListFilename, phenotypeFilename)
71                 if err != nil {
72                         return 1
73                 }
74                 *outputFilename = "/mnt/output/plot.png"
75         }
76         args = []string{
77                 *inputFilename,
78                 fmt.Sprintf("%d", *xComponent),
79                 fmt.Sprintf("%d", *yComponent),
80                 *sampleListFilename,
81                 *phenotypeFilename,
82                 fmt.Sprintf("%d", *cat1Column),
83                 fmt.Sprintf("%d", *cat2Column),
84                 *outputFilename,
85         }
86         if *runlocal {
87                 if *outputFilename == "" {
88                         fmt.Fprintln(stderr, "error: must specify -o filename.png in local mode (or try -help)")
89                         return 1
90                 }
91                 cmd := exec.Command("python3", append([]string{"-"}, args...)...)
92                 cmd.Stdin = strings.NewReader(plotscript)
93                 cmd.Stdout = stdout
94                 cmd.Stderr = stderr
95                 err = cmd.Run()
96                 if err != nil {
97                         return 1
98                 }
99                 return 0
100         }
101         runner.Prog = "python3"
102         runner.Args = append([]string{"/plot.py"}, args...)
103         var output string
104         output, err = runner.Run()
105         if err != nil {
106                 return 1
107         }
108         fmt.Fprintln(stdout, output+"/plot.png")
109         return 0
110 }