astropy/astropy — pull request #2942 by mhvk (2014-09-15 18:15:55+00:00)
Title: Time( ) fails for mjd values in a big-endian array on a little-endian machine

Time( ) in astropy.time raises a *"ValueError: Input values did not match the format class mjd"* exception on a little-endian machine, when the user-specified value is a numpy.ndarray with a correctly indicated big-endian byte order. This situation may occur when using astropy.io.fits to read MJD values from a FITS binary table (big-endian on disk by standard).

The issue occurred in python 2.7.5 on a (little-endian) MacBook Pro, running numpy 1.8.1 and astropy 0.4.1

A temporary (and not obvious until you understand the problem) workaround is to byte swap only on little-endian machines:

```python
mjd = hdulist[1].data['MJD']
if sys.byteorder == 'little':
mjd = mjd.byteswap().newbyteorder()
```

---

Here is a very compact demonstration of the problem, if you are running on a little-endian machine:

```python
import numpy as np
from astropy.time import Time
bigend = np.array([53000.00,54000.00]).byteswap().newbyteorder('>')
Time(bigend, format='mjd')
```

which yields:

```
File "/Users/valenti/ureka/Ureka/variants/common/lib/python2.7/site-packages/astropy/time/core.py", line 322, in _get_time_fmt raise ValueError('Input values did not match {0}'.format(err_msg))
ValueError: Input values did not match the format class mjd
```

---

Here is a longer demonstration that includes cases that work correctly:

Start python 2.7.5 on a MacBook Pro.

```
unix% uname -a
Darwin mobius.local 12.5.0 Darwin Kernel Version 12.5.0: Sun Sep 29 13:33:47 PDT 2013; root:xnu-2050.48.12~1/RELEASE_X86_64 x86_64
unix% python
Python 2.7.5 (default, Jun 19 2014, 11:13:57)
[GCC 4.2.1 (Apple Inc. build 5664)] on darwin
>>>
```

Load packages.

```python
import sys
import numpy as np
from astropy import __version__
from astropy.time import Time
__version__
np.version.version

>>> import sys
>>> import numpy as np
>>> from astropy import __version__
>>> from astropy.time import Time
>>> __version__
'0.4.1'
>>> np.version.version
'1.8.1'
>>>
```

Perform these tests on a little-endian machine.

```python
sys.byteorder

>>> sys.byteorder
'little'
```

Demonstrate expected behavior when array has 'native' endianness, which is 'little' in this case.

```python
native = np.array([53000.00,54000.00])
type(native)
native.dtype.byteorder
native
Time(native, format='mjd')

>>> native = np.array([53000.00,54000.00])
>>> type(native)

>>> native.dtype.byteorder
'='
>>> native
array([ 53000., 54000.])
>>> Time(native, format='mjd')

```

Demonstrate expected behavior when array is explicitly labelled as little-endian, which is native in this case.

```python
litend = native.newbyteorder('<')
type(litend)
litend.dtype.byteorder
litend
Time(litend, format='mjd')

>>> litend = native.newbyteorder('<')
>>> type(litend)

>>> litend.dtype.byteorder
'<'
>>> litend
array([ 53000., 54000.])
>>> Time(litend, format='mjd')

```

Demonstrate **unexpected behavior** when array is big-endian (not native), even when the array is correctly labelled as such. Time( ) properly handles numpy.float64 scalars extracted from the array. Time( ) fails when processing a big-endian numpy.ndarray. MJD read from a FITS binary table is big-endian, so this case will occur practice.

```python
bigend = native.byteswap().newbyteorder('>')
type(bigend)
bigend.dtype.byteorder
bigend
Time(bigend[0], format='mjd')
Time(bigend[1], format='mjd')
Time(bigend, format='mjd')

>>> bigend = native.byteswap().newbyteorder('>')
>>> type(bigend)

>>> bigend.dtype.byteorder
'>'
>>> bigend
array([ 53000., 54000.])
>>> Time(bigend[0], format='mjd')

>>> Time(bigend[1], format='mjd')

>>> Time(bigend, format='mjd')
Traceback (most recent call last):
File "", line 1, in
File "/Users/valenti/ureka/Ureka/variants/common/lib/python2.7/site-packages/astropy/time/core.py", line 120, in new_func
return func(*args, **kwargs)
File "/Users/valenti/ureka/Ureka/variants/common/lib/python2.7/site-packages/astropy/time/core.py", line 227, in __init__
self._init_from_vals(val, val2, format, scale, copy)
File "/Users/valenti/ureka/Ureka/variants/common/lib/python2.7/site-packages/astropy/time/core.py", line 283, in _init_from_vals
self._time = self._get_time_fmt(val, val2, format, scale)
File "/Users/valenti/ureka/Ureka/variants/common/lib/python2.7/site-packages/astropy/time/core.py", line 322, in _get_time_fmt
raise ValueError('Input values did not match {0}'.format(err_msg))
ValueError: Input values did not match the format class mjd
```