Repository: sunpy/ndcube

Issue:
NDcube should be able to be instantiated from another NDCube
If this doesn't already work it should. This would allow you to instantiate a sunraster object from a DKIST user tools object for instance, which is probably something that people are going to want to do.

Discussion:

Patch:
diff --git a/changelog/404.feature.rst b/changelog/404.feature.rst
new file mode 100644
index 0000000..e9f447f
--- /dev/null
+++ b/changelog/404.feature.rst
@@ -0,0 +1,1 @@
+Enable instantiating an NDCube from an existing NDCube by copying extra/global coords.
diff --git a/ndcube/ndcube.py b/ndcube/ndcube.py
index 9dd2c84..16f54ed 100644
--- a/ndcube/ndcube.py
+++ b/ndcube/ndcube.py
@@ -1,5 +1,6 @@
 import abc
 import textwrap
+from copy import deepcopy
 from collections import namedtuple
 
 import astropy.nddata
@@ -186,13 +187,27 @@ class NDCubeBase(NDCubeSlicingMixin, NDCubeABC):
 
         # Format extra coords.
         if not extra_coords:
-            extra_coords = ExtraCoords()
+            # Get existing extra_coords if initializing from an NDCube
+            if hasattr(data, "extra_coords"):
+                extra_coords = data.extra_coords
+            else:
+                extra_coords = ExtraCoords()
 
         if not isinstance(extra_coords, ExtraCoords):
             raise TypeError("The extra_coords argument must be a ndcube.ExtraCoords object.")
 
+        # Get existing global_coords if initializing from an NDCube
+        if hasattr(data, "global_coords"):
+            global_coords = data._global_coords
+        else:
+            global_coords = GlobalCoords(self)
+
+        if copy:
+            extra_coords = deepcopy(extra_coords)
+            global_coords = deepcopy(global_coords)
+
         self._extra_coords = extra_coords
-        self._global_coords = GlobalCoords(self)
+        self._global_coords = global_coords
 
     @property
     def extra_coords(self):


Test patch:
diff --git a/ndcube/tests/test_ndcube.py b/ndcube/tests/test_ndcube.py
index 63359bf..db53eb2 100644
--- a/ndcube/tests/test_ndcube.py
+++ b/ndcube/tests/test_ndcube.py
@@ -7,6 +7,7 @@ from astropy.time import Time
 from astropy.wcs.wcsapi import BaseHighLevelWCS, BaseLowLevelWCS
 from astropy.wcs.wcsapi.wrappers import SlicedLowLevelWCS
 
+from ndcube import NDCube
 from ndcube.tests import helpers
 
 
@@ -495,3 +496,23 @@ def test_crop_by_values_1d_dependent(ndcube_4d_ln_lt_l_t):
     expected = cube_1d[0:2]
     output = cube_1d.crop_by_values(lower_corner, upper_corner)
     helpers.assert_cubes_equal(output, expected)
+
+
+def test_initialize_from_ndcube(ndcube_3d_l_ln_lt_ectime):
+    cube = ndcube_3d_l_ln_lt_ectime
+    cube.global_coords.add('distance', 'pos.distance', 1 * u.m)
+    cube2 = NDCube(cube)
+
+    assert cube.global_coords is cube2.global_coords
+    assert cube.extra_coords is cube2.extra_coords
+
+    cube3 = NDCube(cube, copy=True)
+    ec = cube.extra_coords
+    ec3 = cube3.extra_coords
+
+    assert cube.global_coords == cube3.global_coords
+    assert cube.global_coords is not cube3.global_coords
+    assert ec.keys() == ec3.keys()
+    assert ec.mapping == ec3.mapping
+    assert np.allclose(ec.wcs.pixel_to_world_values(1), ec3.wcs.pixel_to_world_values(1))
+    assert ec is not ec3