Repository: sunpy/sunpy

Issue:
Unable to save map after aiaprep: CROTA2 not found
Trying to save an AIA submap, from a file downloaded via VSO, results in an error. The following ~~works with~~ does not work with  `sunpy.data.sample.AIA_171_IMAGE`, or with other images that I download:

```
aia = sunpy.map.Map(sunpy.data.sample.AIA_171_IMAGE)
aia1 = aiaprep(aia)
aia1.save("test.fits")
```

The above gives the error:

```
---------------------------------------------------------------------------
KeyError                                  Traceback (most recent call last)
<ipython-input-260-752b35ded2b2> in <module>()
----> 1 aia_sub.save("test.fits")

~/miniconda/lib/python3.6/site-packages/sunpy/map/mapbase.py in save(self, filepath, filetype, **kwargs)
    930         """
    931         io.write_file(filepath, self.data, self.meta, filetype=filetype,
--> 932                       **kwargs)
    933 
    934 # #### Image processing routines #### #

~/miniconda/lib/python3.6/site-packages/sunpy/io/file_tools.py in write_file(fname, data, header, filetype, **kwargs)
    155         for extension, readername in _known_extensions.items():
    156             if fname.endswith(extension):
--> 157                 return _readers[readername].write(fname, data, header, **kwargs)
    158 
    159     else:

~/miniconda/lib/python3.6/site-packages/sunpy/io/fits.py in write(fname, data, header, **kwargs)
    197     if isinstance(key_comments, dict):
    198         for k, v in key_comments.items():
--> 199             fits_header.comments[k] = v
    200     elif key_comments:
    201         raise TypeError("KEYCOMMENTS must be a dictionary")

~/miniconda/lib/python3.6/site-packages/astropy/io/fits/header.py in __setitem__(self, item, comment)
   2030         # In this case, key/index errors should be raised; don't update
   2031         # comments of nonexistent cards
-> 2032         idx = self._header._cardindex(item)
   2033         value = self._header[idx]
   2034         self._header[idx] = (value, comment)

~/miniconda/lib/python3.6/site-packages/astropy/io/fits/header.py in _cardindex(self, key)
   1652 
   1653         if not indices:
-> 1654             raise KeyError("Keyword {!r} not found.".format(keyword))
   1655 
   1656         try:

KeyError: "Keyword 'CROTA2' not found."
```


Discussion:
Sorry, this was incorrectly described. Looking a bit more, the problem is squarely with `aiaprep` and submap does not matter. Any level 1.5 map (from `aiaprep`) will lack the `CROTA2` keyword and therefore `save` will not work.
Hi @tiagopereira . I think the actual bug here is in `save` rather than in `aiaprep`. It's certainly true that `aiaprep` removes the `CROTA2` keyword from the header, but this is deliberate, since if I remember rightly this keyword is actually not recommended (ideally you should be using the `PCi_j` keywords to specify a rotation matrix instead. It looks like either `Map.save()` or the astropy fits writing method underneath is enforcing the presence of some keywords but I really don't think it should be.

`aiaprep` has always behaved this way and I don't remember having problems with saving the `Map`s before, so I suspect something must have changed underneath. @Cadair and/or @astrofrog may know more (not to throw them both under the bus...)
ah I can see what's causing this bug. I will try and write a fix for it asap :) 

Resolving patch:
diff --git a/sunpy/io/fits.py b/sunpy/io/fits.py
--- a/sunpy/io/fits.py
+++ b/sunpy/io/fits.py
@@ -196,7 +196,9 @@ def write(fname, data, header, **kwargs):
 
     if isinstance(key_comments, dict):
         for k, v in key_comments.items():
-            fits_header.comments[k] = v
+            # Check that the Card for the comment exists before trying to write to it.
+            if k in fits_header:
+                fits_header.comments[k] = v
     elif key_comments:
         raise TypeError("KEYCOMMENTS must be a dictionary")
 


Test patch:
diff --git a/sunpy/io/tests/test_fits.py b/sunpy/io/tests/test_fits.py
--- a/sunpy/io/tests/test_fits.py
+++ b/sunpy/io/tests/test_fits.py
@@ -81,3 +81,18 @@ def test_extract_waveunit_wavelnthcomment_parentheses():
     # WAVELNTH comment is: "Observed wavelength (nm)"
     waveunit = extract_waveunit(get_header(SVSM_IMAGE)[0])
     assert waveunit == 'nm'
+
+
+def test_simple_write(tmpdir):
+    data, header = sunpy.io.fits.read(AIA_171_IMAGE)[0]
+    outfile = tmpdir / "test.fits"
+    sunpy.io.fits.write(str(outfile), data, header)
+    assert outfile.exists()
+
+
+def test_extra_comment_write(tmpdir):
+    data, header = sunpy.io.fits.read(AIA_171_IMAGE)[0]
+    header["KEYCOMMENTS"]["TEST"] = "Hello world"
+    outfile = tmpdir / "test.fits"
+    sunpy.io.fits.write(str(outfile), data, header)
+    assert outfile.exists()