File: plot.go

package info (click to toggle)
mumax3 3.11.1-1
  • links: PTS, VCS
  • area: contrib
  • in suites: forky, sid
  • size: 10,668 kB
  • sloc: makefile: 194; ansic: 155; sh: 86; javascript: 16
file content (100 lines) | stat: -rw-r--r-- 1,894 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
package engine

import (
	"bytes"
	"errors"
	"fmt"
	"image"
	"image/png"
	"io"
	"net/http"
	"os/exec"
	"sync/atomic"

	"github.com/mumax/3/httpfs"
)

var nPlots int32       // counts number of active gnuplot processes
const MAX_GNUPLOTS = 5 // maximum allowed number of gnuplot processes

func (g *guistate) servePlot(w http.ResponseWriter, r *http.Request) {

	out := []byte{}

	// handle error and return wheter err != nil.
	handle := func(err error) bool {
		if err != nil {
			w.Write(emptyIMG())
			g.Set("plotErr", err.Error()+string(out))
			return true
		} else {
			return false
		}
	}

	// limit max processes
	atomic.AddInt32(&nPlots, 1)
	defer atomic.AddInt32(&nPlots, -1)
	if atomic.LoadInt32(&nPlots) > MAX_GNUPLOTS {
		handle(errors.New("too many gnuplot processes"))
		return
	}

	a := g.StringValue("usingx")
	b := g.StringValue("usingy")

	cmd := "gnuplot"
	args := []string{"-e", fmt.Sprintf(`set format x "%%g"; set key off; set format y "%%g"; set term svg size 480,320 font 'Arial,10'; plot "-" u %v:%v w li; set output;exit;`, a, b)}
	excmd := exec.Command(cmd, args...)

	stdin, err := excmd.StdinPipe()
	if handle(err) {
		return
	}

	stdout, err := excmd.StdoutPipe()
	if handle(err) {
		return
	}

	data, err := httpfs.Read(fmt.Sprintf(`%vtable.txt`, OD()))
	if handle(err) {
		return
	}

	err = excmd.Start()
	if handle(err) {
		return
	}
	defer excmd.Wait()

	_, err = stdin.Write(data)
	if handle(err) {
		return
	}
	err = stdin.Close()
	if handle(err) {
		return
	}

	out, err = io.ReadAll(stdout)
	if handle(err) {
		return
	}

	w.Header().Set("Content-Type", "image/svg+xml")
	w.Write(out)
	g.Set("plotErr", "")
}

var empty_img []byte

// empty image to show if there's no plot...
func emptyIMG() []byte {
	if empty_img == nil {
		o := bytes.NewBuffer(nil)
		png.Encode(o, image.NewNRGBA(image.Rect(0, 0, 4, 4)))
		empty_img = o.Bytes()
	}
	return empty_img
}