diff --git a/examples/plot_tasks.py b/examples/plot_tasks.py
index 1be59d1c8449970321b8ef9053ddf24b4559dabd..75ac2db65cac748606c143b3c691a167b314a926 100755
--- a/examples/plot_tasks.py
+++ b/examples/plot_tasks.py
@@ -1,18 +1,20 @@
 #!/usr/bin/env python
 """
 Usage:
-    plot_tasks.py input.dat output.png [time-range-ms]
+    plot_tasks.py [options] input.dat output.png
 
-where input.dat is a thread info file for a step.  Use the '-y interval'
-flag of the swift MPI commands to create these. The output plot will be
-called 'output.png'. Use the time-range-ms in millisecs to produce
-plots with the same time span.
+where input.dat is a thread info file for a step.  Use the '-y interval' flag
+of the swift command to create these. The output plot will be called
+'output.png'. The --limit option can be used to produce plots with the same
+time span and the --expand option to expand each thread line into '*expand'
+lines, so that adjacent tasks of the same type can be distinguished. Other
+options can be seen using the --help flag.
 
 This file is part of SWIFT.
 Copyright (c) 2015 Pedro Gonnet (pedro.gonnet@durham.ac.uk),
                    Bert Vandenbroucke (bert.vandenbroucke@ugent.be)
                    Matthieu Schaller (matthieu.schaller@durham.ac.uk)
-          (c) 2016 Peter W. Draper (p.w.draper@durham.ac.uk)
+          (c) 2017 Peter W. Draper (p.w.draper@durham.ac.uk)
 
 This program is free software: you can redistribute it and/or modify
 it under the terms of the GNU Lesser General Public License as published
@@ -29,11 +31,42 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.
 """
 
 import matplotlib
+matplotlib.use("Agg")
 import matplotlib.collections as collections
-matplotlib.use('Agg')
+import matplotlib.ticker as plticker
 import pylab as pl
-import numpy as np
 import sys
+import argparse
+
+#  Handle the command line.
+parser = argparse.ArgumentParser(description="Plot task graphs")
+
+parser.add_argument("input", help="Thread data file (-y output)")
+parser.add_argument("outpng", help="Name for output graphic file (PNG)")
+parser.add_argument("-l", "--limit", dest="limit",
+                    help="Upper time limit in millisecs (def: depends on data)",
+                    default=0, type=int)
+parser.add_argument("-e", "--expand", dest="expand",
+                    help="Thread expansion factor (def: 1)",
+                    default=1, type=int)
+parser.add_argument("--height", dest="height",
+                    help="Height of plot in inches (def: 4)",
+                    default=4., type=float)
+parser.add_argument("--width", dest="width",
+                    help="Width of plot in inches (def: 16)",
+                    default=16., type=float)
+parser.add_argument("--nolegend", dest="nolegend",
+                    help="Whether to show the legend (def: False)",
+                    default=False, action="store_true")
+parser.add_argument("-v", "--verbose", dest="verbose",
+                    help="Show colour assignments and other details (def: False)",
+                    default=False, action="store_true")
+
+args = parser.parse_args()
+infile = args.input
+outpng = args.outpng
+delta_t = args.limit
+expand = args.expand
 
 #  Basic plot configuration.
 PLOT_PARAMS = {"axes.labelsize": 10,
@@ -42,7 +75,7 @@ PLOT_PARAMS = {"axes.labelsize": 10,
                "legend.fontsize": 12,
                "xtick.labelsize": 10,
                "ytick.labelsize": 10,
-               "figure.figsize" : (16., 4.),
+               "figure.figsize" : (args.width, args.height),
                "figure.subplot.left" : 0.03,
                "figure.subplot.right" : 0.995,
                "figure.subplot.bottom" : 0.1,
@@ -56,9 +89,10 @@ pl.rcParams.update(PLOT_PARAMS)
 
 #  Tasks and subtypes. Indexed as in tasks.h.
 TASKTYPES = ["none", "sort", "self", "pair", "sub_self", "sub_pair",
-             "init", "ghost", "extra_ghost", "drift", "kick1", "kick2",
+             "init_grav", "ghost", "extra_ghost", "drift", "kick1", "kick2",
              "timestep", "send", "recv", "grav_top_level", "grav_long_range",
              "grav_mm", "grav_down", "cooling", "sourceterms", "count"]
+
 SUBTYPES = ["none", "density", "gradient", "force", "grav", "external_grav",
             "tend", "xv", "rho", "gpart", "multipole", "spart", "count"]
 
@@ -69,14 +103,16 @@ FULLTYPES = ["self/force", "self/density", "self/grav", "sub_self/force",
              "sub_pair/density", "recv/xv", "send/xv", "recv/rho", "send/rho",
              "recv/tend", "send/tend"]
 
-#  Get a number of colours for the various types.
-colours = ["black", "gray", "rosybrown", "firebrick", "red", "darksalmon",
-           "sienna", "sandybrown", "bisque", "tan", "moccasin", "gold", "darkkhaki",
-           "lightgoldenrodyellow", "olivedrab", "chartreuse", "darksage", "lightgreen",
-           "green", "mediumseagreen", "mediumaquamarine", "mediumturquoise", "darkslategrey",
-           "cyan", "cadetblue", "skyblue", "dodgerblue", "slategray", "darkblue",
-           "slateblue", "blueviolet", "mediumorchid", "purple", "magenta", "hotpink",
-           "pink"]
+#  A number of colours for the various types. Recycled when there are
+#  more task types than colours...
+
+colours = ["cyan", "lightgray", "darkblue", "yellow", "tan", "dodgerblue",
+           "sienna", "aquamarine", "bisque", "blue", "green", "brown",
+           "purple", "mocassin", "olivedrab", "chartreuse", "darksage",
+           "darkgreen", "green", "mediumseagreen", "mediumaquamarine",
+           "darkslategrey", "mediumturquoise", "black", "cadetblue", "skyblue",
+           "red", "slategray", "gold", "slateblue", "blueviolet",
+           "mediumorchid", "firebrick", "magenta", "hotpink", "pink"]
 maxcolours = len(colours)
 
 #  Set colours of task/subtype.
@@ -87,30 +123,21 @@ for task in TASKTYPES:
     ncolours = (ncolours + 1) % maxcolours
 
 SUBCOLOURS = {}
-for task in SUBTYPES:
+for task in FULLTYPES:
     SUBCOLOURS[task] = colours[ncolours]
     ncolours = (ncolours + 1) % maxcolours
 
-for task in FULLTYPES:
+for task in SUBTYPES:
     SUBCOLOURS[task] = colours[ncolours]
     ncolours = (ncolours + 1) % maxcolours
 
-#  Show docs if help is requested.
-if len( sys.argv ) == 2 and ( sys.argv[1][0:2] == "-h" or sys.argv[1][0:3] == "--h" ):
-    from pydoc import help
-    help( "__main__" )
-    sys.exit( 0 )
-
-#  Handle command-line.
-if len( sys.argv ) != 3 and len( sys.argv ) != 4:
-    print "Usage: ", sys.argv[0], "input.dat output.png [time-range-ms]"
-    sys.exit(1)
-
-infile = sys.argv[1]
-outpng = sys.argv[2]
-delta_t = 0
-if len( sys.argv ) == 4:
-    delta_t = int(sys.argv[3])
+#  For fiddling with colours...
+if args.verbose:
+    print "#Selected colours:"
+    for task in TASKCOLOURS.keys():
+        print "# " + task + ": " + TASKCOLOURS[task]
+    for task in SUBCOLOURS.keys():
+        print "# " + task + ": " + SUBCOLOURS[task]
 
 #  Read input.
 data = pl.loadtxt( infile )
@@ -118,51 +145,61 @@ data = pl.loadtxt( infile )
 nthread = int(max(data[:,0])) + 1
 print "Number of threads:", nthread
 
-# Recover the start and end time
+#  Recover the start and end time
 full_step = data[0,:]
 tic_step = int(full_step[4])
 toc_step = int(full_step[5])
-CPU_CLOCK = float(full_step[-1])
+CPU_CLOCK = float(full_step[-1]) / 1000.0
 data = data[1:,:]
+if args.verbose:
+    print "CPU frequency:", CPU_CLOCK * 1000.0
 
-print "CPU frequency:", CPU_CLOCK
-
-# Avoid start and end times of zero.
+#  Avoid start and end times of zero.
 data = data[data[:,4] != 0]
 data = data[data[:,5] != 0]
 
-# Calculate the time range, if not given.
-delta_t = delta_t * CPU_CLOCK / 1000
+#  Calculate the time range, if not given.
+delta_t = delta_t * CPU_CLOCK
 if delta_t == 0:
     dt = max(data[:,5]) - min(data[:,4])
     if dt > delta_t:
         delta_t = dt
-    print "Data range: ", delta_t / CPU_CLOCK * 1000, "ms"
+    print "Data range: ", delta_t / CPU_CLOCK, "ms"
 
-# Once more doing the real gather and plots this time.
-start_t = tic_step 
+#  Once more doing the real gather and plots this time.
+start_t = float(tic_step)
 data[:,4] -= start_t
 data[:,5] -= start_t
-end_t = (toc_step - start_t) / CPU_CLOCK * 1000
+end_t = (toc_step - start_t) / CPU_CLOCK
 
 tasks = {}
 tasks[-1] = []
-for i in range(nthread):
+for i in range(nthread*expand):
     tasks[i] = []
 
+#  Counters for each thread when expanding.
+ecounter = []
+for i in range(nthread):
+    ecounter.append(0)
+
 num_lines = pl.size(data) / 10
 for line in range(num_lines):
     thread = int(data[line,0])
+
+    # Expand to cover extra lines if expanding.
+    ethread = thread * expand + (ecounter[thread] % expand)
+    ecounter[thread] = ecounter[thread] + 1
+    thread = ethread
+
     tasks[thread].append({})
     tasktype = TASKTYPES[int(data[line,1])]
     subtype = SUBTYPES[int(data[line,2])]
     tasks[thread][-1]["type"] = tasktype
     tasks[thread][-1]["subtype"] = subtype
-    tic = int(data[line,4]) / CPU_CLOCK * 1000
-    toc = int(data[line,5]) / CPU_CLOCK * 1000
+    tic = int(data[line,4]) / CPU_CLOCK
+    toc = int(data[line,5]) / CPU_CLOCK
     tasks[thread][-1]["tic"] = tic
     tasks[thread][-1]["toc"] = toc
-    tasks[thread][-1]["t"] = (toc + tic)/ 2
     if "self" in tasktype or "pair" in tasktype:
         fulltype = tasktype + "/" + subtype
         if fulltype in SUBCOLOURS:
@@ -171,31 +208,24 @@ for line in range(num_lines):
             tasks[thread][-1]["colour"] = SUBCOLOURS[subtype]
     else:
         tasks[thread][-1]["colour"] = TASKCOLOURS[tasktype]
-    
-for thread in range(nthread):
-    tasks[thread] = sorted(tasks[thread], key=lambda l: l["t"])
-            
+
+# Use expanded threads from now on.
+nthread = nthread * expand
+
 typesseen = []
 fig = pl.figure()
 ax = fig.add_subplot(1,1,1)
-ax.set_xlim(-delta_t * 0.03 * 1000 / CPU_CLOCK, delta_t * 1.03 * 1000 / CPU_CLOCK)
+ax.set_xlim(-delta_t * 0.01 / CPU_CLOCK, delta_t * 1.01 / CPU_CLOCK)
 ax.set_ylim(0, nthread)
-tictoc = np.zeros(2)
 for i in range(nthread):
 
     #  Collect ranges and colours into arrays.
-    tictocs = np.zeros(len(tasks[i])*2)
-    colours = np.empty(len(tasks[i])*2, dtype='object')
-    coloursseen = []
+    tictocs = []
+    colours = []
     j = 0
     for task in tasks[i]:
-        tictocs[j] = task["tic"]
-        tictocs[j+1] = task["toc"]
-        colours[j] = task["colour"]
-        colours[j+1] = task["colour"]
-        j = j + 2
-        if task["colour"] not in coloursseen:
-            coloursseen.append(task["colour"])
+        tictocs.append((task["tic"], task["toc"] - task["tic"]))
+        colours.append(task["colour"])
 
         #  Legend support, collections don't add to this.
         if task["subtype"] != "none":
@@ -206,31 +236,33 @@ for i in range(nthread):
             pl.plot([], [], color=task["colour"], label=qtask)
             typesseen.append(qtask)
 
-    #  Now plot each colour, faster to use a mask to select colour ranges.
-    for colour in coloursseen:
-        collection = collections.BrokenBarHCollection.span_where(tictocs, ymin=i+0.05, ymax=i+0.95,
-                                                                 where=colours == colour,
-                                                                 facecolor=colour,
-                                                                 linewidths=0)
-        ax.add_collection(collection)
-
+    #  Now plot.
+    ax.broken_barh(tictocs, [i+0.05,0.90], facecolors = colours, linewidth=0)
 
 #  Legend and room for it.
 nrow = len(typesseen) / 5
-if len(typesseen) * 5 < nrow:
-    nrow = nrow + 1
-ax.fill_between([0, 0], nthread+0.5, nthread + nrow + 0.5, facecolor="white")
-ax.set_ylim(0, nthread + nrow + 1)
-ax.legend(loc=1, shadow=True, mode="expand", ncol=5)
+if not args.nolegend:
+    if len(typesseen) * 5 < nrow:
+        nrow = nrow + 1
+    ax.fill_between([0, 0], nthread+0.5, nthread + nrow + 0.5, facecolor="white")
+    ax.set_ylim(0, nthread + nrow + 1)
+    ax.legend(loc=1, shadow=True, mode="expand", ncol=5)
 
 # Start and end of time-step
 ax.plot([0, 0], [0, nthread + nrow + 1], 'k--', linewidth=1)
 ax.plot([end_t, end_t], [0, nthread + nrow + 1], 'k--', linewidth=1)
 
 ax.set_xlabel("Wall clock time [ms]")
-ax.set_ylabel("Thread ID" )
+if expand == 1:
+    ax.set_ylabel("Thread ID" )
+else:
+    ax.set_ylabel("Thread ID * " + str(expand) )
 ax.set_yticks(pl.array(range(nthread)), True)
 
+loc = plticker.MultipleLocator(base=expand)
+ax.yaxis.set_major_locator(loc)
+ax.grid(True, which='major', axis="y", linestyle="-")
+
 pl.show()
 pl.savefig(outpng)
 print "Graphics done, output written to", outpng
diff --git a/examples/plot_tasks_MPI.py b/examples/plot_tasks_MPI.py
index c95bfa1fd2d087cc907b57201c1a1397cbeb1460..a1f81bb1789c73ebe21391509c7d7674f6e43100 100755
--- a/examples/plot_tasks_MPI.py
+++ b/examples/plot_tasks_MPI.py
@@ -1,13 +1,15 @@
 #!/usr/bin/env python
 """
 Usage:
-    plot_tasks_MPI.py input.dat png-output-prefix [time-range-ms]
+    plot_tasks_MPI.py [options] input.dat png-output-prefix
 
-where input.dat is a thread info file for a step of an MPI run.  Use the '-y
-interval' flag of the swift MPI commands to create these. The output plots
-will be called 'png-output-prefix<mpi-rank>.png', i.e. one each for all the
-threads in each MPI rank. Use the time-range-ms in millisecs to produce
-plots with the same time span.
+where input.dat is a thread info file for a step.  Use the '-y interval' flag
+of the swift MPI command to create these. The output plot will be called
+'png-output-prefix<mpi-rank>.png', i.e. one each for all the threads in each
+MPI rank.  The --limit option can be used to produce plots with the same time
+span and the --expand option to expand each thread line into '*expand' lines,
+so that adjacent tasks of the same type can be distinguished. Other options
+can be seen using the --help flag.
 
 See the command 'process_plot_tasks_MPI' to efficiently wrap this command to
 process a number of thread info files and create an HTML file to view them.
@@ -17,7 +19,7 @@ This file is part of SWIFT.
 Copyright (C) 2015 Pedro Gonnet (pedro.gonnet@durham.ac.uk),
                    Bert Vandenbroucke (bert.vandenbroucke@ugent.be)
                    Matthieu Schaller (matthieu.schaller@durham.ac.uk)
-                   Peter W. Draper (p.w.draper@durham.ac.uk)
+          (C) 2017 Peter W. Draper (p.w.draper@durham.ac.uk)
 All Rights Reserved.
 
 This program is free software: you can redistribute it and/or modify
@@ -35,13 +37,42 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.
 """
 
 import matplotlib
-import matplotlib.collections as collections
 matplotlib.use("Agg")
+import matplotlib.collections as collections
+import matplotlib.ticker as plticker
 import pylab as pl
-import numpy as np
 import sys
-#import warnings
-#warnings.simplefilter("error")
+import argparse
+
+#  Handle the command line.
+parser = argparse.ArgumentParser(description="Plot task graphs")
+
+parser.add_argument("input", help="Thread data file (-y output)")
+parser.add_argument("outbase", help="Base name for output graphic files (PNG)")
+parser.add_argument("-l", "--limit", dest="limit",
+                    help="Upper time limit in millisecs (def: depends on data)",
+                    default=0, type=int)
+parser.add_argument("-e", "--expand", dest="expand",
+                    help="Thread expansion factor (def: 1)",
+                    default=1, type=int)
+parser.add_argument("--height", dest="height",
+                    help="Height of plot in inches (def: 4)",
+                    default=4., type=float)
+parser.add_argument("--width", dest="width",
+                    help="Width of plot in inches (def: 16)",
+                    default=16., type=float)
+parser.add_argument("--nolegend", dest="nolegend",
+                    help="Whether to show the legend (def: False)",
+                    default=False, action="store_true")
+parser.add_argument("-v", "--verbose", dest="verbose",
+                    help="Show colour assignments and other details (def: False)",
+                    default=False, action="store_true")
+
+args = parser.parse_args()
+infile = args.input
+outbase = args.outbase
+delta_t = args.limit
+expand = args.expand
 
 #  Basic plot configuration.
 PLOT_PARAMS = {"axes.labelsize": 10,
@@ -50,7 +81,7 @@ PLOT_PARAMS = {"axes.labelsize": 10,
                "legend.fontsize": 12,
                "xtick.labelsize": 10,
                "ytick.labelsize": 10,
-               "figure.figsize" : (16., 4.),
+               "figure.figsize" : (args.width, args.height),
                "figure.subplot.left" : 0.03,
                "figure.subplot.right" : 0.995,
                "figure.subplot.bottom" : 0.1,
@@ -64,26 +95,31 @@ pl.rcParams.update(PLOT_PARAMS)
 
 #  Tasks and subtypes. Indexed as in tasks.h.
 TASKTYPES = ["none", "sort", "self", "pair", "sub_self", "sub_pair",
-             "init", "ghost", "extra_ghost", "drift", "kick1", "kick2",
-             "timestep", "send", "recv", "grav_gather_m", "grav_fft",
-             "grav_mm", "grav_up", "cooling", "sourceterms", "count"]
+             "init_grav", "ghost", "extra_ghost", "drift", "kick1", "kick2",
+             "timestep", "send", "recv", "grav_top_level", "grav_long_range",
+             "grav_mm", "grav_down", "cooling", "sourceterms", "count"]
+
 SUBTYPES = ["none", "density", "gradient", "force", "grav", "external_grav",
-            "tend", "xv", "rho", "gpart", "count"]
+            "tend", "xv", "rho", "gpart", "multipole", "spart", "count"]
 
 #  Task/subtypes of interest.
-FULLTYPES = ["self/force", "self/density", "sub_self/force",
-             "sub_self/density", "pair/force", "pair/density", "sub_pair/force",
+FULLTYPES = ["self/force", "self/density", "self/grav", "sub_self/force",
+             "sub_self/density", "pair/force", "pair/density", "pair/grav",
+             "sub_pair/force",
              "sub_pair/density", "recv/xv", "send/xv", "recv/rho", "send/rho",
              "recv/tend", "send/tend"]
 
-#  Get a number of colours for the various types.
-colours = ["black", "gray", "rosybrown", "firebrick", "red", "darksalmon",
-           "sienna", "sandybrown", "bisque", "tan", "moccasin", "gold", "darkkhaki",
-           "lightgoldenrodyellow", "olivedrab", "chartreuse", "darksage", "lightgreen",
-           "green", "mediumseagreen", "mediumaquamarine", "mediumturquoise", "darkslategrey",
-           "cyan", "cadetblue", "skyblue", "dodgerblue", "slategray", "darkblue",
-           "slateblue", "blueviolet", "mediumorchid", "purple", "magenta", "hotpink",
-           "pink"]
+#  A number of colours for the various types. Recycled when there are
+#  more task types than colours...
+
+colours = ["cyan", "lightgray", "darkblue", "yellow", "tan", "dodgerblue",
+           "sienna", "aquamarine", "bisque", "blue", "green", "brown",
+           "purple", "mocassin", "olivedrab", "chartreuse", "darksage",
+           "darkgreen", "green", "mediumseagreen", "mediumaquamarine",
+           "darkslategrey", "mediumturquoise", "black", "cadetblue", "skyblue",
+           "red", "slategray", "gold", "slateblue", "blueviolet",
+           "mediumorchid", "firebrick", "magenta", "hotpink", "pink",
+           "orange", "lightgreen"]
 maxcolours = len(colours)
 
 #  Set colours of task/subtype.
@@ -94,43 +130,30 @@ for task in TASKTYPES:
     ncolours = (ncolours + 1) % maxcolours
 
 SUBCOLOURS = {}
-for task in SUBTYPES:
+for task in FULLTYPES:
     SUBCOLOURS[task] = colours[ncolours]
     ncolours = (ncolours + 1) % maxcolours
 
-for task in FULLTYPES:
+for task in SUBTYPES:
     SUBCOLOURS[task] = colours[ncolours]
     ncolours = (ncolours + 1) % maxcolours
 
-#  Show docs if help is requested.
-if len( sys.argv ) == 2 and ( sys.argv[1][0:2] == "-h" or sys.argv[1][0:3] == "--h" ):
-    from pydoc import help
-    help( "__main__" )
-    sys.exit( 0 )
-
-#  Handle command-line.
-if len( sys.argv ) != 3 and len( sys.argv ) != 4:
-    print "Usage: ", sys.argv[0], "input.dat png-output-prefix [time-range-ms]"
-    sys.exit(1)
-
-
-infile = sys.argv[1]
-outbase = sys.argv[2]
-delta_t = 0
-if len( sys.argv ) == 4:
-    delta_t = int(sys.argv[3])
+#  For fiddling with colours...
+if args.verbose:
+    print "#Selected colours:"
+    for task in TASKCOLOURS.keys():
+        print "# " + task + ": " + TASKCOLOURS[task]
+    for task in SUBCOLOURS.keys():
+        print "# " + task + ": " + SUBCOLOURS[task]
 
 #  Read input.
 data = pl.loadtxt( infile )
 
-# Recover the start and end time
+#  Get CPU_CLOCK to convert ticks into milliseconds.
 full_step = data[0,:]
-tic_step = int(full_step[5])
-toc_step = int(full_step[6])
-CPU_CLOCK = float(full_step[-1])
-
-print "CPU frequency:", CPU_CLOCK
-
+CPU_CLOCK = float(full_step[-1]) / 1000.0
+if args.verbose:
+    print "CPU frequency:", CPU_CLOCK * 1000.0
 
 nranks = int(max(data[:,0])) + 1
 print "Number of ranks:", nranks
@@ -144,60 +167,70 @@ sdata = sdata[sdata[:,6] != 0]
 # Each rank can have different clock (compute node), but we want to use the
 # same delta times range for comparisons, so we suck it up and take the hit of
 # precalculating this, unless the user knows better.
-delta_t = delta_t * CPU_CLOCK / 1000
+delta_t = delta_t * CPU_CLOCK
 if delta_t == 0:
     for rank in range(nranks):
         data = sdata[sdata[:,0] == rank]
         dt = max(data[:,6]) - min(data[:,5])
         if dt > delta_t:
             delta_t = dt
-    print "Data range: ", delta_t / CPU_CLOCK * 1000, "ms"
+    print "Data range: ", delta_t / CPU_CLOCK, "ms"
 
 
 # Once more doing the real gather and plots this time.
 for rank in range(nranks):
     data = sdata[sdata[:,0] == rank]
 
+    #  Start and end times for this rank.
     full_step = data[0,:]
     tic_step = int(full_step[5])
     toc_step = int(full_step[6])
     data = data[1:,:]
-    typesseen = []
 
     #  Dummy image for ranks that have no tasks.
     if data.size == 0:
         print "rank ", rank, " has no tasks"
         fig = pl.figure()
         ax = fig.add_subplot(1,1,1)
-        ax.set_xlim(-delta_t * 0.03 * 1000 / CPU_CLOCK, delta_t * 1.03 * 1000 / CPU_CLOCK)
-        ax.set_ylim(0, nthread)
+        ax.set_xlim(-delta_t * 0.01 / CPU_CLOCK, delta_t * 1.01 / CPU_CLOCK)
+        ax.set_ylim(0, nthread*expand)
         start_t = tic_step
-        end_t = (toc_step - start_t) / CPU_CLOCK * 1000
+        end_t = (toc_step - start_t) / CPU_CLOCK
     else:
 
-        start_t = tic_step
+        start_t = float(tic_step)
         data[:,5] -= start_t
         data[:,6] -= start_t
-        end_t = (toc_step - start_t) / CPU_CLOCK * 1000
+        end_t = (toc_step - start_t) / CPU_CLOCK
 
         tasks = {}
         tasks[-1] = []
-        for i in range(nthread):
+        for i in range(nthread*expand):
             tasks[i] = []
 
+        # Counters for each thread when expanding.
+        ecounter = []
+        for i in range(nthread):
+            ecounter.append(0)
+
         num_lines = pl.shape(data)[0]
         for line in range(num_lines):
             thread = int(data[line,1])
+
+            # Expand to cover extra lines if expanding.
+            ethread = thread * expand + (ecounter[thread] % expand)
+            ecounter[thread] = ecounter[thread] + 1
+            thread = ethread
+
             tasks[thread].append({})
             tasktype = TASKTYPES[int(data[line,2])]
             subtype = SUBTYPES[int(data[line,3])]
             tasks[thread][-1]["type"] = tasktype
             tasks[thread][-1]["subtype"] = subtype
-            tic = int(data[line,5]) / CPU_CLOCK * 1000
-            toc = int(data[line,6]) / CPU_CLOCK * 1000
+            tic = int(data[line,5]) / CPU_CLOCK
+            toc = int(data[line,6]) / CPU_CLOCK
             tasks[thread][-1]["tic"] = tic
             tasks[thread][-1]["toc"] = toc
-            tasks[thread][-1]["t"] = (toc + tic)/ 2
             if "self" in tasktype or "pair" in tasktype or "recv" in tasktype or "send" in tasktype:
                 fulltype = tasktype + "/" + subtype
                 if fulltype in SUBCOLOURS:
@@ -207,29 +240,23 @@ for rank in range(nranks):
             else:
                 tasks[thread][-1]["colour"] = TASKCOLOURS[tasktype]
 
-        for thread in range(nthread):
-            tasks[thread] = sorted(tasks[thread], key=lambda l: l["t"])
+        # Use expanded threads from now on.
+        nethread = nthread * expand
 
+        typesseen = []
         fig = pl.figure()
         ax = fig.add_subplot(1,1,1)
-        ax.set_xlim(-delta_t * 0.03 * 1000 / CPU_CLOCK, delta_t * 1.03 * 1000 / CPU_CLOCK)
-        ax.set_ylim(0, nthread)
-        tictoc = np.zeros(2)
-        for i in range(nthread):
+        ax.set_xlim(-delta_t * 0.01 / CPU_CLOCK, delta_t * 1.01 / CPU_CLOCK)
+        ax.set_ylim(0, nethread)
+        for i in range(nethread):
 
             #  Collect ranges and colours into arrays.
-            tictocs = np.zeros(len(tasks[i])*2)
-            colours = np.empty(len(tasks[i])*2, dtype='object')
-            coloursseen = []
+            tictocs = []
+            colours = []
             j = 0
             for task in tasks[i]:
-                tictocs[j] = task["tic"]
-                tictocs[j+1] = task["toc"]
-                colours[j] = task["colour"]
-                colours[j+1] = task["colour"]
-                j = j + 2
-                if task["colour"] not in coloursseen:
-                    coloursseen.append(task["colour"])
+                tictocs.append((task["tic"], task["toc"] - task["tic"]))
+                colours.append(task["colour"])
 
                 #  Legend support, collections don't add to this.
                 if task["subtype"] != "none":
@@ -241,33 +268,34 @@ for rank in range(nranks):
                     pl.plot([], [], color=task["colour"], label=qtask)
                     typesseen.append(qtask)
 
-            #  Now plot each colour, faster to use a mask to select colour ranges.
-            for colour in coloursseen:
-                collection = collections.BrokenBarHCollection.span_where(tictocs,
-                                                                         ymin=i+0.05,
-                                                                         ymax=i+0.95,
-                                                                         where=colours == colour,
-                                                                         facecolor=colour,
-                                                                         linewidths=0)
-                ax.add_collection(collection)
+            #  Now plot.
+            ax.broken_barh(tictocs, [i+0.05,0.90], facecolors = colours, linewidth=0)
 
 
     #  Legend and room for it.
     nrow = len(typesseen) / 5
     if len(typesseen) * 5 < nrow:
         nrow = nrow + 1
-    ax.fill_between([0, 0], nthread+0.5, nthread + nrow + 0.5, facecolor="white")
-    ax.set_ylim(0, nthread + nrow + 1)
+    ax.fill_between([0, 0], nethread+0.5, nethread + nrow + 0.5, facecolor="white")
+    ax.set_ylim(0, nethread + nrow + 1)
     if data.size > 0:
         ax.legend(loc=1, shadow=True, mode="expand", ncol=5)
 
     # Start and end of time-step
-    ax.plot([0, 0], [0, nthread + nrow + 1], 'k--', linewidth=1)
-    ax.plot([end_t, end_t], [0, nthread + nrow + 1], 'k--', linewidth=1)
+    ax.plot([0, 0], [0, nethread + nrow + 1], 'k--', linewidth=1)
+    ax.plot([end_t, end_t], [0, nethread + nrow + 1], 'k--', linewidth=1)
 
     ax.set_xlabel("Wall clock time [ms]")
-    ax.set_ylabel("Thread ID for MPI Rank " + str(rank) )
-    ax.set_yticks(pl.array(range(nthread)), True)
+
+    if expand == 1:
+        ax.set_ylabel("Thread ID" )
+    else:
+        ax.set_ylabel("Thread ID * " + str(expand) )
+    ax.set_yticks(pl.array(range(nethread)), True)
+
+    loc = plticker.MultipleLocator(base=expand)
+    ax.yaxis.set_major_locator(loc)
+    ax.grid(True, which='major', axis="y", linestyle="-")
 
     pl.show()
     outpng = outbase + str(rank) + ".png"
diff --git a/examples/process_plot_tasks b/examples/process_plot_tasks
index cf19401b582c29f7e35073be93569ea8039f958d..c33531269617e81d4e8f18f1528b43492b08cf26 100755
--- a/examples/process_plot_tasks
+++ b/examples/process_plot_tasks
@@ -56,7 +56,7 @@ done
 
 #  And process them,
 echo "Processing thread info files..."
-echo $list | xargs -P $NPROCS -n 3 /bin/bash -c "./plot_tasks.py \$0 \$2 $TIMERANGE"
+echo $list | xargs -P $NPROCS -n 3 /bin/bash -c "./plot_tasks.py --expand 1 --limit $TIMERANGE --width 16 --height 4 \$0 \$2 "
 
 echo "Writing output index.html file"
 #  Construct document - serial.
diff --git a/examples/process_plot_tasks_MPI b/examples/process_plot_tasks_MPI
index d3eb5d4a5fc5918b287cd5d98efcc5881b6f910c..268a5393dc94f8b05cb4ff0a71c45b3b8e554c84 100755
--- a/examples/process_plot_tasks_MPI
+++ b/examples/process_plot_tasks_MPI
@@ -61,7 +61,7 @@ nrank=$(($nrank-1))
 
 #  And process them,
 echo "Processing thread info files..."
-echo $list | xargs -P $NPROCS -n 3 /bin/bash -c "./plot_tasks_MPI.py \$0 \$2 $TIMERANGE"
+echo $list | xargs -P $NPROCS -n 3 /bin/bash -c "./plot_tasks_MPI.py --expand 1 --limit $TIMERANGE \$0 \$2 "
 
 echo "Writing output index.html file"
 #  Construct document - serial.
diff --git a/src/scheduler.c b/src/scheduler.c
index ccc8e78902efc27360a5bd8b0b7589a9bb8096a5..25d03918ecc53fd54478c8d6e88d8149936a4ac1 100644
--- a/src/scheduler.c
+++ b/src/scheduler.c
@@ -1123,6 +1123,15 @@ void scheduler_enqueue_mapper(void *map_data, int num_elements,
  */
 void scheduler_start(struct scheduler *s) {
 
+/* Reset all task debugging timers */
+#ifdef SWIFT_DEBUG_TASKS
+  for (int i = 0; i < s->nr_tasks; ++i) {
+    s->tasks[i].tic = 0;
+    s->tasks[i].toc = 0;
+    s->tasks[i].rid = -1;
+  }
+#endif
+
   /* Re-wait the tasks. */
   if (s->active_count > 1000) {
     threadpool_map(s->threadpool, scheduler_rewait_mapper, s->tid_active,
diff --git a/tests/tolerance_27_perturbed.dat b/tests/tolerance_27_perturbed.dat
index a238acd234772b6e146a1d83a5ebab6c7fb69921..b6ed8c2c18808156056f9c5816212866c2dfa998 100644
--- a/tests/tolerance_27_perturbed.dat
+++ b/tests/tolerance_27_perturbed.dat
@@ -1,3 +1,3 @@
 #   ID      pos_x      pos_y      pos_z        v_x        v_y        v_z           rho        rho_dh        wcount     wcount_dh         div_v       curl_vx       curl_vy       curl_vz
     0	    1e-6       1e-6	  1e-6 	       1e-6 	  1e-6	     1e-6	   1.2e-6     1e-4	    5e-5       2e-3		 3.1e-6	     3e-6	   3e-6		 3e-6
-    0	    1e-6       1e-6	  1e-6 	       1e-6 	  1e-6	     1e-6	   1e-6	      1e-3	    1e-5       1e-4		 2e-5	     2e-3	   2e-3	 	 2e-3
+    0	    1e-6       1e-6	  1e-6 	       1e-6 	  1e-6	     1e-6	   1e-6	      2e-3	    1e-5       1e-4		 2e-5	     2e-3	   2e-3	 	 2e-3