Repository: obspy/obspy

Issue:
Seisan format file reading error
Hi,
I'm trying to read a seisan format file but I get this error. 

Running code:
```python
from obspy import read
s=read('D1360930.203', format='seisan')
````

Result:
```python
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<decorator-gen-31>", line 2, in read
  File "/usr/local/lib/python2.7/dist-packages/obspy/core/util/decorator.py", line 301, in _map_example_filename
    return func(*args, **kwargs)
  File "/usr/local/lib/python2.7/dist-packages/obspy/core/stream.py", line 235, in read
    st.extend(_read(file, format, headonly, **kwargs).traces)
  File "<decorator-gen-32>", line 2, in _read
  File "/usr/local/lib/python2.7/dist-packages/obspy/core/util/decorator.py", line 211, in uncompress_file
    result = func(filename, *args, **kwargs)
  File "/usr/local/lib/python2.7/dist-packages/obspy/core/stream.py", line 277, in _read
    headonly=headonly, **kwargs)
  File "/usr/local/lib/python2.7/dist-packages/obspy/core/util/base.py", line 433, in _read_from_plugin
    list_obj = read_format(filename, **kwargs)
  File "/usr/local/lib/python2.7/dist-packages/obspy/io/seisan/core.py", line 175, in _read_seisan
    temp = _readline(fh, 1040).decode()
UnicodeDecodeError: 'ascii' codec can't decode byte 0xfb in position 0: ordinal not in range(128)
```

The file is attached in zip format here:
[D1360930.203.zip](https://github.com/obspy/obspy/files/1274607/D1360930.203.zip)



Discussion:

Resolving patch:
diff --git a/obspy/io/seisan/core.py b/obspy/io/seisan/core.py
--- a/obspy/io/seisan/core.py
+++ b/obspy/io/seisan/core.py
@@ -89,17 +89,17 @@ def _get_version(data):
         type of file can also be read with SEISAN, but so far only data written
         on Linux have been tested for reading on all systems.
 
-        From version 7.0,the Linux and PC file structures are exactly the same.
-        On Sun the structure is the same except that the bytes are swapped.
-        This is used by SEISAN to find out where the file was written. Since
-        there is always 80 characters in the first write, character one in the
-        Linux and PC file will be the character P (which is represented by 80)
-        while on Sun character 4 is P.
+        From version 7.0, the Linux and PC file structures are exactly the
+        same. On Sun the structure is the same except that the bytes are
+        swapped. This is used by SEISAN to find out where the file was written.
+        Since there is always 80 characters in the first write, character one
+        in the Linux and PC file will be the character P (which is represented
+        by 80) while on Sun character 4 is P.
     """
     # check size of data chunk
     if len(data) < 12 * 80:
         return False
-    if data[0:2] == b'KP' and data[82:83] == 'P':
+    if data[0:2] == b'KP' and data[82:83] == b'P':
         return ("<", 32, 6)
     elif data[0:8] == b'\x00\x00\x00\x00\x00\x00\x00P' and \
             data[88:96] == b'\x00\x00\x00\x00\x00\x00\x00P':
@@ -140,19 +140,59 @@ def _read_seisan(filename, headonly=False, **kwargs):  # @UnusedVariable
     .KONO.0.L0N | 2001-01-13T17:42:24.924000Z - ... | 1.0 Hz, 3542 samples
     .KONO.0.L0E | 2001-01-13T17:42:24.924000Z - ... | 1.0 Hz, 3542 samples
     """
-    def _readline(fh, length=80):
-        data = fh.read(length + 8)
-        end = length + 4
-        start = 4
-        return data[start:end]
-    # read data chunk from given file
+    # get version info from event file header (at least 12*80 bytes)
     fh = open(filename, 'rb')
     data = fh.read(80 * 12)
-    # get version info from file
-    (byteorder, arch, _version) = _get_version(data)
-    # fetch lines
-    fh.seek(0)
-    # start with event file header
+    (byteorder, arch, version) = _get_version(data)
+    dlen = arch // 8
+    dtype = np.dtype(native_str(byteorder + 'i' + str(dlen)))
+    stype = native_str('=i' + str(dlen))
+
+    def _readline(fh, version=version, dtype=dtype):
+        if version >= 7:
+            # On Sun, Linux, MaxOSX and PC from version 7.0 (using Digital
+            # Fortran), every write is preceded and terminated with 4
+            # additional bytes giving the number of bytes in the write.
+            # With 64 bit systems, 8 bytes is used to define number of bytes
+            # written.
+            start_bytes = fh.read(dtype.itemsize)
+            # convert to int32/int64
+            length = np.fromstring(start_bytes, dtype=dtype)[0]
+            data = fh.read(length)
+            end_bytes = fh.read(dtype.itemsize)
+            assert start_bytes == end_bytes
+            return data
+        else:  # version <= 6
+            # Every write is preceded and terminated with one byte giving the
+            # number of bytes in the write. If the write contains more than 128
+            # bytes, it is blocked in records of 128 bytes, each with the start
+            # and end byte which in this case is the number 128. Each record is
+            # thus 130 bytes long.
+            data = b''
+            while True:
+                start_byte = fh.read(1)
+                if not start_byte:
+                    # end of file
+                    break
+                # convert to unsigned int8
+                length = np.fromstring(start_byte, np.uint8)[0]
+                data += fh.read(length)
+                end_byte = fh.read(1)
+                assert start_byte == end_byte
+                if length == 128:
+                    # blocked data - repeat loop
+                    continue
+                # end of blocked data
+                break
+            return data
+
+    # reset file pointer
+    if version >= 7:
+        fh.seek(0)
+    else:
+        # version <= 6 starts with first byte K
+        fh.seek(1)
+    # event file header
     # line 1
     data = _readline(fh)
     number_of_channels = int(data[30:33])
@@ -160,19 +200,16 @@ def _readline(fh, length=80):
     number_of_lines = number_of_channels // 3 + (number_of_channels % 3 and 1)
     if number_of_lines < 10:
         number_of_lines = 10
-    # line 2
+    # line 2 - always empty
     data = _readline(fh)
     # line 3
     for _i in range(0, number_of_lines):
         data = _readline(fh)
     # now parse each event file channel header + data
     stream = Stream()
-    dlen = arch // 8
-    dtype = np.dtype(native_str(byteorder + 'i' + str(dlen)))
-    stype = native_str('=i' + str(dlen))
     for _i in range(number_of_channels):
         # get channel header
-        temp = _readline(fh, 1040).decode()
+        temp = _readline(fh).decode()
         # create Stats
         header = Stats()
         header['network'] = (temp[16] + temp[19]).strip()
@@ -191,20 +228,17 @@ def _readline(fh, length=80):
         header['starttime'] = UTCDateTime(year, month, day, hour, mins) + secs
         if headonly:
             # skip data
-            fh.seek(dlen * (header['npts'] + 2), 1)
+            from_buffer(_readline(fh), dtype=dtype)
             stream.append(Trace(header=header))
         else:
             # fetch data
-            data = from_buffer(
-                fh.read((header['npts'] + 2) * dtype.itemsize),
-                dtype=dtype)
+            data = from_buffer(_readline(fh), dtype=dtype)
             # convert to system byte order
             data = np.require(data, stype)
-            nbytes = (data.size - 2) * dtype.itemsize
-            if nbytes != data[0] or nbytes != data[-1]:
-                msg = "Mismatching byte size %d, %d, %d"
-                warnings.warn(msg % (nbytes, data[0], data[-1]))
-            stream.append(Trace(data=data[1:-1], header=header))
+            if header['npts'] != len(data):
+                msg = "Mismatching byte size %d != %d"
+                warnings.warn(msg % (header['npts'], len(data)))
+            stream.append(Trace(data=data, header=header))
     fh.close()
     return stream
 


Test patch:
diff --git a/obspy/core/tests/test_waveform_plugins.py b/obspy/core/tests/test_waveform_plugins.py
--- a/obspy/core/tests/test_waveform_plugins.py
+++ b/obspy/core/tests/test_waveform_plugins.py
@@ -167,8 +167,14 @@ def test_is_format(self):
         modules for false positives.
         """
         known_false = [
-            os.path.join('seisan', 'tests', 'data', 'SEISAN_Bug',
-                         '2011-09-06-1311-36S.A1032_001BH_Z_MSEED'),
+            os.path.join('seisan', 'tests', 'data',
+                         '2011-09-06-1311-36S.A1032_001BH_Z.mseed'),
+            os.path.join('seisan', 'tests', 'data',
+                         'D1360930.203.mseed'),
+            os.path.join('seisan', 'tests', 'data',
+                         '2005-07-23-1452-04S.CER___030.mseed'),
+            os.path.join('seisan', 'tests', 'data',
+                         '9701-30-1048-54S.MVO_21_1.ascii'),
             os.path.join('core', 'tests', 'data',
                          'IU_ULN_00_LH1_2015-07-18T02.mseed'),
             # That file is not in obspy.io.mseed as it is used to test an
diff --git a/obspy/io/seisan/tests/data/2005-07-23-1452-04S.CER___030 b/obspy/io/seisan/tests/data/2005-07-23-1452-04S.CER___030
new file mode 100644
Binary files /dev/null and b/obspy/io/seisan/tests/data/2005-07-23-1452-04S.CER___030 differ
diff --git a/obspy/io/seisan/tests/data/2005-07-23-1452-04S.CER___030.mseed b/obspy/io/seisan/tests/data/2005-07-23-1452-04S.CER___030.mseed
new file mode 100644
Binary files /dev/null and b/obspy/io/seisan/tests/data/2005-07-23-1452-04S.CER___030.mseed differ
diff --git a/obspy/io/seisan/tests/data/SEISAN_Bug/2011-09-06-1311-36S.A1032_001BH_Z b/obspy/io/seisan/tests/data/2011-09-06-1311-36S.A1032_001BH_Z
similarity index 100%
rename from obspy/io/seisan/tests/data/SEISAN_Bug/2011-09-06-1311-36S.A1032_001BH_Z
rename to obspy/io/seisan/tests/data/2011-09-06-1311-36S.A1032_001BH_Z
diff --git a/obspy/io/seisan/tests/data/SEISAN_Bug/2011-09-06-1311-36S.A1032_001BH_Z_MSEED b/obspy/io/seisan/tests/data/2011-09-06-1311-36S.A1032_001BH_Z.mseed
similarity index 100%
rename from obspy/io/seisan/tests/data/SEISAN_Bug/2011-09-06-1311-36S.A1032_001BH_Z_MSEED
rename to obspy/io/seisan/tests/data/2011-09-06-1311-36S.A1032_001BH_Z.mseed
diff --git a/obspy/io/seisan/tests/data/MBGBSBJE b/obspy/io/seisan/tests/data/9701-30-1048-54S.MVO_21_1.ascii
similarity index 100%
rename from obspy/io/seisan/tests/data/MBGBSBJE
rename to obspy/io/seisan/tests/data/9701-30-1048-54S.MVO_21_1.ascii
diff --git a/obspy/io/seisan/tests/data/D1360930.203 b/obspy/io/seisan/tests/data/D1360930.203
new file mode 100644
Binary files /dev/null and b/obspy/io/seisan/tests/data/D1360930.203 differ
diff --git a/obspy/io/seisan/tests/data/D1360930.203.mseed b/obspy/io/seisan/tests/data/D1360930.203.mseed
new file mode 100644
Binary files /dev/null and b/obspy/io/seisan/tests/data/D1360930.203.mseed differ
diff --git a/obspy/io/seisan/tests/test_core.py b/obspy/io/seisan/tests/test_core.py
--- a/obspy/io/seisan/tests/test_core.py
+++ b/obspy/io/seisan/tests/test_core.py
@@ -29,100 +29,196 @@ def test_get_version(self):
         """
         Tests resulting version strings of SEISAN file.
         """
-        # 1 - big endian, 32 bit
-        file = os.path.join(self.path, '1996-06-03-1917-52S.TEST__002')
-        with open(file, 'rb') as fp:
+        # 1 - big endian, 32 bit, version 7
+        fn = os.path.join(self.path, '1996-06-03-1917-52S.TEST__002')
+        with open(fn, 'rb') as fp:
             data = fp.read(80 * 12)
         self.assertEqual(_get_version(data), ('>', 32, 7))
-        # 2 - little endian, 32 bit
-        file = os.path.join(self.path, '2001-01-13-1742-24S.KONO__004')
-        with open(file, 'rb') as fp:
+
+        # 2 - little endian, 32 bit, version 7
+        fn = os.path.join(self.path, '2001-01-13-1742-24S.KONO__004')
+        with open(fn, 'rb') as fp:
             data = fp.read(80 * 12)
         self.assertEqual(_get_version(data), ('<', 32, 7))
 
+        # 3 - little endian, 32 bit, version 6
+        fn = os.path.join(self.path, '2005-07-23-1452-04S.CER___030')
+        with open(fn, 'rb') as fp:
+            data = fp.read(80 * 12)
+        self.assertEqual(_get_version(data), ('<', 32, 6))
+
     def test_is_seisan(self):
         """
         Tests SEISAN file check.
         """
-        # 1 - big endian, 32 bit
-        file = os.path.join(self.path, '1996-06-03-1917-52S.TEST__002')
-        self.assertTrue(_is_seisan(file))
-        # 2 - little endian, 32 bit
-        file = os.path.join(self.path, '2001-01-13-1742-24S.KONO__004')
-        self.assertTrue(_is_seisan(file))
+        # 1 - big endian, 32 bit, version 7
+        fn = os.path.join(self.path, '1996-06-03-1917-52S.TEST__002')
+        self.assertTrue(_is_seisan(fn))
+
+        # 2 - little endian, 32 bit, version 7
+        fn = os.path.join(self.path, '2001-01-13-1742-24S.KONO__004')
+        self.assertTrue(_is_seisan(fn))
+
+        # 3 - little endian, 32 bit, version 6
+        fn = os.path.join(self.path, '2005-07-23-1452-04S.CER___030')
+        self.assertTrue(_is_seisan(fn))
 
     def test_read_seisan(self):
         """
         Test SEISAN file reader.
         """
-        # 1 - big endian, 32 bit
-        file = os.path.join(self.path, '9701-30-1048-54S.MVO_21_1')
-        st1 = _read_seisan(file)
-        st1.verify()
-        self.assertEqual(len(st1), 21)
-        self.assertEqual(st1[20].stats.network, '')
-        self.assertEqual(st1[20].stats.station, 'MBGB')
-        self.assertEqual(st1[20].stats.location, 'J')
-        self.assertEqual(st1[20].stats.channel, 'SBE')
-        self.assertEqual(st1[20].stats.starttime,
+        # 1 - big endian, 32 bit, version 7
+        fn = os.path.join(self.path, '9701-30-1048-54S.MVO_21_1')
+        st = _read_seisan(fn)
+        st.verify()
+        self.assertEqual(len(st), 21)
+        self.assertEqual(st[20].stats.network, '')
+        self.assertEqual(st[20].stats.station, 'MBGB')
+        self.assertEqual(st[20].stats.location, 'J')
+        self.assertEqual(st[20].stats.channel, 'SBE')
+        self.assertEqual(st[20].stats.starttime,
                          UTCDateTime('1997-01-30T10:48:54.040000Z'))
-        self.assertEqual(st1[20].stats.endtime,
+        self.assertEqual(st[20].stats.endtime,
                          UTCDateTime('1997-01-30T10:49:42.902881Z'))
-        self.assertAlmostEqual(st1[20].stats.sampling_rate, 75.2, 1)
-        self.assertEqual(st1[20].stats.npts, 3675)
-        self.assertAlmostEqual(st1[20].stats.delta, 0.0133, 4)
-        datafile = os.path.join(self.path, 'MBGBSBJE')
-        # compare with ASCII values of trace
-        # XXX: extracted ASCII file contains less values than the original
-        # Seisan file!
-        self.assertEqual(list(st1[20].data[1:3666]),
+        self.assertAlmostEqual(st[20].stats.sampling_rate, 75.2, 1)
+        self.assertEqual(st[20].stats.npts, 3675)
+        self.assertAlmostEqual(st[20].stats.delta, 0.0133, 4)
+        datafile = os.path.join(self.path, '9701-30-1048-54S.MVO_21_1.ascii')
+        # compare with ASCII values of trace (extracted ASCII file contains
+        # less values than the original Seisan file!)
+        self.assertEqual(st[20].stats.npts, 3675)
+        self.assertEqual(list(st[20].data[1:3666]),
                          np.loadtxt(datafile, dtype=np.int32).tolist())
-        # 2 - little endian, 32 bit
-        file = os.path.join(self.path, '2001-01-13-1742-24S.KONO__004')
-        st2 = _read_seisan(file)
-        st2.verify()
-        self.assertEqual(len(st2), 4)
-        self.assertEqual(list(st2[0].data[1:4]), [492, 519, 542])
+
+        # 2 - little endian, 32 bit, version 7
+        fn = os.path.join(self.path, '2001-01-13-1742-24S.KONO__004')
+        st = _read_seisan(fn)
+        st.verify()
+        self.assertEqual(len(st), 4)
+        self.assertEqual(st[0].stats.npts, 6000)
+        self.assertEqual(list(st[0].data[0:5]), [464, 492, 519, 542, 565])
+
+        # 3 - little endian, 32 bit, version 6, 1 channel
+        fn = os.path.join(self.path, 'D1360930.203')
+        st = _read_seisan(fn)
+        st.verify()
+        self.assertEqual(len(st), 1)
+        self.assertEqual(st[0].stats.npts, 12000)
+        self.assertEqual(list(st[0].data[0:5]),
+                         [24, 64, 139, 123, 99])
+
+        # 4 - little endian, 32 bit, version 6, 3 channels
+        fn = os.path.join(self.path, '2005-07-23-1452-04S.CER___030')
+        st = _read_seisan(fn)
+        st.verify()
+        self.assertEqual(len(st), 3)
+        self.assertEqual(st[0].stats.npts, 10650)
+        self.assertEqual(list(st[0].data[0:5]),
+                         [7520, 7484, 7482, 7480, 7478])
 
     def test_read_seisan_head_only(self):
         """
         Test SEISAN file reader with headonly flag.
         """
-        # 1 - big endian, 32 bit
-        file = os.path.join(self.path, '9701-30-1048-54S.MVO_21_1')
-        st1 = _read_seisan(file, headonly=True)
-        self.assertEqual(len(st1), 21)
-        self.assertEqual(st1[0].stats.network, '')
-        self.assertEqual(st1[0].stats.station, 'MBGA')
-        self.assertEqual(st1[0].stats.location, 'J')
-        self.assertEqual(st1[0].stats.channel, 'SBZ')
-        self.assertEqual(st1[0].stats.starttime,
+        # 1 - big endian, 32 bit, version 7
+        fn = os.path.join(self.path, '9701-30-1048-54S.MVO_21_1')
+        st = _read_seisan(fn, headonly=True)
+        self.assertEqual(len(st), 21)
+        self.assertEqual(st[0].stats.network, '')
+        self.assertEqual(st[0].stats.station, 'MBGA')
+        self.assertEqual(st[0].stats.location, 'J')
+        self.assertEqual(st[0].stats.channel, 'SBZ')
+        self.assertEqual(st[0].stats.starttime,
                          UTCDateTime('1997-01-30T10:48:54.040000Z'))
-        self.assertEqual(st1[0].stats.endtime,
+        self.assertEqual(st[0].stats.endtime,
                          UTCDateTime('1997-01-30T10:49:42.902881Z'))
-        self.assertAlmostEqual(st1[0].stats.sampling_rate, 75.2, 1)
-        self.assertEqual(st1[0].stats.npts, 3675)
-        self.assertAlmostEqual(st1[20].stats.delta, 0.0133, 4)
-        self.assertEqual(list(st1[0].data), [])  # no data
-
-    def test_read_seisan_vs_reference(self):
+        self.assertAlmostEqual(st[0].stats.sampling_rate, 75.2, 1)
+        self.assertEqual(st[0].stats.npts, 3675)
+        self.assertAlmostEqual(st[20].stats.delta, 0.0133, 4)
+        self.assertEqual(list(st[0].data), [])  # no data
+
+        # 2 - little endian, 32 bit, version 7
+        fn = os.path.join(self.path, '2001-01-13-1742-24S.KONO__004')
+        st = _read_seisan(fn, headonly=True)
+        self.assertEqual(len(st), 4)
+        self.assertEqual(st[0].stats.network, '')
+        self.assertEqual(st[0].stats.station, 'KONO')
+        self.assertEqual(st[0].stats.location, '0')
+        self.assertEqual(st[0].stats.channel, 'B0Z')
+        self.assertEqual(st[0].stats.starttime,
+                         UTCDateTime(2001, 1, 13, 17, 45, 1, 999000))
+        self.assertEqual(st[0].stats.endtime,
+                         UTCDateTime(2001, 1, 13, 17, 50, 1, 949000))
+        self.assertEqual(st[0].stats.sampling_rate, 20.0)
+        self.assertEqual(st[0].stats.npts, 6000)
+        self.assertEqual(list(st[0].data), [])  # no data
+
+        # 3 - little endian, 32 bit, version 6, 1 channel
+        fn = os.path.join(self.path, 'D1360930.203')
+        st = _read_seisan(fn, headonly=True)
+        self.assertEqual(len(st), 1)
+        self.assertEqual(st[0].stats.network, '')
+        self.assertEqual(st[0].stats.station, 'mart')
+        self.assertEqual(st[0].stats.location, '1')
+        self.assertEqual(st[0].stats.channel, 'cp')
+        self.assertEqual(st[0].stats.starttime,
+                         UTCDateTime(2017, 7, 22, 9, 30))
+        self.assertEqual(st[0].stats.endtime,
+                         UTCDateTime(2017, 7, 22, 9, 31, 59, 990000))
+        self.assertEqual(st[0].stats.sampling_rate, 100.0)
+        self.assertEqual(st[0].stats.npts, 12000)
+        self.assertEqual(list(st[0].data), [])
+
+        # 4 - little endian, 32 bit, version 6, 3 channels
+        fn = os.path.join(self.path, '2005-07-23-1452-04S.CER___030')
+        st = _read_seisan(fn, headonly=True)
+        self.assertEqual(len(st), 3)
+        self.assertEqual(st[0].stats.channel, 'BHZ')
+        self.assertEqual(st[1].stats.channel, 'BHN')
+        self.assertEqual(st[2].stats.channel, 'BHE')
+        for i in range(0, 3):
+            self.assertEqual(st[i].stats.network, '')
+            self.assertEqual(st[i].stats.station, 'CER')
+            self.assertEqual(st[i].stats.location, '')
+            self.assertEqual(st[i].stats.starttime,
+                             UTCDateTime('2005-07-23T14:52:04.000000Z'))
+            self.assertEqual(st[i].stats.endtime,
+                             UTCDateTime('2005-07-23T14:53:14.993333Z'))
+            self.assertEqual(st[i].stats.sampling_rate, 150.0)
+            self.assertEqual(st[i].stats.npts, 10650)
+            self.assertEqual(list(st[i].data), [])
+
+    def test_read_obspy(self):
         """
-        Test for #970
+        Test ObsPy read function and compare against given MiniSEED files.
         """
-        _file = os.path.join(self.path, 'SEISAN_Bug',
-                             '2011-09-06-1311-36S.A1032_001BH_Z')
-        st = read(_file, format='SEISAN')
-        _file_ref = os.path.join(self.path, 'SEISAN_Bug',
-                                 '2011-09-06-1311-36S.A1032_001BH_Z_MSEED')
-
+        # 1 - little endian, 32 bit, version 7
+        st1 = read(os.path.join(self.path,
+                                '2011-09-06-1311-36S.A1032_001BH_Z'))
         # raises "UserWarning: Record contains a fractional seconds" - ignore
         with warnings.catch_warnings(record=True) as w:
             warnings.simplefilter('always', UserWarning)
-            st_ref = read(_file_ref, format='MSEED')
-        self.assertEqual(len(w), 1)
-        self.assertEqual(w[0].category, UserWarning)
-
-        self.assertTrue(np.allclose(st[0].data, st_ref[0].data))
+            st2 = read(os.path.join(self.path,
+                                    '2011-09-06-1311-36S.A1032_001BH_Z.mseed'))
+            self.assertEqual(len(w), 1)
+            self.assertEqual(w[0].category, UserWarning)
+        self.assertEqual(len(st1), len(st2))
+        self.assertTrue(np.allclose(st1[0].data, st2[0].data))
+
+        # 2 - little endian, 32 bit, version 6, 1 channel
+        st1 = read(os.path.join(self.path, 'D1360930.203'))
+        st2 = read(os.path.join(self.path, 'D1360930.203.mseed'))
+        self.assertEqual(len(st1), len(st2))
+        self.assertTrue(np.allclose(st1[0].data, st2[0].data))
+
+        # 3 - little endian, 32 bit, version 6, 3 channels
+        st1 = read(os.path.join(self.path, '2005-07-23-1452-04S.CER___030'))
+        st2 = read(os.path.join(self.path,
+                                '2005-07-23-1452-04S.CER___030.mseed'))
+        self.assertEqual(len(st1), len(st2))
+        self.assertTrue(np.allclose(st1[0].data, st2[0].data))
+        self.assertTrue(np.allclose(st1[1].data, st2[1].data))
+        self.assertTrue(np.allclose(st1[2].data, st2[2].data))
 
 
 def suite():