Text wrapping with dot (graphviz)

Recently I have been studying a software application that introduces some novel algorithms for correcting errors in next-generation sequencing data. To better understand exactly what one algorithm was doing, I wrote down the logic (flowchart style) on a piece of paper. This was a very helpful process. However, I wanted to copy a preserve electronically. Since my pseudo-flowchart was pretty much a binary tree, I decided I would create a graphic with the graphviz tool.

I learned the bare essentials of graphviz a few years ago, so after looking at some of my old examples I created this .dot file.

digraph
{
  node [color=Blue,shape=box]

  1.1 [label="Frequency of t exceeds upper threshold"]
  2.1 [label="t has d-mutant tiles"]
  2.2 [label="Valid"]
  3.1 [label="Frequency of t exceeds lower threshold"]
  3.2 [label="Frequency of t exceeds lower threshold"]
  4.1 [label="Insufficient evidence"]
  4.2 [label="Valid"]
  4.3 [label="t has only one d-mutant that exceeds lower threshold"]
  4.4 [label="Are there any d-mutant tiles with significantly higher frequencies?"]
  5.1 [label="Insufficient evidence"]
  node [color=Green] 5.2 [label="Correct t to t'"] node [color=Blue]
  5.3 [label="t has a d-mutant tile t' that is closer than all other d-mutant tiles and for which a corrected base has a higher quality score"]
  5.4 [label="Valid"]
  6.1 [label="Insufficient evidence"]
  6.2 [label="t' is unique"]
  7.1 [label="Insufficient evidence"]
  node [color=Green] 7.2 [label="Correct t to t'"] node [color=Blue]

  1.1 -> 2.1 [label="no"]
  1.1 -> 2.2 [label="yes"]
  2.1 -> 3.1 [label="no"]
  2.1 -> 3.2 [label="yes"]
  3.1 -> 4.1 [label="no"]
  3.1 -> 4.2 [label="yes"]
  3.2 -> 4.3 [label="no"]
  3.2 -> 4.4 [label="yes"]
  4.3 -> 5.1 [label="no"]
  4.3 -> 5.2 [label="yes"]
  4.4 -> 5.3 [label="no"]
  4.4 -> 5.4 [label="yes"]
  5.3 -> 6.1 [label="no"]
  5.3 -> 6.2 [label="yes"]
  6.2 -> 7.1 [label="no"]
  6.2 -> 7.2 [label="yes"]
}

The command to create a .png graphic from this file was easy.

dot -Tpng -o test.png test.dot

The result was almost what I was looking for, but not quite (click on the image for full-size version).

Tile error correction: wide

The problem is that the boxes containing a lot of text are are too wide. Unfortunately, graphviz does not allow automatic text wrapping, so you have to control box width by manually inserting \n characters into the box labels. Anyone that has done something like this before knows how tedious this process can be, and how frustrating it is to redo when you need to change the label text.

Instead, I wrote a simple Perl script that will automatically add line breaks to labels so that the label width does not exceed some given number.

#!/usr/bin/perl
use strict;

my $usage = "setdotlabelwidth [char-width] < [dotfile]";
my $width = shift() or die("Usage: $usage $!");

while(<STDIN>)
{
  if(m/label="(.*?)"/)
  {
    my $labeltext = $1;
    my @words = split(/ /, $labeltext);
    my @newtext = ();
    my $newline = "";
    foreach my $word(@words)
    {
      if( length($newline) > 0 and
          length($newline) + length($word) > $width )
      {
        push(@newtext, $newline);
        $newline = "";
      }
      $newline .= " " if( length($newline) > 0 );
      $newline .= $word;
    }
    push(@newtext, $newline) if( length($newline) > 0 );
    my $newlabel = join("\\n", @newtext);
    s/label=".*?"/label="$newlabel"/;
  }
  print;
}

I saved this program as setdotlabelwidth, ran it, and simply piped the output into graphviz. In this case, I set the width to 35 characters.

./setdotlabelwidth 35 < tile-error-correction.dot | dot -Tpng -o tile-error-correction.png

Voilà, the graphic looks much nicer now! Again, click on the image for the full-size version.

Tile error correction

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s