# Source code for obspy.io.gcf.core

    # -*- coding: utf-8 -*-
    """
    GCF bindings to ObsPy core module.
    """
    from __future__ import (absolute_import, division, print_function,
                            unicode_literals)
    from future.builtins import *  # NOQA

    from obspy import Stream, Trace, UTCDateTime

    from . import libgcf

    def merge_gcf_stream(st):
        """
        Merges GCF stream (replacing Stream.merge(-1) for headonly=True)

        :type st: :class:`~obspy.core.stream.Stream`
        :param st: GCF Stream object whith no data
        :rtype: :class:`~obspy.core.stream.Stream`
        :returns: Stream object containing header and data.
        """
        traces = []
        for tr in st:
            delta = tr.stats.delta
            starttime = tr.stats.starttime
            endtime = tr.stats.endtime
            for trace in traces:
                if tr.id == trace.id and delta == trace.stats.delta \
                   and not starttime == trace.stats.starttime:
                    if 0 < starttime - trace.stats.endtime <= delta:
                        trace.stats.npts += tr.stats.npts
                        break
                    elif 0 < trace.stats.starttime - endtime <= delta:
                        trace.stats.starttime = UTCDateTime(starttime)
                        trace.stats.npts += tr.stats.npts
                        break
            else:
                traces.append(tr)
        return Stream(traces=traces)

    def _is_gcf(filename):
        """
        Checks whether a file is GCF or not.

        :type filename: str
        :param filename: GCF file to be checked.
        :rtype: bool
        :return: ``True`` if a GCF file.
        """
        try:
            with open(filename, 'rb') as f:
                libgcf.is_gcf(f)
        except Exception:
            return False
        return True

    def _read_gcf(filename, headonly=False, **kwargs):  # @UnusedVariable
        """
        Reads a GCF file and returns a Stream object.

        only GCF files containing data records are supported.

        .. warning::
            This function should NOT be called directly, it registers via the
            ObsPy :func:`~obspy.core.stream.read` function, call this instead.

        :type filename: str
        :param filename: GCF file to be read.
        :type headonly: bool, optional
        :param headonly: If True read only head of GCF file.
        :type channel_prefix: str, optional
        :param channel_prefix: Channel band and instrument codes.
            Defaults to ``HH``.
        :rtype: :class:`~obspy.core.stream.Stream`
        :returns: Stream object containing header and data.

        .. rubric:: Example
        >>> from obspy import read
        >>> st = read("/path/to/20160603_1955n.gcf", format="GCF")
        """
        traces = []
        with open(filename, 'rb') as f:
            while True:
                try:
                    if headonly:
                        header = libgcf.read_header(f, **kwargs)
                        if header:
                            traces.append(Trace(header=header))
                    else:
                        hd = libgcf.read(f, **kwargs)
                        if hd:
                            traces.append(Trace(header=hd[0], data=hd[1]))
                except EOFError:
                    break
        st = Stream(traces=traces)
        if headonly:
            st = merge_gcf_stream(st)
        else:
            st.merge(-1)
        return st

### Thank you!

We would like to thank our contributors, whose efforts make this software what it is. These people have helped by writing code and documentation, and by testing. They have created and maintained this product, its associated libraries and applications, our build tools and our web sites.

#### Contributors

- Ackerley, Nick
- Allgeyer, Sebastien
- Ammon, Charles J.
- Antunes, Emanuel
- Arnarsson, Ólafur St.
- Bank, Markus
- Barsch, Robert
- Behr, Yannik
- Bernardi, Fabrizio
- Bernauer, Felix
- Bes de Berc, Maxime
- Beyreuther, Moritz
- Boltz, Shawn
- Bonaimé, Sébastien
- Carothers, Lloyd
- Chamberlain, Calum
- Chambers, Derrick
- Chen, Zhao
- Clark, Adam
- Danecek, Peter
- Egdorf, Sven
- Engels, Fabian
- Ermert, Laura
- Eulenfeld, Tom

- Fabbri, Tommaso
- Falco, Nicholas
- Fee, Jeremy
- Grellier, Clément
- Grunberg, Marc
- Hammer, Conny
- Heimann, Sebastian
- Heiniger, Lukas
- Hope, Gaute
- Igel, Heiner
- Inza, Adolfo
- Isken, Marius
- Ketchum, David
- Koymans, Mathijs
- Kremers, Simon
- Kress, Victor
- Krieger, Lars
- Krischer, Lion
- Kula, Damian
- Käufl, Paul
- Köhler, Andreas
- Lecocq, Thomas
- Leeman, John
- Legovini, Paride

- Lesage, Philippe
- Li, Yulin
- Lomax, Anthony
- Lopes, Rui L.
- MacCarthy, Jonathan
- Maggi, Alessia
- Martin, Henri
- Medlin, Andrew
- Megies, Tobias
- Meschede, Matthias
- Michelini, Alberto
- Miller, Nathaniel C.
- Morgenstern, Bernhard
- Nof, Ran Novitsky
- Panning, Mark P.
- Parker, Tom
- Pestourie, Romain
- Rapagnani, Giovanni
- Reyes, Celso
- Ringler, Adam
- Rothenhäusler, Nicolas
- Russo, Emiliano
- Sales de Andrade, Elliott

- Satriano, Claudio
- Saul, Joachim
- Scheingraber, Chris
- Schneider, Simon
- Sippl, Christian
- Snoke, Arthur
- Stange, Stefan
- Stähler, Simon C.
- Sullivan, Benjamin
- Tian, Dongdong
- Trabant, Chad
- Trani, Luca
- Uieda, Leonardo
- Walker, Andrew
- Walther, Marcus
- Wassermann, Joachim
- Williams, Mark C.
- Winkelman, Andrew
- Zaccarelli, Riccardo
- Zad, Seyed Kasra Hosseini
- Zhu, Lijun
- van Driel, Martin
- van Wijk, Kasper

#### Funds

ObsPy was partially funded by the

- German Science Foundation (DFG) via grant DFG IG 16/9-1
- German Ministry for Education and Research (BMBF), GEOTECHNOLOGIEN grant 03G0646H.
- NERA project (Network of European Research Infrastructures for Earthquake Risk Assessment and Mitigation) under the European Community's Seventh Framework Programme (FP7/2007-2013) grant agreement n° 262330
- Leibniz Institute for Applied Geophysics (LIAG)
- VERCE EU-FP7 project (no. 283543)