133

I need to draw a tree, and constantly using dotty and including the PNGs is starting to be a pain. Is there a way to get LaTeX to draw it's own trees that doesn't involve learning an entirely new language like TikZ?

1
  • 18
    Tikz isn't really an entirely new language. I'd recommend it for you. Nov 16, 2010 at 1:23

3 Answers 3

162

While I'd normally second Will Robertson's comment, since TikZ is fantastic and worth learning, I think TikZ's overkill for this situation. I personally find its tree specification syntax bulkier than necessary. My preferred tool for the job is the qtree package (which is on CTAN, too, and is apparently included in both TeX Live and MikTeX). The package is really simple to use. Consider the following TeX:

\Tree[.IP [.NP [.Det \textit{the} ]
               [.N\1 [.N \textit{package} ]]]
          [.I\1 [.I \textsc{3sg.Pres} ]
                [.VP [.V\1 [.V \textit{is} ]
                           [.AP [.Deg \textit{really} ]
                                [.A\1 [.A \textit{simple} ]
                                      \qroof{\textit{to use}}.CP ]]]]]]

This produces the following tree:

Sample X-bar theory parse tree.

That's all it takes! And what's great about it is that the TeX description reads like the tree. I can glance at the TeX, and I instantly know what the created tree is going to look like. The basic syntax is simply [.node-name subtrees... ]; \qroof, which draws the triangle, requires its node name at the end, instead. The \1 is just a shortcut for a math-mode prime. In addition, qtree will always render _ and ^ as sub- and super-scripts, too. (Unless you turn this off.)

In general, you can provide node names at the beginning ([.+ 1 [.* 2 3 ]]) or the end ([ 1 [ 2 3 ].* ].+); you can even provide node names in both places, but then they must match (unsurprisingly). This, incidentally, is why \qroof takes its node name the way it does. You can even leave the node name off entirely to get a node with a smooth join. If any of this is unclear, check out the manual.

Now, qtree as-is has one downside, which is that it is designed for simple trees. It does offer limited support for changing inter-node spacing, framing parts of trees, and things like that, but it's not capable of doing anything incredibly fancy. But luckily, if you want that, you can still get it: enter tikz-qtree. This package allows you to leverage the full power of TikZ to draw your trees. The two obvious features are: (a) instead of text, the labels in a tree can be arbitrary \nodes; and (b) you can redefine how it draws the edges to get arrows, dashed lines, curving edges, and so on. But it's more powerful than just this: if you embed a \Tree into a TikZ picture, you can do whatever you want with the nodes, such as circle them, draw arrows between them for a transformation, etc.

Maybe you don't need this power now, but the take-home message is that using qtree won't lock you in to the simple trees. If you decide that you want the more powerful trees, all you need to do is change one import; everything will keep working the way it did, but you get more power, too. I'm not sure if tikz-qtree this actually uses qtree under the hood or not, but either way, all the syntax for qtree still works, and the output is identical, at least as far as I can tell.


(PS: Linguists, please excuse/correct any errors in the above tree; it's been a year or two since my syntax course.)

11
  • 4
    Great answer! I wasn't aware of this package and the facility to later move to tikz if necessary makes this perfect for the OP. Nov 16, 2010 at 2:27
  • 2
    What are the periods for after the brackets? Nov 17, 2010 at 3:15
  • 5
    tikz-qtree doesn't use qtree underlyingly; it's a completely new implementation. The syntax of the input is the same, however. There is also a compatibility package tikz-qtree-compat which makes converting from older qtree source into tikz-qtree a bit easier.
    – Alan Munn
    Jan 2, 2011 at 21:12
  • 2
    @ClintEastwood: tikz-qtree supports it, but plain qtree does not. The options are standard for TikZ: specify grow=left or grow=right (or use grow') as an argument to the tikzpicture environment your \Tree is in. For more, see the tikz-qtree manual or the tikz manual. Jul 6, 2015 at 3:35
  • 8
    Something that took me a minute to figure out is that there must be a space between the last node and the closing bracket. Aug 5, 2018 at 22:27
81

I am going to put in a plea on behalf of forest. Although forest is extremely flexible and powerful, it can also be used very simply. Like qtree, it uses a simple, concise syntax which 'reads like a tree' but I found forest's syntax a bit easier to learn. (However, this may be because I learnt qtree first.) Like tikz-qtree, it gives you all the power of TikZ but, unlike qtree, you do not have to change packages in order to use that power as forest is already using TikZ underneath. Moreover, in addition to all the power of TikZ, you have all the power of forest itself. And that is very significant: powerful, specialised support for drawing trees of all kinds, manually, automatically and/or dynamically. Take a look at examples on this site for a sense of the possibilities.

For simple trees, however, forest is very simple.

This answer consists of two parts. The first part applies to the current version of forest (version 2). The second, which consists of my original answer, applies to the earlier version of forest (version 1). The changes are not great but, if you are new to the package, you will find it easier to follow if you read the section which applies to the version you are using without modifications.


Current forest: version 2


Here is a forest version of the code for the tree posted in Antal S-Z's answer.

\documentclass[tikz,border=10pt]{standalone}
\usepackage[linguistics]{forest}
\begin{document}
\begin{forest}
  [IP
    [NP
     [Det
       [\textit{the}]
     ]
     [N$'$
       [N
         [\textit{package}]
       ]
     ]
    ]
    [I$'$
      [I
        [\textsc{3sg.Pres}
        ]
      ]
      [VP
        [V$'$
          [V
            [\textit{is}]
          ]
          [AP
            [Deg
              [\textit{extremely}]
            ]
            [A$'$
              [A
                [\textit{straightforward}]
              ]
              [CP
                [\textit{to wield}, roof]
              ]
            ]
          ]
        ]
      ]
    ]
  ]
\end{forest}
\end{document}

The basic idea is that every node in the tree is enclosed in square brackets. The node's subtree is included in the same brackets, if it has one.

Note that there are no dots for branch points and that there is no need to leave a space before a closing square bracket. In fact, the above code is equivalent to

\begin{forest}
  [IP[NP[Det[\textit{the}]][N$'$[N[\textit{package}]]]][I$'$[I[\textsc{3sg.Pres}]][VP[V$'$[V[\textit{is}]][AP[Deg[\textit{extremely}]][A$'$[A[\textit{straightforward}]][CP[\textit{to wield}, roof]]]]]]]]
\end{forest}

Obviously, this is anything but easy to read - hence my preference for lots of 'unnecessary' space.

forest cannot, however, abide a blank line and these must be avoided.

The above trees produce the following output:

tree

How to turn a tree into the bracket specification forest uses

Start with the root and put it inside a forest environment and inside square brackets:

\begin{forest}
  [IP% root
% rest of tree will go here
  ]
\end{forest}

The rest of the tree consists of one or more smaller trees. These are subtrees of the root node. In this case, we have 2 subtrees so we start with the root of each subtree and add each of them in its own pair of square brackets.

\begin{forest}
  [IP% root
    [NP% root of subtree
% rest of subtree will go here
    ]
    [I$'$% root of subtree
% rest of subtree will go here
    ]
  ]
\end{forest}

Then you can work on each of the subtrees in turn and repeat the operation.

Special styles

Because we are interested in this question in trees for linguistics, I added the option linguistics when loading the package.

\usepackage[linguistics]{forest}

This does two things: (1) loads the linguistics library, making various styles of use in linguistics available (e.g. the roof used above); (2) changes the default appearance of trees.

If we only wanted some trees to use the library's defaults (perhaps some of our trees are linguistics trees and some are some other kind of tree), we could instead use

\usepackage{forest}
\useforestlibrary{linguistics} 

in the preamble. Then we could use

\forestapplylibrarydefaults{linguistics}

within a local TeX scope in the body of the document to apply the defaults only to selected trees. For example,

{\forestapplylibrarydefaults{linguistics}
\begin{forest}
  <specification 1>
\end{forest}}

\begin{forest}
  <specification 2>
\end{forest}

would apply lingustics defaults to the tree given by <specification 1> but not to that given by <specification 2>.

But we'll assume that all the trees in our current document are linguistics trees for now.

To make the triangular roof, we just add , roof to the appropriate node and forest applies its triangular roof style.

If you later want to make more complex trees, you can also use TikZ styles in just the same way. Adding , text=red to a node will turn the text of the node red, for example.

     [N$'$, text=red
       [N
         [\textit{package}]
       ]
     ]

red node

Conditional styling saves typing

You can also, if you wish, save changing the font for every terminal node. If most of the terminal nodes should be italicised, you can say

if n children=0{% if the node doesn't have any children of its own
  font=\itshape
}{},

To apply this conditional to the whole tree and, hence, italics to all terminal nodes, we can say

  for tree={
    if n children=0{
      font=\itshape
    }{},
  }

after \begin{forest} and before specifying the tree itself. This is known as the preamble of the tree.

You can then override this for the single small-caps node, by saying , font=\scshape after specifying the node's contents.

Complete code for revised tree

\documentclass[tikz,border=10pt]{standalone}
\usepackage[linguistics]{forest}
\begin{document}
\begin{forest}
  for tree={
    if n children=0{
      font=\itshape
    }{},
  }
  [IP
    [NP
     [Det
       [the]
     ]
     [N$'$
       [N
         [package]
       ]
     ]
    ]
    [I$'$
      [I
        [3sg.Pres, font=\scshape]
      ]
      [VP
        [V$'$
          [V
            [is]
          ]
          [AP
            [Deg
              [extremely]
            ]
            [A$'$
              [A
                [straightforward]
              ]
              [CP
                [to wield, roof]
              ]
            ]
          ]
        ]
      ]
    ]
  ]
\end{forest}
\end{document}

Selected additional features

One common feature requested for linguists' trees seems to be to ensure that the terminal nodes are aligned.

forest allows you to specify that nodes should be aligned on a common tier. To use this feature, you just write , tier=<name of tier> after the content of the node is specified.

Here's an extreme example:

extreme tier alignment

\begin{forest}
  for tree={
    fit=band,% spaces the tree out a little to avoid collisions
  }
  [things
    [cabbages, tier=vegetables
      [peaches, tier=fruits]
    ]
    [kings, tier=aristocrats]
    [sealing wax
      [queens, tier=aristocrats
        [carrots, tier=vegetables]
        [pineapple, tier=fruits]
        [aubergine, tier=vegetables]
      ]
    ]
  ]
\end{forest}

In the case of our linguists' tree, we just want the terminal nodes aligned. We are already saying we want them in italics, so we can just add a tier specification there.

We did have

  for tree={
    if n children=0{
      font=\itshape
    }{},
  }

Now we change this to the following:

  for tree={
    if n children=0{
      font=\itshape,
      tier=terminal,
    }{},
  }

and the tree changes quite dramatically:

aligned terminal nodes


Earlier forest: version 1


Here is a forest version of the code for the tree posted in Antal S-Z's answer.

\documentclass[tikz,border=10pt]{standalone}
\usepackage{forest}
\begin{document}
\begin{forest}
  [IP
    [NP
     [Det
       [\textit{the}]
     ]
     [N$'$
       [N
         [\textit{package}]
       ]
     ]
    ]
    [I$'$
      [I
        [\textsc{3sg.Pres}
        ]
      ]
      [VP
        [V$'$
          [V
            [\textit{is}]
          ]
          [AP
            [Deg
              [\textit{extremely}]
            ]
            [A$'$
              [A
                [\textit{straightforward}]
              ]
              [CP
                [\textit{to wield}, triangle]
              ]
            ]
          ]
        ]
      ]
    ]
  ]
\end{forest}
\end{document}

The basic idea is that every node in the tree is enclosed in square brackets. The node's subtree is included in the same brackets, if it has one.

Note that there are no dots for branch points and that there is no need to leave a space before a closing square bracket. In fact, the above code is equivalent to

\begin{forest}
  [IP[NP[Det[\textit{the}]][N$'$[N[\textit{package}]]]][I$'$[I[\textsc{3sg.Pres}]][VP[V$'$[V[\textit{is}]][AP[Deg[\textit{extremely}]][A$'$[A[\textit{straightforward}]][CP[\textit{to wield}, triangle]]]]]]]]
\end{forest}

Obviously, this is anything but easy to read - hence my preference for lots of 'unnecessary' space.

forest cannot, however, abide a blank line and these must be avoided.

The above trees produce the following output:

tree

How to turn a tree into the bracket specification forest uses

Start with the root and put it inside a forest environment and inside square brackets:

\begin{forest}
  [IP% root
% rest of tree will go here
  ]
\end{forest}

The rest of the tree consists of one or more smaller trees. These are subtrees of the root node. In this case, we have 2 subtrees so we start with the root of each subtree and add each of them in its own pair of square brackets.

\begin{forest}
  [IP% root
    [NP% root of subtree
% rest of subtree will go here
    ]
    [I$'$% root of subtree
% rest of subtree will go here
    ]
  ]
\end{forest}

Then you can work on each of the subtrees in turn and repeat the operation.

Special styles

To make the triangular roof, we just add , triangle to the appropriate node and forest applies its triangular root style.

If you later want to make more complex trees, you can also use TikZ styles in just the same way. Adding , text=red to a node will turn the text of the node red, for example.

     [N$'$, text=red
       [N
         [\textit{package}]
       ]
     ]

red node

Branches for logicians and linguists

Even simple logicians' and linguists' trees probably need a little styling in order to look right. In particular, trees typically have branches which start from a common point beneath the parent node and extend to a point above the child. Although this is not default, we can implement it by saying

parent anchor=south,% start branches beneath the parent
child anchor=north,% end branches above the child

To apply this to the whole tree, we can say

\begin{forest}
  for tree={
    parent anchor=south,
    child anchor=north,
  }
  [IP
    ...
  ]
\end{forest}

branches for logicians and linguists

Conditional styling saves typing

You can also, if you wish, save changing the font for every terminal node. If most of the terminal nodes should be italicised, you can say

if n children=0{% if the node doesn't have any children of its own
  font=\itshape
}{},

You can then override this for the single small-caps node, by saying , font=\scshape after specifying the node's contents.

Complete code for revised tree

\documentclass[tikz,border=10pt,multi]{standalone}
\usepackage{forest}
\begin{document}
\begin{forest}
  for tree={
    parent anchor=south,
    child anchor=north,
    if n children=0{
      font=\itshape
    }{},
  }
  [IP
    [NP
     [Det
       [the]
     ]
     [N$'$
       [N
         [package]
       ]
     ]
    ]
    [I$'$
      [I
        [3sg.Pres, font=\scshape]
      ]
      [VP
        [V$'$
          [V
            [is]
          ]
          [AP
            [Deg
              [extremely]
            ]
            [A$'$
              [A
                [straightforward]
              ]
              [CP
                [to wield, triangle]
              ]
            ]
          ]
        ]
      ]
    ]
  ]
\end{forest}
\end{document}

Selected additional features

One common feature requested for linguists' trees seems to be to ensure that the terminal nodes are aligned.

forest allows you to specify that nodes should be aligned on a common tier. To use this feature, you just write , tier=<name of tier> after the content of the node is specified.

Here's an extreme example:

extreme tier alignment

\begin{forest}
  for tree={
    parent anchor=south,
    child anchor=north,
    fit=band,% spaces the tree out a little to avoid collisions
  }
  [things
    [cabbages, tier=vegetables
      [peaches, tier=fruits]
    ]
    [kings, tier=aristocrats]
    [sealing wax
      [queens, tier=aristocrats
        [carrots, tier=vegetables]
        [pineapple, tier=fruits]
        [aubergine, tier=vegetables]
      ]
    ]
  ]
\end{forest}

In the case of our linguists' tree, we just want the terminal nodes aligned. We are already saying we want them in italics, so we can just add a tier specification there.

We did have

  for tree={
    parent anchor=south,
    child anchor=north,
    if n children=0{
      font=\itshape
    }{},
  }

Now we change this to the following:

  for tree={
    parent anchor=south,
    child anchor=north,
    if n children=0{
      font=\itshape,
      tier=terminal,
    }{},
  }

and the tree changes quite dramatically:

aligned terminal nodes

6
  • 3
    this answer should be part of forest documentation. nice and clear!
    – Zarko
    Dec 9, 2017 at 15:02
  • @Zarko Thank you! There is a quick start guide to Forest already. I don't know what it is like to use, though.
    – cfr
    Dec 9, 2017 at 16:35
  • where i can find it?
    – Zarko
    Dec 9, 2017 at 16:37
  • @Zarko It is on CTAN and in TeX Live. Probably in MikTeX, too. Just search CTAN for forest, for example.
    – cfr
    Dec 9, 2017 at 16:54
  • thank you for info. it is not a part of MikTeX, however i found it on CTAN.
    – Zarko
    Dec 9, 2017 at 17:55
44

For simple, non "graphical" tree you can use the dirtree package:

\documentclass{article}
\usepackage{dirtree}
\begin{document}

\dirtree{%
.1 debug.
.2 filename.
.2 modules.
.3 module.
.3 module.
.3 module.
.2 level.
}

\end{document}

dirtree

3
  • 2
    Thank you for posting this answer. The output is perfect indeed.
    – enthu
    Jul 4, 2015 at 7:04
  • As a student of linguistics, I find this too damn good
    – axolotl
    Oct 9, 2017 at 0:44
  • @Aalok, interesting, can you give an example? feel free to edit the answer.
    – alfC
    Dec 20, 2017 at 3:30

You must log in to answer this question.

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