Repository: sunpy/sunpy

Issue:
Handle discrepancy between contour and imshow kwargs like linewidths in CompositeMap
Hi, 
I think it would be pretty easy to enable passing the plt.contour "linewidths" argument into CompositeMaps. Right now I am using a copy of .plot() where I include the "linewidths" argument in .plot_settings enabled in the case of levels = True. I think it would be pretty easy to work this into the plot function to enable users to make the contour lines more visible.

Here's the basic modification I made to plot():

        if m.levels is False:
              #etc
        else:
            params = {
                "origin": "lower",
                "extent": x_range + y_range,
                "cmap": m.plot_settings['cmap'],
                "norm": m.plot_settings['norm'],
                "linewidths":m.plot_settings['linewidths'], #add matplotlib contour kwarg linewidths
                "alpha": m.alpha,
                "zorder": m.zorder,
            }
            params.update(matplot_args)

            # Check for the presence of masked map data
            if m.mask is None:
                ret.append(axes.contour(m.data, m.levels, **params))
            else:
                ret.append(axes.contour(np.ma.array(np.asarray(m.data), mask=m.mask), m.levels, **params))



Discussion:
The `plot` method of composite map accepts all the keywords the `axes.contour` method does. So you should be able to do `CompositeMap.plot(..., linewidths=)`.

Does that solve the problem or would you like to be able to pre-set the widths in the composite map object itself? (i.e in plot_settings)?
That doesn't work for me. 

In [218]: type(map1)
Out[218]: sunpy.map.compositemap.CompositeMap

In [219]: fig,ax=plt.subplots()

In [220]: map1.plot(axes=ax,linewidths=15)

AttributeError: Unknown property linewidths

Since the params get overwritten in plot(), adjusting a map's plot_settings to include "linewidths" doesn't work either.
Composite map will try and plot as an image by default, unless `compmap.set_levels` is called first. Which I think is the root of this error.
I tried a few things and found out that including linewidths in the plot() call only works if set_levels has first been applied to _all_ maps. Which makes sense because naturally there should be such an error in plt.imshow() as opposed to plt.contour(). So you're right that it does work to set_levels first, but I don't think this is the ideal use case; I'd argue that most users want to overlay contours on an image, not just plot contours alone. 
Either this error needs to be caught before imshow() is called or it should be passed to contour() through plot_settings (although if the **params are inherited from plot_settings in the first place for both the imshow and contour calls, the linewidths keyword will still have to be ignored for non-contour maps).
Thanks for looking into this.
I would like to work on this issue. 
I think this issue is a bit more complex than it seems because it is bit difficult to understand how to incorporate the 'Linewidth' argument inside the plot() function, which is then receiving an 'axes' argument, which again calls the 'imshow' function and this would continue until a matplotlib function is called, meaning we have to pass the linewidth argument to that matplotlib function finally. Since, the plot() function in matplotlib already incorporates the 'Linewidth' argument, our work would be done and plotting would be according to our needs.

Resolving patch:
diff --git a/sunpy/map/compositemap.py b/sunpy/map/compositemap.py
--- a/sunpy/map/compositemap.py
+++ b/sunpy/map/compositemap.py
@@ -433,6 +433,10 @@ def plot(self, axes=None, annotate=True,  # pylint: disable=W0613
             # non False levels property.  If levels is False, then the layer is
             # rendered using imshow.
             if m.levels is False:
+                # Check if the linewidths argument is provided, if so, then delete it from params.
+                if matplot_args.get('linewidths'):
+                    del params['linewidths']
+
                 # Check for the presence of masked map data
                 if m.mask is None:
                     ret.append(axes.imshow(m.data, **params))


Test patch:
diff --git a/sunpy/map/tests/test_compositemap.py b/sunpy/map/tests/test_compositemap.py
new file mode 100644
--- /dev/null
+++ b/sunpy/map/tests/test_compositemap.py
@@ -0,0 +1,37 @@
+"""
+Test Composite Map
+"""
+import os
+import pytest
+
+
+import sunpy.map
+import sunpy.data.test
+from sunpy.tests.helpers import figure_test
+
+testpath = sunpy.data.test.rootdir
+
+
+@pytest.fixture
+def aia171_test_map():
+    return sunpy.map.Map(os.path.join(testpath, 'aia_171_level1.fits'))
+
+
+@pytest.fixture
+def hmi_test_map():
+    return sunpy.map.Map(os.path.join(testpath, 'resampled_hmi.fits'))
+
+
+@pytest.fixture
+def composite_test_map(aia171_test_map, hmi_test_map):
+    return sunpy.map.Map(aia171_test_map, hmi_test_map, composite=True)
+
+
+@figure_test
+def test_plot_composite_map(composite_test_map):
+    composite_test_map.plot()
+
+
+@figure_test
+def test_plot_composite_map_linewidths(composite_test_map):
+    composite_test_map.plot(linewidths=4)
diff --git a/sunpy/tests/figure_hashes_py36.json b/sunpy/tests/figure_hashes_py36.json
--- a/sunpy/tests/figure_hashes_py36.json
+++ b/sunpy/tests/figure_hashes_py36.json
@@ -1,6 +1,9 @@
 {
+    "sunpy.map.tests.test_compositemap.test_plot_composite_map": "be9eabc2f0bfa85eeb8dd9ddb2aab141f1937a3f206b234f47b33934e7d7c7fc",
+    "sunpy.map.tests.test_compositemap.test_plot_composite_map_linewidths": "be9eabc2f0bfa85eeb8dd9ddb2aab141f1937a3f206b234f47b33934e7d7c7fc",
     "sunpy.map.tests.test_plotting.test_draw_contours_aia": "4256007c254efdb03dd6b6bd9a53ad89e695a8f4c22a016ba3bfcefe109f61fd",
     "sunpy.map.tests.test_plotting.test_draw_grid_aia171": "79fc8e423bb83d9b0cb164fe91e635f3c1b3e6fd98ca320752888f563f3184ac",
+    "sunpy.map.tests.test_plotting.test_heliographic_grid_annotations": "83b3e21c8b421789ed69c7b17175394f740621cf097b028d9e9122db057c3f58",
     "sunpy.map.tests.test_plotting.test_heliographic_peek": "3ad7bada31398662c0852f3819937a6bc0df415a589354ab0703e87780e21d42",
     "sunpy.map.tests.test_plotting.test_heliographic_rectangle": "13080ad768f6b1e026433889673fe9432a43596dcbb8ff45171d46db8ead4c1b",
     "sunpy.map.tests.test_plotting.test_peek_aia171": "0a9603c94583a0e36ee01f10a7c8d639ec95c786624d9c222cd178d7b8c73818",
@@ -18,7 +21,6 @@
     "sunpy.map.tests.test_plotting.test_plot_masked_aia171_superpixel": "40d053eca1d23a24bec6b282978a30e0410b8a4e82286ace848b3c382c731c69",
     "sunpy.map.tests.test_plotting.test_plot_masked_aia171_superpixel_nowcsaxes": "0f0225378d2bd9820af2d2d526a804296496dcffa4e9a7659fc2bb91223a138b",
     "sunpy.map.tests.test_plotting.test_rectangle_aia171": "b59915b551c809d66149c7ea3687c01b186138f0c6893d9c308bf06850b089cc",
-    "sunpy.map.tests.test_plotting.test_heliographic_grid_annotations":"83b3e21c8b421789ed69c7b17175394f740621cf097b028d9e9122db057c3f58",
     "sunpy.timeseries.tests.test_timeseriesbase.test_esp_peek": "c25e927aaa39d576482a35438acee56fab915aede44e62744eb0bf2cefc889b4",
     "sunpy.timeseries.tests.test_timeseriesbase.test_eve_peek": "d2e7093fa95dc1a4bbde958275bba31d9061967ab5ef003d1af4f9519658d14b",
     "sunpy.timeseries.tests.test_timeseriesbase.test_fermi_gbm_peek": "dda01d15a769a3334e5254a93fd7bf8d16341f0e11cbd069f6738d8680bf6f96",
diff --git a/sunpy/tests/figure_hashes_py37.json b/sunpy/tests/figure_hashes_py37.json
--- a/sunpy/tests/figure_hashes_py37.json
+++ b/sunpy/tests/figure_hashes_py37.json
@@ -1,6 +1,9 @@
 {
+    "sunpy.map.tests.test_compositemap.test_plot_composite_map": "be9eabc2f0bfa85eeb8dd9ddb2aab141f1937a3f206b234f47b33934e7d7c7fc",
+    "sunpy.map.tests.test_compositemap.test_plot_composite_map_linewidths": "be9eabc2f0bfa85eeb8dd9ddb2aab141f1937a3f206b234f47b33934e7d7c7fc",
     "sunpy.map.tests.test_plotting.test_draw_contours_aia": "4256007c254efdb03dd6b6bd9a53ad89e695a8f4c22a016ba3bfcefe109f61fd",
     "sunpy.map.tests.test_plotting.test_draw_grid_aia171": "79fc8e423bb83d9b0cb164fe91e635f3c1b3e6fd98ca320752888f563f3184ac",
+    "sunpy.map.tests.test_plotting.test_heliographic_grid_annotations": "83b3e21c8b421789ed69c7b17175394f740621cf097b028d9e9122db057c3f58",
     "sunpy.map.tests.test_plotting.test_heliographic_peek": "3ad7bada31398662c0852f3819937a6bc0df415a589354ab0703e87780e21d42",
     "sunpy.map.tests.test_plotting.test_heliographic_rectangle": "13080ad768f6b1e026433889673fe9432a43596dcbb8ff45171d46db8ead4c1b",
     "sunpy.map.tests.test_plotting.test_peek_aia171": "0a9603c94583a0e36ee01f10a7c8d639ec95c786624d9c222cd178d7b8c73818",
@@ -18,7 +21,6 @@
     "sunpy.map.tests.test_plotting.test_plot_masked_aia171_superpixel": "40d053eca1d23a24bec6b282978a30e0410b8a4e82286ace848b3c382c731c69",
     "sunpy.map.tests.test_plotting.test_plot_masked_aia171_superpixel_nowcsaxes": "0f0225378d2bd9820af2d2d526a804296496dcffa4e9a7659fc2bb91223a138b",
     "sunpy.map.tests.test_plotting.test_rectangle_aia171": "b59915b551c809d66149c7ea3687c01b186138f0c6893d9c308bf06850b089cc",
-    "sunpy.map.tests.test_plotting.test_heliographic_grid_annotations":"83b3e21c8b421789ed69c7b17175394f740621cf097b028d9e9122db057c3f58",
     "sunpy.timeseries.tests.test_timeseriesbase.test_esp_peek": "c25e927aaa39d576482a35438acee56fab915aede44e62744eb0bf2cefc889b4",
     "sunpy.timeseries.tests.test_timeseriesbase.test_eve_peek": "d2e7093fa95dc1a4bbde958275bba31d9061967ab5ef003d1af4f9519658d14b",
     "sunpy.timeseries.tests.test_timeseriesbase.test_fermi_gbm_peek": "dda01d15a769a3334e5254a93fd7bf8d16341f0e11cbd069f6738d8680bf6f96",