diff --git a/docs/quadripartitions.ipynb b/docs/quadripartitions.ipynb
new file mode 100644
index 00000000..e972f619
--- /dev/null
+++ b/docs/quadripartitions.ipynb
@@ -0,0 +1,249 @@
+{
+ "cells": [
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "# Quadripartition methods \n",
+ "\n",
+ "\n",
+ "The `iter_quadripartitions()` function in the `.enum` subpackage returns all possible quadripartitions of a tree. Quadripartitions are defined by an internal `focal edge`, from which the tree is split into four partitions. Each partition stems from the children of the 2 nodes on either side of the `focal edge`. The quadripartitions are yielded in Node idxorder traversal in a nested format: a tuple of two tuples of two sets, e.g. `(({e0},{e1}), ({e2},{e3}))`, with the contents representing the tip Nodes descending from each of the four partition stems. In this example, `e0` through `e3` are the partition stems and are each children of the nodes being split along the `focal edge`. The order in which the partitions of a particular quadripartition are ordered is (child-left, child-right, sister, up) in relation to the Node directly below the `focal edge`.\n",
+ "\n",
+ "Note: Sets are used by default, which means when there are multiple nodes in a partition, they will not be sorted. This can be modified by using an ordered datatype like `type=tuple` or `type=list`. This will sort the nodes in alphabetical or index order (depending on whether `feature=\"name\"` or `feature=\"idx\"`.)\n",
+ "\n",
+ "### Simple example\n"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 24,
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "(({'a'}, {'b'}), ({'d', 'c'}, {'e'}))\n",
+ "(({'c'}, {'d'}), ({'e'}, {'b', 'a'}))\n"
+ ]
+ },
+ {
+ "data": {
+ "text/html": [
+ "
"
+ ]
+ },
+ "metadata": {},
+ "output_type": "display_data"
+ }
+ ],
+ "source": [
+ "import toytree \n",
+ "\n",
+ "#define tree with simple Newick string\n",
+ "newick = \"((a,b)X,((c,d)Y,e)Z)R;\" \n",
+ "tree = toytree.tree(newick) \n",
+ "\n",
+ "tree.draw('r'); #draw tree in R-style\n",
+ "\n",
+ "#iteratively return all quadripartitions in phylogenetic tree\n",
+ "for q in toytree.enum.iter_quadripartitions(tree):\n",
+ " print(q)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "In this example, the only internal edges available to make quadripartitions from are the edges directly above `Y` and `Z` (or `X`, but it has the same result as `Z`). These two quadripartitions are given in tuples of tuples of sets to denotate the first (tuple) and second (sets) bipartitions that create the quadripartition."
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "### Sorting and formatting \n",
+ "\n",
+ "\n",
+ "When `type=` is set to an ordered datatype (i.e. tuple, list), `iter_quadripartitions` will automatically sort the values within each partition. The user can choose to sort the quadripartition further, ordering each partition within its bipartitions and each bipartition within its quadripartition, by using `sort=True`. This first orders them in size order (small to large), and if the sizes are equal, then by the lowest value Node present."
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 25,
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "[(((2,), (3,)), ((4, 5, 7), (0, 1))), (((4,), (5,)), ((2, 3, 6), (0, 1))), (((2, 3, 6), (4, 5, 7)), ((0,), (1,)))]\n",
+ "[(((2,), (3,)), ((0, 1), (4, 5, 7))), (((4,), (5,)), ((0, 1), (2, 3, 6))), (((0,), (1,)), ((2, 3, 6), (4, 5, 7)))]\n"
+ ]
+ },
+ {
+ "data": {
+ "text/html": [
+ "
"
+ ]
+ },
+ "metadata": {},
+ "output_type": "display_data"
+ }
+ ],
+ "source": [
+ "#build tree from simple newick string and visualize it\n",
+ "tree = toytree.tree(\"(a,b,((c,d)CD,(e,f)EF)X)AB;\") \n",
+ "tree.draw()\n",
+ "\n",
+ "#return quadripartitions as list, with each partition returned in a tuple (instead of a set), including the internal nodes of each partition\n",
+ "unordered = list(tree.enum.iter_quadripartitions(type=tuple, \n",
+ " include_internal_nodes=True, \n",
+ " feature=\"idx\"))\n",
+ "ordered = list(tree.enum.iter_quadripartitions(type=tuple, \n",
+ " include_internal_nodes=True, \n",
+ " feature=\"idx\", \n",
+ " sort=True))\n",
+ "print(unordered)\n",
+ "print(ordered)"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "The user can also choose to return more or less information about each quadripartition, ranging from all tips and internal nodes using `include_internal_nodes=True`, to only the stems of each partition (`contract_partitions=True`). To specify what information is returned, use the `feature=` argument with any available Node feature. \n",
+ "\n",
+ "### Example \n",
+ "\n",
+ "#### Lots of information"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 26,
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "(({'alfred'}, {'bob'}), ({'david', 'Yasmin', 'cindy'}, {'ellis'}))\n",
+ "(({'cindy'}, {'david'}), ({'ellis'}, {'bob', 'Xiang', 'alfred'}))\n"
+ ]
+ },
+ {
+ "data": {
+ "text/html": [
+ "