Repository: astropy/astropy

Issue:
Very poor performance with Angle.__str__ and Angle._repr_latex_
The following illustrates very poor performance with ``Angle.__str__`` and ``Angle._repr_latex_`` with arrays:

```python
In [15]: a = Angle(np.ones(1000000), u.deg)

In [16]: %time a.__repr__()
CPU times: user 324 µs, sys: 23 µs, total: 347 µs
Wall time: 332 µs
Out[16]: '<Angle [ 1., 1., 1.,...,  1., 1., 1.] deg>'

In [17]: %time a.__str__()
CPU times: user 22.4 s, sys: 341 ms, total: 22.8 s
Wall time: 23.4 s
Out[17]: "['1d00m00s' '1d00m00s' '1d00m00s' ..., '1d00m00s' '1d00m00s' '1d00m00s']"

In [18]: %time a._repr_latex_()
CPU times: user 22.6 s, sys: 436 ms, total: 23.1 s
Wall time: 23.7 s
Out[18]: '[$1^\\circ00{}^\\prime00{}^{\\prime\\prime}$\n $1^\\circ00{}^\\prime00{}^{\\prime\\prime}$\n $1^\\circ00{}^\\prime00{}^{\\prime\\prime}$ ...,\n $1^\\circ00{}^\\prime00{}^{\\prime\\prime}$\n $1^\\circ00{}^\\prime00{}^{\\prime\\prime}$\n $1^\\circ00{}^\\prime00{}^{\\prime\\prime}$]'
```

This poor performance is unnecessary since only a few items are returned in the strings, and the rest is ``...``

This is not an issue with Quantity or Distance, but does percolate up to e.g. SkyCoord I think.


Discussion:

Patch:
diff --git a/CHANGES.rst b/CHANGES.rst
index 726da29cae..6ec929c2ec 100644
--- a/CHANGES.rst
+++ b/CHANGES.rst
@@ -179,8 +179,8 @@ astropy.utils
 - ``JsonCustomEncoder`` is expanded to handle ``Quantity`` and ``UnitBase``.
   [#5471]
 
-- Added a ``dcip_xy`` method to IERS that interpolates along the dX_2000A and 
-  dY_2000A columns of the IERS table.  Hence, the data for the CIP offsets is 
+- Added a ``dcip_xy`` method to IERS that interpolates along the dX_2000A and
+  dY_2000A columns of the IERS table.  Hence, the data for the CIP offsets is
   now available for use in coordinate frame conversion. [#5837]
 
 - The functions ``matmul``, ``broadcast_arrays``, ``broadcast_to`` of the
@@ -340,7 +340,7 @@ astropy.io.ascii
 
 - Added support for reading very large tables in chunks to reduce memory
   usage. [#6458]
-  
+
 - Strip leading/trailing white-space from latex lines to avoid issues when
   matching ``\begin{tabular}`` statements.  This is done by introducing a new
   ``LatexInputter`` class to override the ``BaseInputter``. [#6311]
@@ -515,6 +515,13 @@ astropy.wcs
 ^^^^^^^^^^^
 
 
+Other Changes and Additions
+---------------------------
+
+- Substantial performance improvement (potentially >1000x for some cases) when
+  converting non-scalar ``coordinates.Angle`` objects to strings. [#7004]
+
+
 2.0.3 (2017-12-13)
 ==================
 
diff --git a/astropy/coordinates/angles.py b/astropy/coordinates/angles.py
index c1fa3fe152..00bf06838b 100644
--- a/astropy/coordinates/angles.py
+++ b/astropy/coordinates/angles.py
@@ -427,7 +427,10 @@ class Angle(u.SpecificTypeQuantity):
         return bool(ok)
 
     def __str__(self):
-        return str(self.to_string())
+        if self.isscalar:
+            return str(self.to_string())
+        else:
+            return np.array2string(self, formatter={'all': lambda x: x.to_string()})
 
     def _repr_latex_(self):
         if self.isscalar:
@@ -435,8 +438,7 @@ class Angle(u.SpecificTypeQuantity):
         else:
             # Need to do a magic incantation to convert to str.  Regular str
             # or array2string causes all backslashes to get doubled.
-            return np.array2string(self.to_string(format='latex'),
-                                   formatter={'str_kind': lambda x: x})
+            return np.array2string(self, formatter={'all': lambda x: x.to_string(format='latex')})
 
 
 def _no_angle_subclass(obj):


Test patch:
diff --git a/astropy/coordinates/tests/test_angles.py b/astropy/coordinates/tests/test_angles.py
index 0b37127ade..e1a6472d66 100644
--- a/astropy/coordinates/tests/test_angles.py
+++ b/astropy/coordinates/tests/test_angles.py
@@ -846,6 +846,25 @@ def test_wrap_at_without_new():
     l = np.concatenate([l1, l2])
     assert l._wrap_angle is not None
 
+def test__str__():
+    """
+    Check the __str__ method used in printing the Angle
+    """
+
+    # scalar angle
+    scangle = Angle('10.2345d')
+    strscangle = scangle.__str__()
+    assert strscangle == '10d14m04.2s'
+
+    # non-scalar array angles
+    arrangle = Angle(['10.2345d', '-20d'])
+    strarrangle = arrangle.__str__()
+
+    assert strarrangle == '[10d14m04.2s -20d00m00s]'
+
+    # summarizing for large arrays, ... should appear
+    bigarrangle = Angle(np.ones(10000), u.deg)
+    assert '...' in bigarrangle.__str__()
 
 def test_repr_latex():
     """