diff --git a/README.md b/README.md index ed0dd99..649761d 100644 --- a/README.md +++ b/README.md @@ -59,11 +59,12 @@ the area is exponentially proportional to the count indicated. Examples: ####Diagram generation options ``` + -legend draw a legend for colored regions -syn-color="#0000ff" color to use for synonymous mutation markers -mut-color="#ff0000" color to use for non-synonymous mutation markers -hide-axis do not draw the amino position x-axis - -hide-disordered do not draw disordered regions on the backbone - -hide-motifs do not draw simple motif regions + -show-disordered draw disordered regions on the backbone + -show-motifs draw simple motif regions -labels draw label text above lollipop markers -no-patterns use solid fill instead of patterns (SVG only) ``` diff --git a/data/fetch_data.go b/data/fetch_data.go index f28867e..f9f199f 100644 --- a/data/fetch_data.go +++ b/data/fetch_data.go @@ -30,6 +30,15 @@ import ( const PfamGraphicURL = "http://pfam.xfam.org/protein/%s/graphic" +// PfamMotifNames has human-readable names from http://pfam.xfam.org/help#tabview=tab9 +var PfamMotifNames = map[string]string{ + "disorder": "Disordered region (Pfam/IUPred)", + "low_complexity": "Low complexity region (Pfam/SEG)", + "sig_p": "Signal peptide region (Pfam/Phobius)", + "coiled_coil": "Coiled-coil motif (Pfam/ncoils)", + "transmembrane": "Transmembrane region (Pfam/Phobius)", +} + // PfamGraphicFeature is a generic representation of various Pfam feature responses type PfamGraphicFeature struct { Color string `json:"colour"` diff --git a/drawing/draw.go b/drawing/draw.go index 717c206..d05e23f 100644 --- a/drawing/draw.go +++ b/drawing/draw.go @@ -112,6 +112,10 @@ func (s *Settings) prepare(changelist []string, g *data.PfamGraphicResponse) *di s.GraphicHeight += s.AxisPadding + s.AxisHeight } + if s.ShowLegend { + s.legendInfo = make(map[string]string) + } + d.startY = startY d.ticks = append(d.ticks, Tick{Pos: 0, Pri: 0}, // start isn't very important (0 is implied) @@ -154,12 +158,16 @@ func (s *Settings) prepare(changelist []string, g *data.PfamGraphicResponse) *di if r.Type == "pfamb" { continue } + if r.Type == "disorder" && s.HideDisordered { + continue + } if r.Type != "disorder" { tstart, _ := r.Start.Int64() tend, _ := r.End.Int64() d.ticks = append(d.ticks, Tick{Pos: int(tstart), Pri: 1}) d.ticks = append(d.ticks, Tick{Pos: int(tend), Pri: 1}) } + s.legendInfo[r.Type] = BlendColorStrings(r.Color, "#FFFFFF") } } @@ -224,9 +232,22 @@ func (s *Settings) prepare(changelist []string, g *data.PfamGraphicResponse) *di } } + if label != r.Metadata.Description { + s.legendInfo[r.Metadata.Description] = r.Color + } d.domainLabels = append(d.domainLabels, label) } + if s.legendInfo != nil { + s.GraphicHeight += float64(1+len(s.legendInfo)) * 14.0 + for key, color := range s.legendInfo { + if rename, found := data.PfamMotifNames[key]; found { + delete(s.legendInfo, key) + s.legendInfo[rename] = color + } + } + } + sort.Sort(d.ticks) return d } diff --git a/drawing/png.go b/drawing/png.go index 30cd0bd..baf5814 100644 --- a/drawing/png.go +++ b/drawing/png.go @@ -211,6 +211,23 @@ func (s *diagram) png(w io.Writer) { } blackFontDrawer.DrawString(spos) } + startY += s.AxisHeight + } + + for key, colorstring := range s.legendInfo { + startY += 14.0 + // 15% darker than backbone (i.e. disordered color) + clr := color.RGBA{0x9E, 0xA0, 0x9A, 0xFF} + if key != data.PfamMotifNames["disorder"] { + clr = colorFromHex(BlendColorStrings(colorstring, "#FFFFFF")) + } + drawRectWHShadow(img, 4, startY, 12, 12, clr, 2*s.dpi/72.0) + + blackFontDrawer.Dot = fixed.Point26_6{ + X: fixed.I(20), + Y: fixed.I(int(startY + 12)), // 12=font height-baseline + } + blackFontDrawer.DrawString(key) } png.Encode(w, img) diff --git a/drawing/settings.go b/drawing/settings.go index 0411676..4eccf84 100644 --- a/drawing/settings.go +++ b/drawing/settings.go @@ -19,6 +19,8 @@ package drawing // Settings contains all the configurable options for lollipop diagram generation. type Settings struct { + // ShowLegend adds a color-coding legend above the diagram. + ShowLegend bool // ShowLabels adds mutation label text above lollipops markers. ShowLabels bool // HideDisordered hides disordered regions on the backbone even if motifs are shown. @@ -68,11 +70,14 @@ type Settings struct { GraphicHeight float64 dpi float64 + + legendInfo map[string]string } // DefaultSettings contains the "standard" diagram output config and is used by // the package-level Draw invocations. var DefaultSettings = Settings{ + ShowLegend: false, ShowLabels: false, HideDisordered: false, HideMotifs: false, diff --git a/drawing/svg.go b/drawing/svg.go index 615f1e3..20aeb90 100644 --- a/drawing/svg.go +++ b/drawing/svg.go @@ -173,6 +173,17 @@ func (s *diagram) svg(w io.Writer) { } fmt.Fprintln(w, "") + startY += s.AxisHeight + } + + for key, color := range s.legendInfo { + startY += 14.0 + if key == data.PfamMotifNames["disorder"] { + color = disFill + } + fmt.Fprintf(w, ``, color, startY) + fmt.Fprintf(w, `%s`, + fontSpec, startY+12, key) // 12=font height-baseline } fmt.Fprintln(w, svgFooter) diff --git a/main.go b/main.go index be19297..c5b7b22 100644 --- a/main.go +++ b/main.go @@ -39,6 +39,7 @@ var ( width = flag.Int("w", 0, "output width (default automatic fit labels)") dpi = flag.Float64("dpi", 72, "output DPI for PNG rasterization") + showLegend = flag.Bool("legend", false, "draw a legend for colored regions") showLabels = flag.Bool("labels", false, "draw mutation labels above lollipops") showDisordered = flag.Bool("show-disordered", false, "draw disordered regions on the backbone") showMotifs = flag.Bool("show-motifs", false, "draw simple motif regions") @@ -91,6 +92,7 @@ Protein changes: (N.B. color must come before count in tags) Diagram generation options: + -legend draw a legend for colored regions -syn-color="#0000ff" color to use for synonymous mutation markers -mut-color="#ff0000" color to use for non-synonymous mutation markers -hide-axis do not draw the amino position x-axis @@ -110,6 +112,7 @@ Output options: } flag.Parse() + drawing.DefaultSettings.ShowLegend = *showLegend drawing.DefaultSettings.ShowLabels = *showLabels drawing.DefaultSettings.HideDisordered = !*showDisordered drawing.DefaultSettings.HideMotifs = !*showMotifs @@ -208,5 +211,4 @@ Press Enter/Ctrl-C to quit.`) } else { drawing.DrawSVG(f, flag.Args()[varStart:], data) } - }