Пример #1
0
// DrawFontExtents draws some text and denotes the
// various extents and width with lines. Expects
// about a 4x4 inch canvas.
func DrawFontExtents(c vg.Canvas) {
	x, y := vg.Inches(1), vg.Inches(2)
	str := "Eloquent"
	font, err := vg.MakeFont("Times-Roman", 18)
	if err != nil {
		panic(err)
	}
	width := font.Width(str)
	ext := font.Extents()
	des := ext.Descent
	asc := ext.Ascent

	c.FillString(font, x, y, str)

	// baseline
	path := vg.Path{}
	path.Move(x, y)
	path.Line(x+width, y)
	c.Stroke(path)

	// descent
	c.SetColor(color.RGBA{G: 255, A: 255})
	path = vg.Path{}
	path.Move(x, y+des)
	path.Line(x+width, y+des)
	c.Stroke(path)

	// ascent
	c.SetColor(color.RGBA{B: 255, A: 255})
	path = vg.Path{}
	path.Move(x, y+asc)
	path.Line(x+width, y+asc)
	c.Stroke(path)
}
Пример #2
0
// NewLabels returns a new Labels using the DefaultFont and
// the DefaultFontSize.
func NewLabels(d interface {
	XYer
	Labeller
}) (*Labels, error) {
	xys, err := CopyXYs(d)
	if err != nil {
		return nil, err
	}

	if d.Len() != len(xys) {
		return nil, errors.New("Number of points does not match the number of labels")
	}

	strs := make([]string, d.Len())
	for i := range strs {
		strs[i] = d.Label(i)
	}

	fnt, err := vg.MakeFont(DefaultFont, DefaultFontSize)
	if err != nil {
		return nil, err
	}

	return &Labels{
		XYs:       xys,
		Labels:    strs,
		TextStyle: plot.TextStyle{Font: fnt},
	}, nil
}
Пример #3
0
// New returns a new plot with some reasonable
// default settings.
func New() (*Plot, error) {
	titleFont, err := vg.MakeFont(DefaultFont, 12)
	if err != nil {
		return nil, err
	}
	x, err := makeAxis()
	if err != nil {
		return nil, err
	}
	y, err := makeAxis()
	if err != nil {
		return nil, err
	}
	legend, err := makeLegend()
	if err != nil {
		return nil, err
	}
	p := &Plot{
		BackgroundColor: color.White,
		X:               x,
		Y:               y,
		Legend:          legend,
	}
	p.Title.TextStyle = TextStyle{
		Color: color.Black,
		Font:  titleFont,
	}
	return p, nil
}
Пример #4
0
func init() {
	var err error
	plot.DefaultFont = "Helvetica"
	defaultFont, err = vg.MakeFont("Helvetica", 6)
	if err != nil {
		fmt.Println(err.Error())
	}
}
Пример #5
0
// makeLegend returns a legend with the default
// parameter settings.
func makeLegend() (Legend, error) {
	font, err := vg.MakeFont(defaultFont, vg.Points(12))
	if err != nil {
		return Legend{}, err
	}
	return Legend{
		ThumbnailWidth: vg.Points(20),
		TextStyle:      TextStyle{Font: font},
	}, nil
}
Пример #6
0
// makeAxis returns a default Axis.
//
// The default range is (∞, ­∞), and thus any finite
// value is less than Min and greater than Max.
func makeAxis() (Axis, error) {
	labelFont, err := vg.MakeFont(DefaultFont, vg.Points(12))
	if err != nil {
		return Axis{}, err
	}

	tickFont, err := vg.MakeFont(DefaultFont, vg.Points(10))
	if err != nil {
		return Axis{}, err
	}

	a := Axis{
		Min: math.Inf(1),
		Max: math.Inf(-1),
		LineStyle: LineStyle{
			Color: color.Black,
			Width: vg.Points(0.5),
		},
		Padding: vg.Points(5),
		Scale:   LinearScale,
	}
	a.Label.TextStyle = TextStyle{
		Color: color.Black,
		Font:  labelFont,
	}
	a.Tick.Label = TextStyle{
		Color: color.Black,
		Font:  tickFont,
	}
	a.Tick.LineStyle = LineStyle{
		Color: color.Black,
		Width: vg.Points(0.5),
	}
	a.Tick.Length = vg.Points(8)
	a.Tick.Marker = DefaultTicks

	return a, nil
}
Пример #7
0
func main() {
	ps[0].plot = linesPlot()
	ps[1].plot = histPlot()

	var err error
	font, err = vg.MakeFont("Times-Roman", vg.Points(12))
	if err != nil {
		panic(err)
	}

	win, err := x11.NewWindow()
	if err != nil {
		panic(err)
	}

	drawPlots(win.Screen())
	win.FlushImage()

	if cpuProfile != "" {
		f, err := os.Create(cpuProfile)
		if err != nil {
			panic(err)
		}
		pprof.StartCPUProfile(f)
		defer pprof.StopCPUProfile()
	}
	if memProfile != "" {
		f, err := os.Create(memProfile)
		if err != nil {
			panic(err)
		}
		pprof.WriteHeapProfile(f)
		f.Close()
	}

	events := win.EventChan()
	for ev := range events {
		if m, ok := ev.(ui.MouseEvent); ok && m.Buttons == 1 {
			winHeight := 600 // hard-coded for ui/x11…
			p, x, y := dataCoord(m.Loc.X, winHeight-m.Loc.Y)
			if p >= 0 {
				str := fmt.Sprintf("plot: %d, coord: %g, %g\n", p, x, y)
				crosshair(win.Screen(), m.Loc.X, winHeight-m.Loc.Y, str)
				win.FlushImage()
			}
		}
	}
}
Пример #8
0
// NewLabels returns a new Labels using
// the DefaultFont and the DefaultFontSize.
// An error may be returned if there is an
// error loading the default font.
func NewLabels(d interface {
	XYer
	Labeller
}) (*Labels, error) {
	fnt, err := vg.MakeFont(DefaultFont, DefaultFontSize)
	if err != nil {
		return nil, err
	}
	strs := make([]string, d.Len())
	for i := range strs {
		strs[i] = d.Label(i)
	}
	return &Labels{
		XYs:       CopyXYs(d),
		Labels:    strs,
		TextStyle: plot.TextStyle{Font: fnt},
	}, nil
}
Пример #9
0
// DrawFonts draws some text in all of the various
// fonts along with a box to make sure that their
// sizes are computed correctly.
func DrawFonts(c vg.Canvas) {
	y := vg.Points(0)
	var fonts []string
	for fname := range vg.FontMap {
		fonts = append(fonts, fname)
	}
	sort.Strings(fonts)
	for _, fname := range fonts {
		font, err := vg.MakeFont(fname, 20)
		if err != nil {
			panic(err)
		}

		w := font.Width(fname + "Xqg")
		h := font.Extents().Ascent

		c.FillString(font, 0, y-font.Extents().Descent, fname+"Xqg")
		fmt.Println(fname)

		var path vg.Path
		path.Move(0, y+h)
		path.Line(w, y+h)
		path.Line(w, y)
		path.Line(0, y)
		path.Close()
		c.Stroke(path)

		path = vg.Path{}
		c.SetColor(color.RGBA{B: 255, A: 255})
		c.SetLineDash([]vg.Length{vg.Points(5), vg.Points(3)}, 0)
		path.Move(0, y-font.Extents().Descent)
		path.Line(w, y-font.Extents().Descent)
		c.Stroke(path)
		c.SetColor(color.Black)
		c.SetLineDash([]vg.Length{}, 0)

		y += h
	}
}
Пример #10
0
func mouseTracks(scores []rings.Scorer, diameter vg.Length, lenRange int) ([]plot.Plotter, error) {
	var p []plot.Plotter

	radius := diameter / 2

	// Relative sizes.
	const (
		label = 117. / 110.

		karyotypeInner = 100. / 110.
		karyotypeOuter = 1.

		heatInner = 30. / 110.
		heatOuter = 75. / 110.

		traceInner = 80. / 110.
		traceOuter = 95. / 110.

		large = 7. / 110.
		small = 2. / 110.
	)

	sty := plotter.DefaultLineStyle
	sty.Width /= 2

	chr := make([]feat.Feature, len(mm10.Chromosomes))
	for i, c := range mm10.Chromosomes {
		chr[i] = c
	}
	mm, err := rings.NewGappedBlocks(
		chr,
		rings.Arc{rings.Complete / 4 * rings.CounterClockwise, rings.Complete * rings.Clockwise},
		radius*karyotypeInner, radius*karyotypeOuter, 0.005,
	)
	if err != nil {
		return nil, err
	}
	mm.LineStyle = sty
	p = append(p, mm)

	bands := make([]feat.Feature, len(mm10.Bands))
	cens := make([]feat.Feature, 0, len(mm10.Chromosomes))
	for i, b := range mm10.Bands {
		bands[i] = colorBand{b}
		s := b.Start()
		// This condition depends on p -> q sort order in the $karyotype.Bands variable.
		// All standard genome packages follow this, though here the test is more general than
		// actually required since mm is telocentric.
		if b.Band[0] == 'q' && (s == 0 || mm10.Bands[i-1].Band[0] == 'p') {
			cens = append(cens, colorBand{&genome.Band{Band: "cen", Desc: "Band", StartPos: s, EndPos: s, Giemsa: "acen", Chr: b.Location()}})
		}
	}
	b, err := rings.NewBlocks(bands, mm, radius*karyotypeInner, radius*karyotypeOuter)
	if err != nil {
		return nil, fmt.Errorf("bands: %v", err)
	}
	p = append(p, b)
	c, err := rings.NewBlocks(cens, mm, radius*karyotypeInner, radius*karyotypeOuter)
	if err != nil {
		return nil, fmt.Errorf("centromeres: %v", err)
	}
	p = append(p, c)

	font, err := vg.MakeFont("Helvetica", radius*large)
	if err != nil {
		return nil, err
	}
	lb, err := rings.NewLabels(mm, radius*label, rings.NameLabels(mm.Set)...)
	if err != nil {
		return nil, err
	}
	lb.TextStyle = plot.TextStyle{Color: color.Gray16{0}, Font: font}
	p = append(p, lb)

	s, err := rings.NewScores(scores, mm, radius*heatInner, radius*heatOuter,
		&rings.Heat{Palette: palette.Heat(10, 1).Colors()},
	)
	if err != nil {
		return nil, err
	}
	p = append(p, s)

	traces := make([]rings.Scorer, len(scores))
	for i, s := range scores {
		traces[i] = &tfs{s.(*fs)}
	}

	smallFont, err := vg.MakeFont("Helvetica", radius*small)
	if err != nil {
		return nil, err
	}
	t, err := rings.NewScores(traces, mm, radius*traceInner, radius*traceOuter,
		&rings.Trace{
			LineStyles: func() []plot.LineStyle {
				ls := []plot.LineStyle{sty, sty}
				for i, c := range brewer.Set1[3].Colors()[:len(ls)] {
					nc := color.NRGBAModel.Convert(c).(color.NRGBA)
					nc.A = 0x80
					ls[i].Color = nc
				}
				return ls
			}(),
			Join: true,
			Axis: &rings.Axis{
				Angle:     rings.Complete / 4,
				Grid:      plotter.DefaultGridLineStyle,
				LineStyle: sty,
				Tick: rings.TickConfig{
					Marker:    plot.DefaultTicks,
					LineStyle: sty,
					Length:    2,
					Label:     plot.TextStyle{Color: color.Gray16{0}, Font: smallFont},
				},
			},
		},
	)
	if err != nil {
		return nil, err
	}
	p = append(p, t)

	return p, nil
}
Пример #11
0
func boxplot(path string, sets []set) error {
	var (
		fiveEnds  = make([]plotter.Values, len(sets))
		threeEnds = make([]plotter.Values, len(sets))

		err error

		ln int
	)
	for i := range sets {
		fiveEnds[i], err = plotter.CopyValues(&normalised{vals: sets[i].fiveEnd})
		if err != nil {
			return err
		}
		threeEnds[i], err = plotter.CopyValues(&normalised{vals: sets[i].threeEnd})
		if err != nil {
			return err
		}
		if i == 0 {
			ln = fiveEnds[i].Len()
		}
		if fiveEnds[i].Len() != threeEnds[i].Len() || fiveEnds[i].Len() != ln {
			return errors.New("missing values")
		}
	}

	font, err := vg.MakeFont("Helvetica", 10)
	if err != nil {
		return err
	}
	titleFont, err := vg.MakeFont("Helvetica", 12)
	if err != nil {
		return err
	}
	style := plot.TextStyle{Color: color.Gray{0}, Font: font}
	p, err := plot.New()
	if err != nil {
		return err
	}
	p.Title.Text = titles[filter]
	p.Title.TextStyle = plot.TextStyle{Color: color.Gray{0}, Font: titleFont}
	p.X.Label.Text = "Length Offset"
	p.Y.Label.Text = "Relative Frequency"
	p.X.Label.TextStyle = style
	p.Y.Label.TextStyle = style
	p.X.Tick.Label = style
	p.Y.Tick.Label = style
	p.Legend.TextStyle = style

	type boxPair struct{ five, three *plotter.BoxPlot }
	var boxes []boxPair
	for i := 0; i < ln; i++ {
		fiveEnd := make(plotter.Values, len(sets))
		threeEnd := make(plotter.Values, len(sets))
		for j := range sets {
			fiveEnd[j] = fiveEnds[j][i]
			threeEnd[j] = threeEnds[j][i]
		}

		boxFivePrime, err := plotter.NewBoxPlot(1, float64(i), fiveEnd) // A non-zero width is required to prevent the creation failing.
		if err != nil {
			return err
		}
		boxFivePrime.MedianStyle.Width = 0.5
		boxFivePrime.BoxStyle.Width = 0.75
		boxFivePrime.BoxStyle.Color = plotutil.Color(0)

		boxThreePrime, err := plotter.NewBoxPlot(1, float64(i), threeEnd) // A non-zero width is required to prevent the creation failing.
		if err != nil {
			return err
		}
		boxThreePrime.MedianStyle.Width = 0.5
		boxThreePrime.BoxStyle.Width = 0.75
		boxThreePrime.BoxStyle.Color = plotutil.Color(1)

		boxes = append(boxes, boxPair{boxFivePrime, boxThreePrime})

		p.Add(boxFivePrime, boxThreePrime)
	}

	p.Legend.Add("5'-end", &plotter.BarChart{Color: plotutil.Color(0)})
	p.Legend.Add("3'-end", &plotter.BarChart{Color: plotutil.Color(1)})
	p.Legend.Top = true
	p.NominalX(func() []string {
		n := make([]string, ln)
		for i := 0; i < ln; i++ {
			if v := i - maxLength; v%5 == 0 {
				n[i] = fmt.Sprint(v)
			}
		}
		return n
	}()...)
	p.X.Width = 0.5
	p.X.Tick.Width = 0.5
	p.X.Tick.Length = 8
	p.Add(&plotter.Grid{Vertical: plotter.DefaultGridLineStyle})

	c := vgsvg.New(vg.Centimeters(19), vg.Centimeters(10))
	da := plot.MakeDrawArea(c)
	trX, _ := p.Transforms(&da)
	w := ((trX(float64(2*maxLength)) - trX(float64(0))) / vg.Length(2*maxLength)) / 3

	for _, b := range boxes {
		b.five.Width = w
		b.five.Offset = -w / 2
		b.three.Width = w
		b.three.Offset = w / 2
	}

	p.Draw(da)

	f, err := os.Create(decorate(path, "boxplot.svg", filter))
	if err != nil {
		return err
	}
	defer f.Close()
	_, err = c.WriteTo(f)

	return err
}
Пример #12
0
func barchart(path string, data set) error {
	font, err := vg.MakeFont("Helvetica", 10)
	if err != nil {
		return err
	}
	titleFont, err := vg.MakeFont("Helvetica", 12)
	if err != nil {
		return err
	}
	style := plot.TextStyle{Color: color.Gray{0}, Font: font}
	p, err := plot.New()
	if err != nil {
		return err
	}
	p.Title.Text = titles[filter]
	p.Title.TextStyle = plot.TextStyle{Color: color.Gray{0}, Font: titleFont}
	p.X.Label.Text = "Length Offset"
	p.Y.Label.Text = "Relative Frequency"
	p.X.Label.TextStyle = style
	p.Y.Label.TextStyle = style
	p.X.Tick.Label = style
	p.Y.Tick.Label = style
	p.Legend.TextStyle = style

	barsFivePrime, err := plotter.NewBarChart(&normalised{vals: data.fiveEnd}, 1) // A non-zero width is required to prevent the creation failing.
	if err != nil {
		return err
	}
	barsFivePrime.LineStyle.Width = vg.Length(0)
	barsFivePrime.Color = plotutil.Color(0)

	barsThreePrime, err := plotter.NewBarChart(&normalised{vals: data.threeEnd}, 1) // A non-zero width is required to prevent the creation failing.
	if err != nil {
		return err
	}
	barsThreePrime.LineStyle.Width = vg.Length(0)
	barsThreePrime.Color = plotutil.Color(1)

	p.Add(barsFivePrime, barsThreePrime)
	p.Legend.Add("5'-end", barsFivePrime)
	p.Legend.Add("3'-end", barsThreePrime)
	p.Legend.Top = true
	p.NominalX(func() []string {
		n := make([]string, len(data.fiveEnd))
		for i := range data.fiveEnd {
			if v := i - maxLength; v%5 == 0 {
				n[i] = fmt.Sprint(v)
			}
		}
		return n
	}()...)

	c := vgsvg.New(vg.Centimeters(19), vg.Centimeters(10))
	da := plot.MakeDrawArea(c)
	trX, _ := p.Transforms(&da)
	w := ((trX(float64(2*maxLength)) - trX(float64(0))) / vg.Length(2*maxLength)) / 3

	barsFivePrime.Width = w
	barsFivePrime.Offset = -w / 2
	barsThreePrime.Width = w
	barsThreePrime.Offset = w / 2

	p.Draw(da)

	f, err := os.Create(decorate(path, "barchart.svg", filter))
	if err != nil {
		return err
	}
	defer f.Close()
	_, err = c.WriteTo(f)

	return err
}