Repository: ARM-DOE/ACT

Issue:
Attempting to set identical low and high xlims
* ACT version: 1.4.0
* Python version: 3.8.13
* Operating System: Linux

### Description
When processing in an automated queue we sometimes process when there are few time steps. The process does not fail but does produce a warning. 

/.conda/envs/dqo-base/lib/python3.8/site-packages/act/plotting/timeseriesdisplay.py:214: UserWarning: Attempting to set identical low and high xlims makes transformation singular; automatically expanding.

I want to add a check when setting xlim values to ensure start and end are not the same. If so automatically expand the xlim to exclude the warning.


Discussion:
Gotcha that makes sense!

Resolving patch:
diff --git a/act/plotting/act_cmap.py b/act/plotting/act_cmap.py
--- a/act/plotting/act_cmap.py
+++ b/act/plotting/act_cmap.py
@@ -92,4 +92,7 @@ def _generate_cmap(name, lutsize):
 # register the colormaps so that they can be accessed with the names act_XXX
 for name, cmap in cmap_d.items():
     full_name = 'act_' + name
-    mpl.cm.register_cmap(name=full_name, cmap=cmap)
+    try:
+        matplotlib.colormaps.register(name=full_name, cmap=cmap, force=True)
+    except AttributeError:
+        matplotlib.cm.register_cmap(name=full_name, cmap=cmap)
diff --git a/act/plotting/timeseriesdisplay.py b/act/plotting/timeseriesdisplay.py
--- a/act/plotting/timeseriesdisplay.py
+++ b/act/plotting/timeseriesdisplay.py
@@ -211,6 +211,20 @@ def set_xrng(self, xrng, subplot_index=(0,)):
         if self.axes is None:
             raise RuntimeError('set_xrng requires the plot to be displayed.')
 
+        # If the xlim is set to the same value for range it will throw a warning
+        # This is to catch that and expand the range so we avoid the warning.
+        if xrng[0] == xrng[1]:
+            if isinstance(xrng[0], np.ndarray) and np.issubdtype(xrng[0].dtype, np.datetime64):
+                print(f'\nAttempting to set xlim range to single value {xrng[0]}. '
+                      'Expanding range by 2 seconds.\n')
+                xrng[0] = xrng[0] - np.timedelta64(1, 's')
+                xrng[1] = xrng[1] + np.timedelta64(1, 's')
+            elif isinstance(xrng[0], dt.datetime):
+                print(f'\nAttempting to set xlim range to single value {xrng[0]}. '
+                      'Expanding range by 2 seconds.\n')
+                xrng[0] = xrng[0] - dt.timedelta(seconds=1)
+                xrng[1] = xrng[1] + dt.timedelta(seconds=1)
+
         self.axes[subplot_index].set_xlim(xrng)
 
         # Make sure that the xrng value is a numpy array not pandas


Test patch:
diff --git a/act/tests/baseline/test_xlim_correction_plot.png b/act/tests/baseline/test_xlim_correction_plot.png
new file mode 100644
Binary files /dev/null and b/act/tests/baseline/test_xlim_correction_plot.png differ
diff --git a/act/tests/test_plotting.py b/act/tests/test_plotting.py
--- a/act/tests/test_plotting.py
+++ b/act/tests/test_plotting.py
@@ -1157,3 +1157,16 @@ def test_groupby_plot():
             display.axes[i, j].tick_params(pad=-20)
     ds.close()
     return display.fig
+
+
+@pytest.mark.mpl_image_compare(tolerance=30)
+def test_xlim_correction_plot():
+    ds = arm.read_netcdf(sample_files.EXAMPLE_MET1)
+
+    # Plot data
+    xrng = [datetime(2019, 1, 1, 0, 0, 0), datetime(2019, 1, 1, 0, 0, 0)]
+    display = TimeSeriesDisplay(ds)
+    display.plot('temp_mean', time_rng=xrng)
+
+    ds.close()
+    return display.fig
diff --git a/act/tests/test_qc.py b/act/tests/test_qc.py
--- a/act/tests/test_qc.py
+++ b/act/tests/test_qc.py
@@ -1037,7 +1037,7 @@ def test_qc_speed():
         ds.qcfilter.add_test(name, index=failed_qc, test_meaning='Value above threshold')
 
     time_diff = datetime.utcnow() - start
-    assert time_diff.seconds <= 3
+    assert time_diff.seconds <= 4
 
 
 @pytest.mark.skipif(not PYSP2_AVAILABLE, reason="PySP2 is not installed.")