Merge branch '19524-pca'
[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         phenotypeCategoryColumn := flags.Int("phenotype-category-column", -1, "0-based column `index` of 2nd category in phenotype.csv file")
39         phenotypeColumn := flags.Int("phenotype-column", 1, "0-based column `index` of phenotype in phenotype.csv file")
40         priority := flags.Int("priority", 500, "container request priority")
41         runlocal := flags.Bool("local", false, "run on local host (default: run in an arvados container)")
42         err = flags.Parse(args)
43         if err == flag.ErrHelp {
44                 err = nil
45                 return 0
46         } else if err != nil {
47                 return 2
48         }
49
50         runner := arvadosContainerRunner{
51                 Name:        "lightning plot",
52                 Client:      arvados.NewClientFromEnv(),
53                 ProjectUUID: *projectUUID,
54                 RAM:         4 << 30,
55                 VCPUs:       1,
56                 Priority:    *priority,
57                 Mounts: map[string]map[string]interface{}{
58                         "/plot.py": map[string]interface{}{
59                                 "kind":    "text",
60                                 "content": plotscript,
61                         },
62                 },
63         }
64         if !*runlocal {
65                 err = runner.TranslatePaths(inputFilename, sampleListFilename, phenotypeFilename)
66                 if err != nil {
67                         return 1
68                 }
69                 *outputFilename = "/mnt/output/plot.png"
70         }
71         args = []string{*inputFilename, *sampleListFilename, *phenotypeFilename, fmt.Sprintf("%d", *phenotypeCategoryColumn), fmt.Sprintf("%d", *phenotypeColumn), *outputFilename}
72         if *runlocal {
73                 if *outputFilename == "" {
74                         fmt.Fprintln(stderr, "error: must specify -o filename.png in local mode (or try -help)")
75                         return 1
76                 }
77                 cmd := exec.Command("python3", append([]string{"-"}, args...)...)
78                 cmd.Stdin = strings.NewReader(plotscript)
79                 cmd.Stdout = stdout
80                 cmd.Stderr = stderr
81                 err = cmd.Run()
82                 if err != nil {
83                         return 1
84                 }
85                 return 0
86         }
87         runner.Prog = "python3"
88         runner.Args = append([]string{"/plot.py"}, args...)
89         var output string
90         output, err = runner.Run()
91         if err != nil {
92                 return 1
93         }
94         fmt.Fprintln(stdout, output+"/plot.png")
95         return 0
96 }