plot_utils: make xlim and ylim consistent and accept strings as well as tuples

before xlim = None was different than ylim = None.  Discard the None
and just make them accept strings that describe their purpose.
diff --git a/cr2/plot_utils.py b/cr2/plot_utils.py
index 45a9606..ec8ef15 100644
--- a/cr2/plot_utils.py
+++ b/cr2/plot_utils.py
@@ -33,11 +33,44 @@
 
     return title
 
+def set_lim(lim, get_lim, set_lim):
+    """Set x or y limitis of the plot
+
+    lim can be a tuple containing the limits or the string "default"
+    or "range".  "default" does nothing and uses matplotlib default.
+    "range" extends the current margin by 10%.  This is useful since
+    the default xlim and ylim of the plots sometimes make it harder to
+    see data that is just in the margin.
+
+    """
+    if lim == "default":
+        return
+
+    if lim == "range":
+        cur_lim = get_lim()
+        lim = (cur_lim[0] - 0.1 * (cur_lim[1] - cur_lim[0]),
+               cur_lim[1] + 0.1 * (cur_lim[1] - cur_lim[0]))
+
+    set_lim(lim[0], lim[1])
+
+def set_xlim(ax, xlim):
+    """Set the xlim of the plot
+
+    See set_lim() for the details
+    """
+    set_lim(xlim, ax.get_xlim, ax.set_xlim)
+
+def set_ylim(ax, ylim):
+    """Set the ylim of the plot
+
+    See set_lim() for the details
+    """
+    set_lim(ylim, ax.get_ylim, ax.set_ylim)
+
 def pre_plot_setup(width=None, height=None):
     """initialize a figure
 
-    width and height are numbers, ylim is a tuple with min and max
-    values for the y axis.  This function should be called before
+    width and height are numbers  This function should be called before
     any calls to plot()
     """
 
@@ -47,10 +80,13 @@
 
     return ax
 
-def post_plot_setup(ax, title="", xlabel=None, xlim=None, ylim=None):
+def post_plot_setup(ax, title="", xlabel=None, xlim="default", ylim="range"):
     """Set xlabel, title, xlim adn ylim of the plot
 
-    This has to be called after calls to .plot()
+    This has to be called after calls to .plot().  The default ylim is
+    to extend it by 10% because matplotlib default makes it hard
+    values that are close to the margins
+
     """
 
     if xlabel is None:
@@ -60,15 +96,8 @@
     if title:
         plt.title(title)
 
-    if not ylim:
-        cur_ylim = ax.get_ylim()
-        ylim = (cur_ylim[0] - 0.1 * (cur_ylim[1] - cur_ylim[0]),
-                cur_ylim[1] + 0.1 * (cur_ylim[1] - cur_ylim[0]))
-
-    ax.set_ylim(ylim[0], ylim[1])
-
-    if xlim:
-        ax.set_xlim(xlim[0], xlim[1])
+    set_ylim(ax, ylim)
+    set_xlim(ax, xlim)
 
 def plot_allfreqs(in_power, out_power, map_label, title="", width=None, height=None):
     """Do allfreqs plots similar to those of CompareRuns"""
diff --git a/cr2/thermal.py b/cr2/thermal.py
index 684bf7a..42af452 100644
--- a/cr2/thermal.py
+++ b/cr2/thermal.py
@@ -120,7 +120,7 @@
             unique_word="thermal_zone=",
         )
 
-    def plot_temperature(self, title="", width=None, height=None, ylim=None):
+    def plot_temperature(self, title="", width=None, height=None, ylim="range"):
         """Plot the temperature"""
         dfr = self.get_data_frame()
         title = normalize_title("Temperature", title)
@@ -147,7 +147,7 @@
         with open("thermal.csv", "w") as fout:
             fout.write(self.data_csv)
 
-    def plot_temperature(self, title="", width=None, height=None, ylim=None):
+    def plot_temperature(self, title="", width=None, height=None, ylim="range"):
         """Plot the temperature"""
         dfr = self.get_data_frame()
         control_temp_series = (dfr["currT"] + dfr["deltaT"]) / 1000
diff --git a/tests/test_plot_utils.py b/tests/test_plot_utils.py
index d774118..361477c 100644
--- a/tests/test_plot_utils.py
+++ b/tests/test_plot_utils.py
@@ -19,6 +19,51 @@
         self.assertEquals(plot_utils.normalize_title("Foo", ""), "Foo")
         self.assertEquals(plot_utils.normalize_title("Foo", "Bar"), "Bar - Foo")
 
+    def test_set_lim(self):
+        """Test set_lim()"""
+
+        class GetSet(object):
+            def __init__(self):
+                self.min = 1
+                self.max = 2
+
+            def get(self):
+                return (self.min, self.max)
+
+            def set(self, minimum, maximum):
+                self.min = minimum
+                self.max = maximum
+
+        gs = GetSet()
+
+        plot_utils.set_lim("default", gs.get, gs.set)
+        self.assertEquals(gs.min, 1)
+        self.assertEquals(gs.max, 2)
+
+        plot_utils.set_lim("range", gs.get, gs.set)
+        self.assertEquals(gs.min, 0.9)
+        self.assertEquals(gs.max, 2.1)
+
+        plot_utils.set_lim((0, 100), gs.get, gs.set)
+        self.assertEquals(gs.min, 0)
+        self.assertEquals(gs.max, 100)
+
+    def test_set_ylim(self):
+        """Test that set_ylim() doesn't bomb"""
+
+        ax = plot_utils.pre_plot_setup()
+
+        plot_utils.set_ylim(ax, "default")
+        plot_utils.set_ylim(ax, (0, 5))
+
+    def test_set_xlim(self):
+        """Test that set_xlim() doesn't bomb"""
+
+        ax = plot_utils.pre_plot_setup()
+
+        plot_utils.set_xlim(ax, "default")
+        plot_utils.set_xlim(ax, (0, 5))
+
     def test_post_plot_setup(self):
         """Test that post_plot_setup() doesn't bomb"""
 
@@ -27,8 +72,10 @@
         plot_utils.post_plot_setup(ax)
         plot_utils.post_plot_setup(ax, title="Foo")
         plot_utils.post_plot_setup(ax, ylim=(0, 72))
+        plot_utils.post_plot_setup(ax, ylim="range")
         plot_utils.post_plot_setup(ax, xlabel="Bar")
         plot_utils.post_plot_setup(ax, xlim=(0, 100))
+        plot_utils.post_plot_setup(ax, xlim="default")
 
 class TestPlotUtilsNeedTrace(TestThermalBase):
     def test_plot_allfreqs(self):