diff --git a/pi.go b/pi.go
index 34c73e3fc8b044cfd29aa171bae354abbed2beb3..3193c26b794e49b008af4b2ab25252cd9cef88b8 100644
--- a/pi.go
+++ b/pi.go
@@ -5,7 +5,6 @@
 // The plotting library I used does not draw to the screen. Bummer. One could
 // use the canvas in vggio, although that pulls in all of fyne.
 
-
 package main
 
 import (
@@ -41,6 +40,7 @@ const (
 func usage(e string) {
 	u := "usage: pi seed nsteps nstep_nprint"
 	fmt.Fprintln(os.Stderr, e+"\n"+u)
+	flag.Usage()
 	os.Exit(exitFailure)
 }
 
@@ -90,6 +90,22 @@ func wrtTable(cmdArgs cmdArgs, pi, stdErr []float32) {
 	}
 }
 
+// addline saves us doing the same point copying, adding three times.
+func oneplot(y []float32) (*plot.Plot, error) {
+	p := plot.New()
+	points := make(plotter.XYs, len(y))
+	for i, piV := range y {
+		points[i] = plotter.XY{X: float64(i + 1), Y: float64(piV)}
+	}
+	if line, err := plotter.NewLine(points); err != nil {
+		return nil, err
+	} else {
+		line.LineStyle.Width = 4
+		p.Add(line)
+	}
+	return p, nil
+}
+
 // doplot makes a primitive plot without any interesting options
 // If no plotname is given, it means no plot is wanted. We have to rewrite the data
 // to fit to the plot function's expectations (x/y pairs).
@@ -97,26 +113,53 @@ func doplot(pi, stdErr []float32, plotName string) error {
 	if plotName == "" {
 		return nil
 	}
-	p := plot.New()
-	p.Title.Text = ""
-	cnvs := draw.New(vgimg.New(vg.Points(10), vg.Points(16)))
-	points := make (plotter.XYs, len(pi))
-	for i, piV := range pi {
-		points[i] = plotter.XY{X: float64(i+1), Y:float64(piV)}
+	const step = "step"
+	pPi, err := oneplot(pi) // pi estimate
+	if err != nil {
+		return err
 	}
-	line, err := plotter.NewLine(points)
+	pPi.Title.Text = ""
+	pPi.X.Label.Text = step
+	pPi.Y.Label.Text = "π estimate"
+
+	pStd, err := oneplot(stdErr) // std error
 	if err != nil {
 		return err
 	}
-	p.X.Label.Text = "step"
-	p.Y.Label.Text = "π estimate"
-	p.Add(line)
-	p.Draw(cnvs)
-	if plotName != "" {
-		if err := p.Save(sizeHrznt, sizeVert, plotName); err != nil {
-			return fmt.Errorf("Plotting, opening \"%s\": %w", plotName, err)
+	pStd.Title.Text = ""
+	pStd.X.Label.Text = step
+	pStd.Y.Label.Text = "std error"
+
+	pAbs := plot.New()
+	{
+		tmperr := make([]float32, len(pi)) // the extra bracing makes
+		for i := range tmperr {            // the lifetime of tmperr clear...
+			tmperr[i] = pi[i] - math.Pi // for garbage collector
+		}
+		pAbs, err = oneplot(tmperr)
+		if err != nil {
+			return err
 		}
 	}
+	pAbs.X.Label.Text = step
+	pAbs.Y.Label.Text = "error"
+	dt := draw.Tiles{Rows: 3, Cols: 1, PadTop: 2}
+	img := vgimg.New(vg.Points(400), vg.Points(600))
+	dc := draw.New(img)
+	dCnvs := plot.Align([][]*plot.Plot{{pPi}, {pStd}, {pAbs}}, dt, dc)
+	pPi.Draw(dCnvs[2][0])
+	pAbs.Draw(dCnvs[1][0])
+	pStd.Draw(dCnvs[0][0])
+
+	w, err := os.Create(plotName)
+	if err != nil {
+		return fmt.Errorf("Opening plotfile for writing %w", err)
+	}
+	defer w.Close()
+	jpg := vgimg.JpegCanvas{Canvas: img}
+	if _, err := jpg.WriteTo(w); err != nil {
+		return err
+	}
 	return nil
 }
 
@@ -161,7 +204,9 @@ func main() {
 		usage(err.Error())
 	}
 	pi, stdErr := getnums(cmdArgs)
-	wrtTable(cmdArgs, pi, stdErr)
+	if cmdArgs.doStdout {
+		wrtTable(cmdArgs, pi, stdErr)
+	}
 	if err := doplot(pi, stdErr, cmdArgs.plotName); err != nil {
 		fmt.Fprintln(os.Stderr, err)
 		os.Exit(exitFailure)