Example #1
0
func tracks(scores []rings.Scorer, diameter vg.Length) ([]plot.Plotter, error) {
	var p []plot.Plotter

	radius := diameter / 2

	// Relative sizes.
	const (
		gap = 0.005

		label = 117. / 110.

		countsInner = 97. / 110.
		countsOuter = 70. / 110.

		karyotypeInner = 100. / 110.
		karyotypeOuter = 1.

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

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

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

	p = append(p, hs)

	bands := make([]feat.Feature, len(hg19.Bands))
	cens := make([]feat.Feature, 0, len(hg19.Chromosomes))
	for i, b := range hg19.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 hs is telocentric.
		if b.Band[0] == 'q' && (s == 0 || hg19.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, hs, radius*karyotypeInner, radius*karyotypeOuter)
	if err != nil {
		return nil, fmt.Errorf("bands: %v", err)
	}
	p = append(p, b)
	c, err := rings.NewBlocks(cens, hs, 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(hs, radius*label, rings.NameLabels(hs.Set)...)
	if err != nil {
		return nil, err
	}
	lb.TextStyle = draw.TextStyle{Color: color.Gray16{0}, Font: font}
	p = append(p, lb)

	smallFont, err := vg.MakeFont("Helvetica", radius*small)
	if err != nil {
		return nil, err
	}

	counts := make([]rings.Scorer, len(scores))
	for i, s := range scores {
		counts[i] = s.(*feature)
	}
	ct, err := rings.NewScores(counts, hs, radius*countsInner, radius*countsOuter,
		&rings.Trace{
			LineStyles: func() []draw.LineStyle {
				ls := []draw.LineStyle{sty}
				ls[0].Color = color.Gray16{0}
				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:     draw.TextStyle{Color: color.Gray16{0}, Font: smallFont},
				},
			},
		},
	)
	if err != nil {
		return nil, err
	}
	p = append(p, ct)

	return p, nil
}
Example #2
0
func mouseTracks(scores []rings.Scorer, highlight []string, palname string, diameter vg.Length, lenRange int) (pp []plot.Plotter, lo, hi float64, err error) {
	var p []plot.Plotter

	radius := diameter / 2

	// Relative sizes.
	const (
		gap = 0.005

		label = 117. / 110.

		countsInner = 25. / 110.
		countsOuter = 40. / 110.

		heatInner = 45. / 110.
		heatOuter = 75. / 110.

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

		karyotypeInner = 100. / 110.
		karyotypeOuter = 1.

		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, gap,
	)
	if err != nil {
		return nil, 0, 0, err
	}
	mm.LineStyle = sty

	pal, err := brewer.GetPalette(brewer.TypeQualitative, palname, len(highlight))
	if err == nil {
		for i, hn := range highlight {
			for _, c := range mm.Set {
				if hn == strings.ToLower(c.Name()) {
					arc, err := mm.Base.ArcOf(c, nil)
					arc.Theta += rings.Complete * gap / 2
					arc.Phi -= rings.Complete * gap
					if err != nil {
						fmt.Printf("could not find: %s\n", hn)
						break
					}
					col := pal.Colors()[i]
					nc := color.NRGBAModel.Convert(col).(color.NRGBA)
					nc.A = 0x40
					h := rings.NewHighlight(
						nc,
						arc,
						radius*(traceInner-2.5/110.),
						radius*(label+5./110.),
					)
					h.LineStyle = sty
					h.LineStyle.Width /= 4
					p = append(p, h)
					break
				}
			}
		}
	} else if len(highlight) > 0 {
		fmt.Println("no palette")
	}

	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, 0, 0, fmt.Errorf("bands: %v", err)
	}
	p = append(p, b)
	c, err := rings.NewBlocks(cens, mm, radius*karyotypeInner, radius*karyotypeOuter)
	if err != nil {
		return nil, 0, 0, fmt.Errorf("centromeres: %v", err)
	}
	p = append(p, c)

	font, err := vg.MakeFont("Helvetica", radius*large)
	if err != nil {
		return nil, 0, 0, err
	}
	lb, err := rings.NewLabels(mm, radius*label, rings.NameLabels(mm.Set)...)
	if err != nil {
		return nil, 0, 0, err
	}
	lb.TextStyle = draw.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, 0, 0, err
	}
	p = append(p, s)

	smallFont, err := vg.MakeFont("Helvetica", radius*small)
	if err != nil {
		return nil, 0, 0, err
	}

	traces := make([]rings.Scorer, len(scores))
	for i, s := range scores {
		traces[i] = &tfs{s.(*feature)}
	}
	t, err := rings.NewScores(traces, mm, radius*traceInner, radius*traceOuter,
		&rings.Trace{
			LineStyles: func() []draw.LineStyle {
				ls := []draw.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:     draw.TextStyle{Color: color.Gray16{0}, Font: smallFont},
				},
			},
		},
	)
	if err != nil {
		return nil, 0, 0, err
	}
	if maxTrace != 0 {
		t.Max = maxTrace
		if t.Min > t.Max {
			return nil, 0, 0, fmt.Errorf("maximum trace out of range: min=%f", t.Min)
		}
	}
	if !math.IsInf(t.Max-t.Min, 0) {
		p = append(p, t)
	}

	counts := make([]rings.Scorer, len(scores))
	for i, s := range scores {
		counts[i] = ctfs{s.(*feature)}
	}
	ct, err := rings.NewScores(counts, mm, radius*countsInner, radius*countsOuter,
		&rings.Trace{
			LineStyles: func() []draw.LineStyle {
				ls := []draw.LineStyle{sty}
				ls[0].Color = color.Gray16{0}
				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:     draw.TextStyle{Color: color.Gray16{0}, Font: smallFont},
				},
			},
		},
	)
	if err != nil {
		return nil, 0, 0, err
	}
	if maxCounts != 0 {
		ct.Max = maxCounts
		if ct.Min > ct.Max {
			return nil, 0, 0, fmt.Errorf("maximum counts out of range: min=%f", ct.Min)
		}
	}
	p = append(p, ct)

	return p, s.Min, s.Max, nil
}