14

The following TikZ code shows a representation of DNA code segments.

I have two different versions of this code. Version 1 uses multipart rectangles, and is my preferred version. Version 2 models the DNA sequences as individual squares stuck together. The issue with that is that these squares tend to come unstuck on changing scale, which is annoying.

Partly for that reason, I prefer version 1, but it has some problems. If these can't be fixed, then I will use version 2.

Here is the problems.

1) The block on the left, call this block A, has the colors bleeding outside the boxes in some places. Particularly on the right side. See for example the bottom right corner, where the square flanked by $X_{9}$ and $X^{(6)}$. Here this bleeding of the color out of the square is quite noticeable. It can be seen in other places as well. This effect becomes much less if

\tikzstyle{every path}=[very thick]

is removed. However, I want the thick paths. This might be the result of user error, or a bug. I think it might be the cumulative result of rounding errors as TikZ moves along calculating the dimensions of the parts of the rectangle, since it gets worse as one moves to the right. The question is whether there is a way around it.

2) The arrows from block A to the right should have an arrow head only at the termination point, but has arrows on both ends.

3) The boxes on the left and the right should be aligned. They are aligned on the top, but not the bottom.

Finally, a few questions which are not strictly problems.

4) Any suggestions to stop the arrows from obscuring the labels? Maybe make the labels a different color? Is there an easy way to superimpose the labels on top of the arrows?

5) Is there any way to make the division lines within the multipart rectangles a different thickness from the other lines?

6) How can I make the block of code which begins with

\node [below] at (leftrow6.one south) {$\mathsmaller{\mathbf{X_{0}}}$};

into a loop? An attempt is below, namely

\foreach \i in {one, two, three, four, five, six, seven, eight, nine, ten}
{
  \foreach \j in {0,...,9}
  {
    \node [below] at (leftrow6.\i south) {$\mathsmaller{\mathbf{X_{\j}}}$};
  }
}

but this does not work.

The code for the two versions follow. Suggestions for improvement, including reducing lines of code appreciated. The image for version 1 is at the bottom.

Version 1

\documentclass[a4paper, 12pt]{article}
\usepackage{tikz}
\usetikzlibrary{shapes,arrows, positioning, calc, patterns, shadows, external}
%%%<
\usepackage{verbatim}
\usepackage{lmodern}
\usepackage{scrextend}
\usepackage{relsize}
\usepackage[active,tightpage]{preview}
\PreviewEnvironment{tikzpicture}
\setlength\PreviewBorder{5pt}%
%%%>
\usetikzlibrary{chains,fit,shapes, shapes.multipart}
\begin{document}
\changefontsizes{20pt}
\begin{tikzpicture}
\tikzstyle{every path}=[very thick]
\tikzstyle{line} = [draw, -latex', thick]

\tikzstyle{seq}=[rectangle split, rectangle split horizontal, rectangle split parts=#1, minimum height=1cm, draw, anchor=center]

\matrix[row sep=0.5cm] at (0cm, 4cm)
{
\node [seq=10, rectangle split part fill={blue!20, none, cyan!30, none, blue!20, none, none, cyan!30, none, cyan!30}] (leftrow1)
{C \nodepart{two} \phantom{X} \nodepart{three} A \nodepart{four} \phantom{X} \nodepart{five} G \nodepart{six} \phantom{X} \nodepart{seven} \phantom{X} \nodepart{eight} G \nodepart{nine} \phantom{X} \nodepart{ten} C}; \\

\node [seq=10, rectangle split part fill={green!20, none, orange!50, none, green!20, none, none, orange!50, none, orange!50}] (leftrow2)
{A \nodepart{two} \phantom{X} \nodepart{three} C \nodepart{four} \phantom{X} \nodepart{five} C \nodepart{six} \phantom{X} \nodepart{seven} \phantom{X} \nodepart{eight} A \nodepart{nine} \phantom{X} \nodepart{ten} A}; \\

\node [seq=10, rectangle split part fill={green!20, none, yellow!50, none, green!20, none, none, yellow!50, none, yellow!50}] (leftrow3)
{A \nodepart{two} \phantom{X} \nodepart{three} T \nodepart{four} \phantom{X} \nodepart{five} C \nodepart{six} \phantom{X} \nodepart{seven} \phantom{X} \nodepart{eight} T \nodepart{nine} \phantom{X} \nodepart{ten} T}; \\

\node [seq=10, rectangle split part fill={blue!20, none, cyan!30, none, blue!20, none, none, cyan!30, none, cyan!30}] (leftrow4)
{C \nodepart{two} \phantom{X} \nodepart{three} A \nodepart{four} \phantom{X} \nodepart{five} G \nodepart{six} \phantom{X} \nodepart{seven} \phantom{X} \nodepart{eight} G \nodepart{nine} \phantom{X} \nodepart{ten} C}; \\

\node [seq=10, rectangle split part fill={blue!20, none, cyan!30, none, blue!20, none, none, cyan!30, none, cyan!30}] (leftrow5)
{C \nodepart{two} \phantom{X} \nodepart{three} A \nodepart{four} \phantom{X} \nodepart{five} G \nodepart{six} \phantom{X} \nodepart{seven} \phantom{X} \nodepart{eight} G \nodepart{nine} \phantom{X} \nodepart{ten} C}; \\

\node [seq=10, rectangle split part fill={red!50, none, orange!50, none, red!50, none, none, orange!50, none, orange!50}] (leftrow6)
{A \nodepart{two} \phantom{X} \nodepart{three} C \nodepart{four} \phantom{X} \nodepart{five} A \nodepart{six} \phantom{X} \nodepart{seven} \phantom{X} \nodepart{eight} A \nodepart{nine} \phantom{X} \nodepart{ten} A}; \\
};

\node [below] at (leftrow6.one south) {$\mathsmaller{\mathbf{X_{0}}}$};
\node [below] at (leftrow6.two south) {$\mathsmaller{\mathbf{X_{1}}}$};
\node [below] at (leftrow6.three south) {$\mathsmaller{\mathbf{X_{2}}}$};
\node [below] at (leftrow6.four south) {$\mathsmaller{\mathbf{X_{3}}}$};
\node [below] at (leftrow6.five south) {$\mathsmaller{\mathbf{X_{4}}}$};
\node [below] at (leftrow6.six south) {$\mathsmaller{\mathbf{X_{5}}}$};
\node [below] at (leftrow6.seven south) {$\mathsmaller{\mathbf{X_{6}}}$};
\node [below] at (leftrow6.eight south) {$\mathsmaller{\mathbf{X_{7}}}$};
\node [below] at (leftrow6.nine south) {$\mathsmaller{\mathbf{X_{8}}}$};
\node [below] at (leftrow6.ten south) {$\mathsmaller{\mathbf{X_{9}}}$};

%loop version does not work
%\foreach \i in {{one}, {two}, {three}, {four}, {five}, {six}, {seven}, {eight},   
%{nine}, {ten}}
%{
%  \foreach \j in {0,...,9}
% {
%    \node [below] at (leftrow6.\i south) {$\mathsmaller{\mathbf{X_{\j}}}$};
% }
%}

% loop version does not work
\foreach \i in {1,...,6}
{
  \node [right] at (leftrow\i.ten east) {$\mathsmaller{\mathbf{X^{(\i)}}}$};
}

\matrix[row sep=0.5cm] at (10cm, 4cm)
{
\node [seq=2, rectangle split part fill={blue!20, blue!20}] (tupletoprow)
{C \nodepart{two} G}; \\
\node [seq=2, rectangle split part fill={green!20, green!20}]
{A \nodepart{two} C}; \\
\node [seq=2, rectangle split part fill={green!20, green!20}]
{A \nodepart{two} C}; \\
\node [seq=2, rectangle split part fill={blue!20, blue!20}]
{C \nodepart{two} G}; \\
\node [seq=2, rectangle split part fill={blue!20, blue!20}]
{C \nodepart{two} G}; \\
\node [seq=2, rectangle split part fill={red!50, red!50}] (tuplebottomrow)
{A \nodepart{two} A}; \\
};

\matrix[row sep=0.5cm] at (13cm, 4cm)
{
  \node [seq=3, rectangle split part fill={cyan!30, cyan!30}] (tripletoprow)
  {A \nodepart{two} G \nodepart{three} C}; \\
  \node [seq=3, rectangle split part fill={orange!50, orange!50}]
  {C \nodepart{two} A \nodepart{three} A}; \\
  \node [seq=3, rectangle split part fill={yellow!50, yellow!50}]
  {T \nodepart{two} T \nodepart{three} T}; \\
  \node [seq=3, rectangle split part fill={cyan!30, cyan!30}]
  {A \nodepart{two} G \nodepart{three} C}; \\
  \node [seq=3, rectangle split part fill={cyan!30, cyan!30}]
  {A \nodepart{two} G \nodepart{three} C}; \\
 \node [seq=3, rectangle split part fill={orange!50, orange!50}]  (triplebottomrow)
  {C \nodepart{two} A \nodepart{three} A}; \\
};

\node [below] at (tuplebottomrow.south) {$(\mathsmaller{\mathbf{X_{0}}}, \mathsmaller{\mathbf{X_{4}}})$};
\node [below] at (triplebottomrow.south) {$(\mathsmaller{\mathbf{X_{3}}}, \mathsmaller{\mathbf{X_{7}}}, , \mathsmaller{\mathbf{X_{9}}})$};

\node [above] at (tupletoprow.north) {(0, 4)};
\node [above] at (tripletoprow.north) {(3, 7, 9)};

\path [line] (leftrow6.one south) edge[out=270, in=270] node {}(tuplebottomrow);
\path [line] (leftrow6.five south) edge[out=270, in=270] node {}(tuplebottomrow);

\path [line] (leftrow1.three north) edge[out=90, in=90] node {}(tripletoprow);
\path [line] (leftrow1.eight north) edge[out=90, in=90] node {}(tripletoprow);
\path [line] (leftrow1.ten north) edge[out=90, in=90] node {}(tripletoprow);

\end{tikzpicture}
\changefontsizes{12pt}
\end{document}

Version 2

\documentclass[a4paper, 12pt]{article}
\usepackage{tikz}
\usetikzlibrary{shapes,arrows, positioning, calc, patterns, shadows, external}
\usepackage{verbatim}
\usepackage{lmodern}
\usepackage{scrextend}
\usepackage[active,tightpage]{preview}
\PreviewEnvironment{tikzpicture}
\setlength\PreviewBorder{5pt}%
\usetikzlibrary{chains,fit,shapes}

\begin{document}
\changefontsizes{15pt}
\begin{tikzpicture}
\tikzstyle{every path}=[very thick]
\tikzstyle{line} = [draw, -latex', thick]
\edef\sizeseqbox{1.3cm}
\tikzstyle{seq}=[draw,minimum size=\sizeseqbox]

\matrix [row sep=3mm] at (-7, 0)
{
  \node []{}; & \node []{}; & \node [] {}; & \node []{}; & \node []{}; & \node []{}; & \node []{}; & \node []{}; & \node []{}; & \node [] {}; \\
  \node [seq, fill=blue!20]{C}; & \node [seq]{}; & \node [seq, fill=cyan!30] (triplecol1left) {A}; & \node [seq]{}; & \node [seq, fill=blue!20]{G}; & \node [seq]{}; & \node [seq]{}; & \node [seq, fill=cyan!30] (triplecol2left) {G}; & \node [seq]{}; & \node [seq, fill=cyan!30] (triplecol3left) {C}; & \node [] {$\mathbf{X^{(1)}}$};\\
  \node [seq, fill=green!20]{A}; & \node [seq]{}; & \node [seq, fill=orange!50]{C}; & \node [seq]{}; & \node [seq, fill=green!20]{C}; & \node [seq]{}; & \node [seq]{}; & \node [seq, fill=orange!50]{A}; & \node [seq]{}; & \node [seq, fill=orange!50]{A}; & \node [] {$\mathbf{X^{(2)}}$};\\
  \node [seq, fill=green!20]{A}; & \node [seq]{}; & \node [seq, fill=yellow!50]{T}; & \node [seq]{}; & \node [seq, fill=green!20]{C}; & \node [seq]{}; & \node [seq]{}; & \node [seq, fill=yellow!50]{T}; & \node [seq]{}; & \node [seq, fill=yellow!50]{T}; & \node [] {$\mathbf{X^{(3)}}$};\\
  \node [seq, fill=blue!20]{C}; & \node [seq]{}; & \node [seq, fill=cyan!30]{A}; & \node [seq]{}; & \node [seq, fill=blue!20]{G}; & \node [seq]{}; & \node [seq]{}; & \node [seq, fill=cyan!30]{G}; & \node [seq]{}; & \node [seq, fill=cyan!30]{C}; & \node [] {$\mathbf{X^{(4)}}$};\\
  \node [seq, fill=blue!20]{C}; & \node [seq]{}; & \node [seq, fill=cyan!30]{A}; & \node [seq]{}; & \node [seq, fill=blue!20]{G}; & \node [seq]{}; & \node [seq]{}; & \node [seq, fill=cyan!30]{G}; & \node [seq]{}; & \node [seq, fill=cyan!30]{C}; & \node [] {$\mathbf{X^{(5)}}$};\\
  \node [seq, fill=red!50] (tuplecol1left) {A}; & \node [seq]{}; & \node [seq, fill=orange!50] {C}; & \node [seq]{}; & \node [seq, fill=red!50] (tuplecol2left)  {A}; & \node [seq]{}; & \node [seq]{}; & \node [seq, fill=orange!50] {A}; & \node [seq]{}; & \node [seq, fill=orange!50] {A}; & \node [] {$\mathbf{X^{(6)}}$};\\
  \node []{$\mathbf{X_{0}}$}; & \node []{$\mathbf{X_{1}}$}; & \node [] {$\mathbf{X_{2}}$}; & \node []{$\mathbf{X_{3}}$}; & \node []{$\mathbf{X_{4}}$}; & \node []{$\mathbf{X_{5}}$}; & \node []{$\mathbf{X_{6}}$}; & \node []{$\mathbf{X_{7}}$}; & \node []{$\mathbf{X_{8}}$}; & \node [] {$\mathbf{X_{9}}$}; \\
};

\matrix [row sep=3mm] at (5, 0)
{
 \node [] {(0,}; & \node [] {4)}; \\
  \node [seq, fill=blue!20]{C}; & \node [seq, fill=blue!20]{G}; \\
  \node [seq, fill=green!20]{A}; & \node [seq, fill=green!20]{C}; \\
  \node [seq, fill=green!20]{A}; & \node [seq, fill=green!20]{C}; \\
  \node [seq, fill=blue!20]{C}; & \node [seq, fill=blue!20]{G}; \\
  \node [seq, fill=blue!20]{C}; & \node [seq, fill=blue!20]{G}; \\
  \node [seq, fill=red!50] (tuplecol1right) {A}; & \node [seq, fill=red!50] (tuplecol2right) {A}; \\
  \node [] {$(\mathbf{X_0},$}; & \node [] {$\mathbf{X_4})$}; \\
};

\matrix [row sep=3mm] at (9, 0)
{
  \node [] {(2,};                 & \node [] {7,};                   & \node [] {9)};                   \\
  \node [seq, fill=cyan!30] (triplecol1right) {A}; & \node [seq, fill=cyan!30]  (triplecol2right) {G}; & \node [seq, fill=cyan!30] (triplecol3right) {C}; \\
  \node [seq, fill=orange!50]{C}; & \node [seq, fill=orange!50]{A}; & \node [seq, fill=orange!50]{A}; \\
  \node [seq, fill=yellow!50]{T}; & \node [seq, fill=yellow!50]{T}; & \node [seq, fill=yellow!50]{T}; \\
  \node [seq, fill=cyan!30]{A};   & \node [seq, fill=cyan!30]{G};   & \node [seq, fill=cyan!30]{C};   \\
  \node [seq, fill=cyan!30]{A};   & \node [seq, fill=cyan!30]{G};   & \node [seq, fill=cyan!30]{C};   \\
  \node [seq, fill=orange!50] {C};& \node [seq, fill=orange!50] {A};& \node [seq, fill=orange!50] {A};\\
  \node [] {($\mathbf{X_2},$};                   & \node [] {$\mathbf{X_7},$};                   & \node [] {$\mathbf{X_9})$};                   \\
};

\path [line] (tuplecol1left) edge[out=270, in=270] node {}(tuplecol1right.south east);
\path [line] (tuplecol2left) edge[out=270, in=270] node {}(tuplecol2right.south west);

\path [line] (triplecol1left) edge[out=90, in=90] node {}(triplecol2right);
\path [line] (triplecol2left) edge[out=90, in=90] node {}(triplecol2right);
\path [line] (triplecol3left) edge[out=90, in=90] node {}(triplecol2right);

\end{tikzpicture}
\changefontsizes{12pt}
\end{document}

enter image description here

4
  • There seems to several unrelated questions here: color bleed outside of multi part rectangles, arrow heads on both ends and shorter arrows, alignment of boxes, different division lines of multipart rectangles, looping construct. I would suggest you compose separate questions on these specific items as then those questions/answers will be helpful to others, and also be easier to find. Commented Nov 8, 2012 at 19:25
  • 1
    I would have done this in a totally different way using listings for typesetting different characters with different colors in a DNA sequence and, or similar processing in tikz to add coloring and boxes, with automatic insertion of \tikzmark at each node. Then do the arrow drawgins based on the \tikzmarks. Commented Nov 8, 2012 at 19:28
  • @PeterGrill: I guess you might be right about the multiple questions thing. I suppose I was lazy. I'd be interested in a different approach to this, if you feel like providing details. Commented Nov 8, 2012 at 20:05
  • Change fontsize inside float in KOMA class
    – Johannes_B
    Commented Jan 17, 2015 at 13:31

2 Answers 2

12

1) and 3) Change none to white when filling the parts of the rectangles.

2) Change the stile for the line to have arrow tip only on one end (I wasn't sure which ones to you wanted to change, so I chose the two on the bottom).

4) One possibility is to draw the arrows first, and then place the labels (shifting them a little bit vertically, if required).

6) Loops fixed.

Additionally, I changed from the old \tikzstyle syntax to the newer \tikzset.

\documentclass[a4paper, 12pt]{article}
\usepackage{tikz}
\usetikzlibrary{shapes,arrows, positioning, calc, patterns, shadows, external}
%%%<
\usepackage{verbatim}
\usepackage{lmodern}
\usepackage{scrextend}
\usepackage{relsize}
\usepackage[active,tightpage]{preview}
\PreviewEnvironment{tikzpicture}
\setlength\PreviewBorder{5pt}%
%%%>
\usetikzlibrary{chains,fit,shapes, shapes.multipart}

\begin{document}
\changefontsizes{20pt}
\begin{tikzpicture}
\tikzset{
  every path/.style={very thick},
  line/.style={draw, -latex', thick},
  seq/.style={rectangle split,
    rectangle split horizontal,
    rectangle split parts=#1,
    minimum height=1cm,
    draw, anchor=center}
}

\matrix[row sep=0.5cm] at (0cm, 4cm)
{
\node [seq=10, rectangle split part fill={blue!20,white, cyan!30,white, blue!20, white, white, cyan!30,white,cyan!30}] (leftrow1)
{C \nodepart{two} \phantom{X} \nodepart{three} A \nodepart{four} \phantom{X} \nodepart{five} G \nodepart{six} \phantom{X} \nodepart{seven} \phantom{X} \nodepart{eight} G \nodepart{nine} \phantom{X} \nodepart{ten} C}; \\

\node [seq=10, rectangle split part fill={green!20, white, orange!50, white, green!20, white, white, orange!50, white, orange!50}] (leftrow2)
{A \nodepart{two} \phantom{X} \nodepart{three} C \nodepart{four} \phantom{X} \nodepart{five} C \nodepart{six} \phantom{X} \nodepart{seven} \phantom{X} \nodepart{eight} A \nodepart{nine} \phantom{X} \nodepart{ten} A}; \\

\node [seq=10, rectangle split part fill={green!20, white, yellow!50, white, green!20, white, white, yellow!50, white, yellow!50}] (leftrow3)
{A \nodepart{two} \phantom{X} \nodepart{three} T \nodepart{four} \phantom{X} \nodepart{five} C \nodepart{six} \phantom{X} \nodepart{seven} \phantom{X} \nodepart{eight} T \nodepart{nine} \phantom{X} \nodepart{ten} T}; \\

\node [seq=10, rectangle split part fill={blue!20, white, cyan!30, white, blue!20, white, white, cyan!30, white, cyan!30}] (leftrow4)
{C \nodepart{two} \phantom{X} \nodepart{three} A \nodepart{four} \phantom{X} \nodepart{five} G \nodepart{six} \phantom{X} \nodepart{seven} \phantom{X} \nodepart{eight} G \nodepart{nine} \phantom{X} \nodepart{ten} C}; \\

\node [seq=10, rectangle split part fill={blue!20, white, cyan!30, white, blue!20, white, white, cyan!30, white, cyan!30}] (leftrow5)
{C \nodepart{two} \phantom{X} \nodepart{three} A \nodepart{four} \phantom{X} \nodepart{five} G \nodepart{six} \phantom{X} \nodepart{seven} \phantom{X} \nodepart{eight} G \nodepart{nine} \phantom{X} \nodepart{ten} C}; \\

\node [seq=10, rectangle split part fill={red!50, white, orange!50, white, red!50, white, white, orange!50, white, orange!50}] (leftrow6)
{A \nodepart{two} \phantom{X} \nodepart{three} C \nodepart{four} \phantom{X} \nodepart{five} A \nodepart{six} \phantom{X} \nodepart{seven} \phantom{X} \nodepart{eight} A \nodepart{nine} \phantom{X} \nodepart{ten} A}; \\
};

\matrix[row sep=0.5cm] at (10cm, 4cm)
{
\node [seq=2, rectangle split part fill={blue!20, blue!20}] (tupletoprow)
{C \nodepart{two} G}; \\
\node [seq=2, rectangle split part fill={green!20, green!20}]
{A \nodepart{two} C}; \\
\node [seq=2, rectangle split part fill={green!20, green!20}]
{A \nodepart{two} C}; \\
\node [seq=2, rectangle split part fill={blue!20, blue!20}]
{C \nodepart{two} G}; \\
\node [seq=2, rectangle split part fill={blue!20, blue!20}]
{C \nodepart{two} G}; \\
\node [seq=2, rectangle split part fill={red!50, red!50}] (tuplebottomrow)
{A \nodepart{two} A}; \\
};

\matrix[row sep=0.5cm] at (13cm, 4cm)
{
  \node [seq=3, rectangle split part fill={cyan!30, cyan!30}] (tripletoprow)
  {A \nodepart{two} G \nodepart{three} C}; \\
  \node [seq=3, rectangle split part fill={orange!50, orange!50}]
  {C \nodepart{two} A \nodepart{three} A}; \\
  \node [seq=3, rectangle split part fill={yellow!50, yellow!50}]
  {T \nodepart{two} T \nodepart{three} T}; \\
  \node [seq=3, rectangle split part fill={cyan!30, cyan!30}]
  {A \nodepart{two} G \nodepart{three} C}; \\
  \node [seq=3, rectangle split part fill={cyan!30, cyan!30}]
  {A \nodepart{two} G \nodepart{three} C}; \\
  \node [seq=3, rectangle split part fill={orange!50, orange!50}]  (triplebottomrow)
  {C \nodepart{two} A \nodepart{three} A}; \\
};

\path [latex'-, thick] (leftrow6.one south) edge[out=270, in=270] node {}(tuplebottomrow);
\path [latex'-, thick] (leftrow6.five south) edge[out=270, in=270] node {}(tuplebottomrow);

\path [line] (leftrow1.three north) edge[out=90, in=90] node {}(tripletoprow);
\path [line] (leftrow1.eight north) edge[out=90, in=90] node {}(tripletoprow);
\path [line] (leftrow1.ten north) edge[out=90, in=90] node {}(tripletoprow);

%loop version works
\foreach \i [count=\x] in {one ,two ,three ,four ,five ,six ,seven ,eight ,nine ,ten }
    \node [below=8pt,fill=white] at (leftrow6.\i south) {$\mathsmaller{\mathbf{X_{\x}}}$};

% loop version works
\foreach \i in {1,...,6}
{
  \node [right] at (leftrow\i.ten east) {$\mathsmaller{\mathbf{X^{(\i)}}}$};
}

\node [below=8pt,fill=white] at (tuplebottomrow.south) {$(\mathsmaller{\mathbf{X_{0}}}, \mathsmaller{\mathbf{X_{4}}})$};
\node [below=8pt,fill=white] at (triplebottomrow.south) {$(\mathsmaller{\mathbf{X_{3}}}, \mathsmaller{\mathbf{X_{7}}}, , \mathsmaller{\mathbf{X_{9}}})$};

\node [above=8pt] at (tupletoprow.north) {(0, 4)};
\node [above=8pt,fill=white] at (tripletoprow.north) {(3, 7, 9)};

\end{tikzpicture}
\changefontsizes{12pt}
\end{document}

enter image description here

8
  • Hi Gonzalo. Thanks for the answer. It will take me some time to digest. For (1), what did you need to change? Is this not a bug then? An explanation would be appreciated, so I can avoid the issue another time. I meant the arrows to go the other way. The solution for (4) looks good. Can you point me to a reference in the manual for the \foreach \i [count=\x] syntax used for (6) (the loop)? Commented Nov 8, 2012 at 19:52
  • @FaheemMitha You're welcome! For (1), you had none as a color to fill the empty parts; however, none is not a color, so you can use white instead. You can easily change the direction of the arrows (if not, please let me know exactly which arrows should be changed and I'll explain how to do it). Commented Nov 8, 2012 at 19:56
  • I think your numbering is a bit off, which confused me. I think (1) and (2) should just be (1) (bleeding issue). Also (3) should be (2) (arrow issue). Are you saying the none caused the problem with the bleeding? Also, curious how you fixed (3) (the alignment issue). Thanks for the impressive help. Let me review and maybe I'll be back with more questions. Commented Nov 8, 2012 at 20:02
  • @FaheemMitha Yes, none solved the bleeding and alignment issues. Commented Nov 8, 2012 at 20:06
  • Oh, maybe you meant to write (1) and (3) and then (2) on the next line? Commented Nov 8, 2012 at 20:08
18

Not sure if this addresses any of your specific questions, as there are many disjoint ones in the posting. It would be better to split them into separate questions so that they might be of more help to others, and also easier to answer. So this is more of a how I would recommend you do this kind of diagram.

Fist thing to figure out is not the diagram itself, but rather

What is the actual information that you want to specify to obtain the desired result?

1. Capture the Data:

Since I am not knowledgeable in DNA sequencing, there may well be a better way that more accurately reflects what you want, but the way I see it is that in each row you have three sets of DNA sequences. In a chat discussion you mentioned that there was not an easy algorithm to automatically determine the color to use, so the natural syntax I see is something such as:

\ThreeDNASequences
    {C/cyan,, A/orange,,,G/blue,,G/red!25,,C/yellow}
    {C/violet,G/brown}
    {A/cyan,G/yellow,C/brown};

where each of the three parameters represent the left, middle, and right sequence along with the color. Multiple subsequent commas are used to denote an empty cell. So you would need one of these calls for each row of your diagram. So with three instances you get three rows:

enter image description here

2. Draw the Arrows:

The other portion of the problem is how to draw the arrows between the various nodes. Using a process similar to the \tikzmark we simply name each of the nodes using a counter to provide a unique reference to each column, and provide an optional parameter to the \ThreeDNASequences macro so that we can have a prefix to distinguish between the rows.

So using \ThreeDNASequences[Top]{}{}{} for the top row, and \ThreeDNASequences[Bottom]{}{}{} for the bottom row can be used to label the nodes as Top-0, Top-1, ..., and Bottom-0, Bottom-1, ... with which we can access each of those nodes. Since this also has a pattern where one node connects to many nodes, it makes sense to define a macro such as:

\ConnectNodes[red, out=100, in=80]
    {Top-12.north}
    {Top-2.north,Top-7.north,Top-9.north};

to specify the options of the lines, and the nodes to connect.

Putting these together you have:

enter image description here

Further Enhancements:

  • Since it is now possible to access each of the nodes, these nodes can be used to place the text that goes adjacent (below, right, or top) of each of these nodes. Note that in the MWE below I did not provide a unique label to use for the middle rows as I was not concerned about the text that needs to be placed. So when placing the text it would be recommended that you also provide unique prefix for each row's node labels.
  • One may need to tweak the arrows via shorten syntax if desired.
  • The xshift used in \ThreeDNASequences should really be computed based on the number of members of the previous sequence. This is really only important if the numbers of each of the columns might change in a different diagram. I used \pgfmathsetmacro{\Shift}{} only to provide a place holder as to where this change may be needed.

Code:

\documentclass[border=3pt]{article}
\usepackage{tikz}
\usepackage{xstring}
\usetikzlibrary{calc, arrows}

\newcommand*{\NodeSize}{0.5cm}%
\newcommand*{\YShiftBetweenRows}{-1cm}% Subsequent rows are shited down so they don't overlap
\tikzset{DNA Style/.style={minimum size=0.5cm, draw=gray, line width=1pt}}{}

\newlength{\YShift}% 
\newcounter{ColumnCounter}% Prefix for node labels

% Initialize - These are probably not needed, but prefer to set them
\setlength{\YShift}{0cm}% 
\setcounter{ColumnCounter}{0}


\newcommand*{\DNASequence}[2][Mark]{%
    % http://tex.stackexchange.com/questions/12091/tikz-foreach-loop-with-macro-defined-list
    \def\Sequence{#2}
    \foreach [count=\xi] \Label/\Color in \Sequence {%
        \pgfmathsetmacro{\XShift}{\NodeSize*\xi}%
        \IfStrEq{\Color}{}{\def\Color{white}}{}
        \edef\NodeName{#1-\arabic{ColumnCounter}}
        \node [DNA Style, fill=\Color, xshift=\XShift] (\NodeName) {\Label};
        \stepcounter{ColumnCounter}
    } 
}%


\newcommand*{\ThreeDNASequences}[4][Mark]{% #1 = tikzmark prefix
    \setcounter{ColumnCounter}{0}% reset column counter
    \begin{scope}[yshift=\YShift]
        \DNASequence[#1]{#2} 
        \pgfmathsetmacro{\Shift}{6cm}% Should compute this based on num of items in #1
        \begin{scope}[xshift=\Shift]
            \DNASequence[#1]{#3} 
        \end{scope}
        \pgfmathsetmacro{\Shift}{8cm}% Should compute this based on num of items in #2  
        \begin{scope}[xshift=\Shift]
            \DNASequence[#1]{#4} 
        \end{scope}
    \end{scope}
    \pgfmathsetlength{\YShift}{\YShift\YShiftBetweenRows}%
}

\newcommand*{\ConnectNodes}[3][]{%
    % #1 = draw options
    % #2 = ending node
    % #3 = list of starting nodes
    \def\ListOfEndNodes{#3}
    \foreach \EndNode in \ListOfEndNodes {%
    \draw[latex'-, thick, #1] (#2) to[#1] (\EndNode);
    }%
}


\begin{document}
\begin{tikzpicture}
    \ThreeDNASequences[Top]
        {C/blue!20,, A/cyan!30,,, G/blue!20,, G/cyan!30,, C/cyan!30}
        {C/blue!20, G/blue!20}
        {A/cyan!30, G/cyan!30, C/cyan!30};

    \ThreeDNASequences
        {A/green!20,, C/orange!50,,, C/green!20,, A/orange!50,, A/orange!50}
        {A/green!20, C/green!20}
        {C/orange!50, A/orange!50, A/orange!50};

    \ThreeDNASequences[Bottom]
        {C/blue!20,, A/cyan!30,,, G/blue!20,, G/cyan!30,, C/cyan!30}
        {C/blue!20, G/blue!20}
        {A/cyan!30, G/cyan!30, C/cyan!30};    

    % Now, draw the arrows as desired

\ConnectNodes[out=90, in=90]
        {Top-10.north east}
        {Top-0.north,Top-5.north};

    \ConnectNodes[out=-90, in=-90]
        {Bottom-13.south}
        {Bottom-2.south,Bottom-7.south,Bottom-9.south};  

\end{tikzpicture}
\end{document}

I looked at the image a bit more and perhaps this is a slightly different way to show the merging of the cells:

enter image description here

It looks better with just one side showing, but the MWE below has the code (commented though) for the top as well:

Code:

\documentclass[border=3pt]{article}
\usepackage{tikz}
\usepackage{xstring}
\usetikzlibrary{calc,fit,backgrounds}

\pgfdeclarelayer{background layer} 
\pgfdeclarelayer{foreground layer} 
\pgfsetlayers{background layer,main,foreground layer}

\newcommand*{\NodeSize}{0.5cm}%
\newcommand*{\YShiftBetweenRows}{-1cm}% Subsequent rows are shited down so they don't overlap
\tikzset{DNA Style/.style={minimum size=0.5cm, draw=gray, line width=1pt}}

\tikzset{Fit Line Style 1/.style={draw=olive, thick, dotted}}
\tikzset{Fill Style 1/.style={fill=olive!20}}

\tikzset{Fit Line Style 2/.style={draw=green!50!black, thick, dashed}}
\tikzset{Fill Style 2/.style={fill=green!20}}

\newlength{\YShift}% 
\newcounter{ColumnCounter}% Prefix for node labels

% Initialize - These are probably not needed, but prefer to set them
\setlength{\YShift}{0cm}% 
\setcounter{ColumnCounter}{0}


\newcommand*{\DNASequence}[2][Mark]{%
    % http://tex.stackexchange.com/questions/12091/tikz-foreach-loop-with-macro-defined-list
    \def\Sequence{#2}
    \foreach [count=\xi] \Label/\Color in \Sequence {%
        \pgfmathsetmacro{\XShift}{\NodeSize*\xi}%
        \IfStrEq{\Color}{}{\def\Color{white}}{}
        \edef\NodeName{#1-\arabic{ColumnCounter}}
        \begin{pgfonlayer}{foreground layer}
        \node [DNA Style, fill=\Color, xshift=\XShift] (\NodeName) {\Label};
        \end{pgfonlayer}
        \stepcounter{ColumnCounter}
    } 
}%


\newcommand*{\ThreeDNASequences}[4][Mark]{% #1 = tikzmark prefix
    \setcounter{ColumnCounter}{0}% reset column counter
    \begin{scope}[yshift=\YShift]
        \DNASequence[#1]{#2} 
        \pgfmathsetmacro{\Shift}{6cm}% Should compute this based on num of items in #1
        \begin{scope}[xshift=\Shift]
            \DNASequence[#1]{#3} 
        \end{scope}
        \pgfmathsetmacro{\Shift}{8cm}% Should compute this based on num of items in #2  
        \begin{scope}[xshift=\Shift]
            \DNASequence[#1]{#4} 
        \end{scope}
    \end{scope}
    \pgfmathsetlength{\YShift}{\YShift\YShiftBetweenRows}%
}

\newcommand*{\ConnectNodes}[3][]{%
    % #1 = draw options
    % #2 = ending node
    % #3 = list of starting nodes
    \def\ListOfEndNodes{#3}
    \foreach \EndNode in \ListOfEndNodes {%
    \draw[red, <->, thick, #1] (#2) to[#1] (\EndNode);
    }%
}

\newcommand*{\Fit}[3][]{\node [inner sep=2pt, #1, fit= #3] (#2) {};}%

\begin{document}
\begin{tikzpicture}

    \ThreeDNASequences[Top]
        {C/blue!20,, A/cyan!30,,, G/blue!20,, G/cyan!30,, C/cyan!30}
        {C/blue!20, G/blue!20}
        {A/cyan!30, G/cyan!30, C/cyan!30};

    \ThreeDNASequences
        {A/green!20,, C/orange!50,,, C/green!20,, A/orange!50,, A/orange!50}
        {A/green!20, C/green!20}
        {C/orange!50, A/orange!50, A/orange!50};

    \ThreeDNASequences[Bottom]
        {C/blue!20,, A/cyan!30,,, G/blue!20,, G/cyan!30,, C/cyan!30}
        {C/blue!20, G/blue!20}
        {A/cyan!30, G/cyan!30, C/cyan!30};

%    % Now, draw the arrows as desired
%
%   \ConnectNodes[red, out=100, in=80, ]
%       {Top-12.north}
%       {Top-2.north,Top-7.north,Top-9.north};
%
%   \ConnectNodes[blue, out=-80, in=-100]
%       {Bottom-10.south east}
%       {Bottom-2.south,Bottom-7.south,Bottom-9.south};


   % Bottom connections
    \Fit[Fit Line Style 1, Fill Style 1]{LeftB1}{(Top-0.north west) (Bottom-0.south east)}
    \Fit[Fit Line Style 1, Fill Style 1]{LeftB2}{(Top-5.north west) (Bottom-5.south east)}
    \Fit[Fit Line Style 1, Fill Style 1]{RightB1}{(Top-10.north west) (Bottom-11.south east)}


    \ConnectNodes[Fit Line Style 1, solid, <-, out=-120, in=-20]
        {RightB1.south}
        {LeftB1.south, LeftB2.south};

%   % Top connections
%   \Fit[Fit Line Style 2, Fill Style 2]{LeftT1}{(Top-2.north west) (Bottom-2.south east)}
%   \Fit[Fit Line Style 2, Fill Style 2]{LeftT2}{(Top-7.north west) (Bottom-7.south east)}
%   \Fit[Fit Line Style 2, Fill Style 2]{LeftT3}{(Top-9.north west) (Bottom-9.south east)}
%   \Fit[Fit Line Style 2, Fill Style 2]{RightT1}{(Top-12.north west) (Bottom-14.south east)}
%
%
%   \ConnectNodes[Fit Line Style 2, solid, out=100, in=80, <-]
%       {RightT1.north}
%       {LeftT1.north, LeftT2.north, LeftT3.north};
\end{tikzpicture}
\end{document}

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .