Exemplo n.º 1
0
def create(filename, spec):
    """Create a new segy file.

    Since v1.1

    Unstructured file creation since v1.4

    Create a new segy file with the geometry and properties given by `spec`.
    This enables creating SEGY files from your data. The created file supports
    all segyio modes, but has an emphasis on writing. The spec must be
    complete, otherwise an exception will be raised. A default, empty spec can
    be created with `segyio.spec()`.

    Very little data is written to the file, so just calling create is not
    sufficient to re-read the file with segyio. Rather, every trace header and
    trace must be written to for the file to be considered complete.

    Create should be used together with python's `with` statement. This ensure
    the data is written. Please refer to the examples.

    The `spec` is any object that has the following attributes:
        Mandatory:
            iline   (int/segyio.BinField)
            xline   (int/segyio.BinField)
            samples (array-like of int)
            format  (int), 1 = IBM float, 5 = IEEE float

        Exclusive:
            ilines  (array-like of int)
            xlines  (array-like of int)
            offsets (array-like of int)
            sorting (int/segyio.TraceSortingFormat)

            OR

            tracecount (int)

        Optional:
            ext_headers (int)

    The `segyio.spec()` function will default offsets and everything in the
    mandatory group, except format and samples, and requires the caller to fill
    in *all* the fields in either of the exclusive groups.

    If any field is missing from the first exclusive group, and the tracecount
    is set, the resulting file will be considered unstructured. If the
    tracecount is set, and all fields of the first exclusive group are
    specified, the file is considered structured and the tracecount is inferred
    from the xlines/ilines/offsets. The offsets are defaulted to [1] by
    `segyio.spec()`.

    Args:
        filename (str): Path to file to open.
        spec (:obj: `spec`): Structure of the segy file.

    Examples:
        Create a file::
            >>> spec = segyio.spec()
            >>> spec.ilines  = [1, 2, 3, 4]
            >>> spec.xlines  = [11, 12, 13]
            >>> spec.samples = list(range(50))
            >>> spec.sorting = 2
            >>> spec.format  = 1
            >>> with segyio.create(path, spec) as f:
            ...     ## fill the file with data
            ...

        Copy a file, but shorten all traces by 50 samples::
            >>> with segyio.open(srcpath) as src:
            ...     spec = segyio.spec()
            ...     spec.sorting = src.sorting
            ...     spec.format = src.format
            ...     spec.samples = src.samples[:len(src.samples) - 50]
            ...     spec.ilines = src.ilines
            ...     spec.xline = src.xlines
            ...     with segyio.create(dstpath, spec) as dst:
            ...         dst.text[0] = src.text[0]
            ...         dst.bin = src.bin
            ...         dst.header = src.header
            ...         dst.trace = src.trace

        Copy a file, but shorten all traces by 50 samples (since v1.4)::
            >>> with segyio.open(srcpath) as src:
            ...     spec = segyio.tools.metadata(src)
            ...     spec.samples = spec.samples[:len(spec.samples) - 50]
            ...     with segyio.create(dstpath, spec) as dst:
            ...         dst.text[0] = src.text[0]
            ...         dst.bin = src.bin
            ...         dst.header = src.header
            ...         dst.trace = src.trace
    :rtype: segyio.SegyFile
    """
    f = segyio.SegyFile(filename, "w+")

    f._samples = numpy.asarray(spec.samples, dtype=numpy.single)
    f._ext_headers = spec.ext_headers if hasattr(spec, 'ext_headers') else 0
    f._bsz = _segyio.trace_bsize(len(f.samples))

    txt_hdr_sz = _segyio.textheader_size()
    bin_hdr_sz = _segyio.binheader_size()
    f._tr0 = txt_hdr_sz + bin_hdr_sz + (f.ext_headers * txt_hdr_sz)
    f._fmt = int(spec.format)

    f._il = int(spec.iline)
    f._xl = int(spec.xline)

    if not structured(spec):
        f._tracecount = spec.tracecount
    else:
        f._sorting = spec.sorting
        f._offsets = numpy.copy(numpy.asarray(spec.offsets, dtype=numpy.intc))
        f._tracecount = len(spec.ilines) * len(spec.xlines) * len(spec.offsets)

        f._ilines = numpy.copy(numpy.asarray(spec.ilines, dtype=numpy.intc))
        f._xlines = numpy.copy(numpy.asarray(spec.xlines, dtype=numpy.intc))

        line_metrics = _segyio.init_line_metrics(f.sorting, f.tracecount,
                                                 len(f.ilines), len(f.xlines),
                                                 len(f.offsets))

        f._iline_length = line_metrics['iline_length']
        f._iline_stride = line_metrics['iline_stride']

        f._xline_length = line_metrics['xline_length']
        f._xline_stride = line_metrics['xline_stride']

    f.text[0] = default_text_header(f._il, f._xl, segyio.TraceField.offset)
    f.bin = {
        3213: f.tracecount,
        3217: 4000,
        3221: len(f.samples),
        3225: f.format,
        3505: f.ext_headers,
    }

    return f
Exemplo n.º 2
0
def create(filename, spec):
    """Create a new segy file.

    Since v1.1

    Create a new segy file with the geometry and properties given by `spec`.
    This enables creating SEGY files from your data. The created file supports
    all segyio modes, but has an emphasis on writing. The spec must be
    complete, otherwise an exception will be raised. A default, empty spec can
    be created with `segyio.spec()`.

    Very little data is written to the file, so just calling create is not
    sufficient to re-read the file with segyio. Rather, every trace header and
    trace must be written to for the file to be considered complete.

    Create should be used together with python's `with` statement. This ensure
    the data is written. Please refer to the examples.

    Args:
        filename (str): Path to file to open.
        spec (:obj: `spec`): Structure of the segy file.

    Examples:
        Create a file::
            >>> spec = segyio.spec()
            >>> spec.ilines  = [1, 2, 3, 4]
            >>> spec.xlines  = [11, 12, 13]
            >>> spec.samples = list(range(50))
            >>> spec.sorting = 2
            >>> spec.format  = 1
            >>> with segyio.create(path, spec) as f:
            ...     ## fill the file with data
            ...

        Copy a file, but shorten all traces by 50 samples::
            >>> with segyio.open(srcpath) as src:
            ...     spec = segyio.spec()
            ...     spec.sorting = src.sorting
            ...     spec.format = src.format
            ...     spec.samples = src.samples[:len(src.samples) - 50]
            ...     spec.ilines = src.ilines
            ...     spec.xline = src.xlines
            ...     with segyio.create(dstpath, spec) as dst:
            ...         dst.text[0] = src.text[0]
            ...         dst.bin = src.bin
            ...         dst.header = src.header
            ...         dst.trace = src.trace
    :rtype: segyio.SegyFile
    """
    f = segyio.SegyFile(filename, "w+")

    f._samples = numpy.asarray(spec.samples, dtype=numpy.single)
    f._ext_headers = spec.ext_headers
    f._bsz = _segyio.trace_bsize(len(f.samples))

    txt_hdr_sz = _segyio.textheader_size()
    bin_hdr_sz = _segyio.binheader_size()
    f._tr0 = txt_hdr_sz + bin_hdr_sz + (spec.ext_headers * txt_hdr_sz)
    f._sorting = spec.sorting
    f._fmt = int(spec.format)
    f._offsets = numpy.copy(numpy.asarray(spec.offsets, dtype=numpy.intc))
    f._tracecount = len(spec.ilines) * len(spec.xlines) * len(spec.offsets)

    f._il = int(spec.iline)
    f._ilines = numpy.copy(numpy.asarray(spec.ilines, dtype=numpy.intc))

    f._xl = int(spec.xline)
    f._xlines = numpy.copy(numpy.asarray(spec.xlines, dtype=numpy.intc))

    line_metrics = _segyio.init_line_metrics(f.sorting, f.tracecount,
                                             len(f.ilines), len(f.xlines),
                                             len(f.offsets))

    f._iline_length = line_metrics['iline_length']
    f._iline_stride = line_metrics['iline_stride']

    f._xline_length = line_metrics['xline_length']
    f._xline_stride = line_metrics['xline_stride']

    f.text[0] = default_text_header(f._il, f._xl, segyio.TraceField.offset)
    f.bin = {
        3213: f.tracecount,
        3217: 4000,
        3221: len(f.samples),
        3225: f.format,
        3505: f.ext_headers,
    }

    return f
Exemplo n.º 3
0
def open(filename,
         mode="r",
         iline=189,
         xline=193,
         strict=True,
         ignore_geometry=False):
    """Open a segy file.

    Opens a segy file and tries to figure out its sorting, inline numbers,
    crossline numbers, and offsets, and enables reading and writing to this
    file in a simple manner.

    For reading, the access mode "r" is preferred. All write operations will
    raise an exception. For writing, the mode "r+" is preferred (as "rw" would
    truncate the file). The modes used are standard C file modes; please refer
    to that documentation for a complete reference.

    Open should be used together with python's `with` statement. Please refer
    to the examples. When the `with` statement is used the file will
    automatically be closed when the routine completes or an exception is
    raised.

    By default, segyio tries to open in 'strict' mode. This means the file will
    be assumed to represent a geometry with consistent inline, crosslines and
    offsets. If strict is False, segyio will still try to establish a geometry,
    but it won't abort if it fails. When in non-strict mode is opened,
    geometry-dependent modes such as iline will raise an error.

    If 'ignore_geometry' is set to True, segyio will *not* try to build
    iline/xline or other geometry related structures, which leads to faster
    opens. This is essentially the same as using strict = False on a file that
    has no geometry.

    Args:
        filename (str): Path to file to open.
        mode (str, optional): File access mode, defaults to "r".
        iline (TraceField): Inline number field in the trace headers. Defaults
                            to 189 as per the SEGY specification.
        xline (TraceField): Crossline number field in the trace headers.
                            Defaults to 193 as per the SEGY specification.
        strict (bool, optional): Abort if a geometry cannot be inferred.
                                 Defaults to True.
        ignore_geometry (bool, optional): Opt out on building geometry
                                          information, useful for e.g. shot
                                          organised files. Defaults to False.

    Examples:
        Open a file in read-only mode::
            >>> with segyio.open(path, "r") as f:
            ...     print(f.ilines)
            ...

        Open a file in read-write mode::
            >>> with segyio.open(path, "r+") as f:
            ...     f.trace = np.arange(100)
            ...

        Open two files at once::
            >>> with segyio.open(path) as src, segyio.open(path, "r+") as dst:
            ...     dst.trace = src.trace # copy all traces from src to dst
            ...
    :rtype: segyio.SegyFile
    """
    f = segyio.SegyFile(filename, mode, iline, xline)

    try:
        metrics = segyio._segyio.init_metrics(f.xfd, f.bin.buf)

        f._tr0 = metrics['trace0']
        f._fmt = metrics['format']
        f._bsz = metrics['trace_bsize']
        f._tracecount = metrics['trace_count']
        f._ext_headers = (f._tr0 - 3600) // 3200  # should probably be from C

        dt = segyio.tools.dt(f, fallback_dt=4000.0)
        t0 = f.header[0][segyio.TraceField.DelayRecordingTime]
        sample_count = metrics['sample_count']
        f._samples = numpy.array([t0 + i * dt for i in range(sample_count)],
                                 dtype=numpy.single) / 1000.0

    except:
        f.close()
        raise

    if ignore_geometry:
        return f

    try:
        cube_metrics = segyio._segyio.init_cube_metrics(
            f.xfd, iline, xline, f.tracecount, f._tr0, f._bsz)
        f._sorting = cube_metrics['sorting']
        iline_count = cube_metrics['iline_count']
        xline_count = cube_metrics['xline_count']
        offset_count = cube_metrics['offset_count']
        metrics.update(cube_metrics)

        line_metrics = segyio._segyio.init_line_metrics(
            f.sorting, f.tracecount, iline_count, xline_count, offset_count)

        f._iline_length = line_metrics['iline_length']
        f._iline_stride = line_metrics['iline_stride']

        f._xline_length = line_metrics['xline_length']
        f._xline_stride = line_metrics['xline_stride']

        f._ilines = numpy.zeros(iline_count, dtype=numpy.intc)
        f._xlines = numpy.zeros(xline_count, dtype=numpy.intc)
        f._offsets = numpy.zeros(offset_count, dtype=numpy.intc)
        segyio._segyio.init_indices(f.xfd, metrics, f.ilines, f.xlines,
                                    f.offsets)

        if numpy.unique(f.ilines).size != f.ilines.size:
            raise ValueError(
                "Inlines inconsistent - expect all inlines to be unique")

        if numpy.unique(f.xlines).size != f.xlines.size:
            raise ValueError(
                "Crosslines inconsistent - expect all crosslines to be unique")

    except:
        if not strict:
            f._ilines = None
            f._xlines = None
            f._offsets = None
        else:
            f.close()
            raise

    return f
Exemplo n.º 4
0
def create(filename, spec):
    """Create a new segy file.

    Create a new segy file with the geometry and properties given by `spec`.
    This enables creating SEGY files from your data. The created file supports
    all segyio modes, but has an emphasis on writing. The spec must be
    complete, otherwise an exception will be raised. A default, empty spec can
    be created with ``segyio.spec()``.

    Very little data is written to the file, so just calling create is not
    sufficient to re-read the file with segyio. Rather, every trace header and
    trace must be written to the file to be considered complete.

    Create should be used together with python's ``with`` statement. This ensure
    the data is written. Please refer to the examples.

    The ``segyio.spec()`` function will default offsets and everything in the
    mandatory group, except format and samples, and requires the caller to fill
    in *all* the fields in either of the exclusive groups.

    If any field is missing from the first exclusive group, and the tracecount
    is set, the resulting file will be considered unstructured. If the
    tracecount is set, and all fields of the first exclusive group are
    specified, the file is considered structured and the tracecount is inferred
    from the xlines/ilines/offsets. The offsets are defaulted to ``[1]`` by
    ``segyio.spec()``.

    Parameters
    ----------
    filename : str
        Path to file to create
    spec : segyio.spec
        Structure of the segy file

    Returns
    -------
    file : segyio.SegyFile
        An open segyio file handle, similar to that returned by `segyio.open`

    See also
    --------
    segyio.spec : template for the `spec` argument


    Notes
    -----

    .. versionadded:: 1.1

    .. versionchanged:: 1.4
       Support for creating unstructured files

    The ``spec`` is any object that has the following attributes

    Mandatory::

        iline   : int or segyio.BinField
        xline   : int or segyio.BinField
        samples : array of int
        format  : { 1, 5 }
            1 = IBM float, 5 = IEEE float

    Exclusive::

        ilines  : array_like of int
        xlines  : array_like of int
        offsets : array_like of int
        sorting : int or segyio.TraceSortingFormat

        OR

        tracecount : int

    Optional::

        ext_headers : int


    Examples
    --------

    Create a file:

    >>> spec = segyio.spec()
    >>> spec.ilines  = [1, 2, 3, 4]
    >>> spec.xlines  = [11, 12, 13]
    >>> spec.samples = list(range(50))
    >>> spec.sorting = 2
    >>> spec.format  = 1
    >>> with segyio.create(path, spec) as f:
    ...     ## fill the file with data
    ...     pass
    ...

    Copy a file, but shorten all traces by 50 samples:

    >>> with segyio.open(srcpath) as src:
    ...     spec = segyio.spec()
    ...     spec.sorting = src.sorting
    ...     spec.format = src.format
    ...     spec.samples = src.samples[:len(src.samples) - 50]
    ...     spec.ilines = src.ilines
    ...     spec.xline = src.xlines
    ...     with segyio.create(dstpath, spec) as dst:
    ...         dst.text[0] = src.text[0]
    ...         dst.bin = src.bin
    ...         dst.header = src.header
    ...         dst.trace = src.trace

    Copy a file, but shorten all traces by 50 samples (since v1.4):

    >>> with segyio.open(srcpath) as src:
    ...     spec = segyio.tools.metadata(src)
    ...     spec.samples = spec.samples[:len(spec.samples) - 50]
    ...     with segyio.create(dstpath, spec) as dst:
    ...         dst.text[0] = src.text[0]
    ...         dst.bin = src.bin
    ...         dst.header = src.header
    ...         dst.trace = src.trace
    """


    if not structured(spec):
        tracecount = spec.tracecount
    else:
        tracecount = len(spec.ilines) * len(spec.xlines) * len(spec.offsets)

    ext_headers = spec.ext_headers if hasattr(spec, 'ext_headers') else 0
    samples = numpy.asarray(spec.samples, dtype = numpy.single)

    binary = bytearray(_segyio.binsize())
    _segyio.putfield(binary, 3217, 4000)
    _segyio.putfield(binary, 3221, len(samples))
    _segyio.putfield(binary, 3225, int(spec.format))
    _segyio.putfield(binary, 3505, int(ext_headers))

    f = segyio.SegyFile(str(filename), "w+", tracecount = tracecount,
                                             binary = binary)

    f._il            = int(spec.iline)
    f._xl            = int(spec.xline)
    f._samples       = samples

    if structured(spec):
        f._sorting       = spec.sorting
        f._offsets       = numpy.copy(numpy.asarray(spec.offsets, dtype = numpy.intc))

        f._ilines        = numpy.copy(numpy.asarray(spec.ilines, dtype=numpy.intc))
        f._xlines        = numpy.copy(numpy.asarray(spec.xlines, dtype=numpy.intc))

        line_metrics = _segyio.line_metrics(f.sorting,
                                            tracecount,
                                            len(f.ilines),
                                            len(f.xlines),
                                            len(f.offsets))

        f._iline_length = line_metrics['iline_length']
        f._iline_stride = line_metrics['iline_stride']

        f._xline_length = line_metrics['xline_length']
        f._xline_stride = line_metrics['xline_stride']

    f.text[0] = default_text_header(f._il, f._xl, segyio.TraceField.offset)
    f.xfd.putbin(binary)

    return f
Exemplo n.º 5
0
def open(filename,
         mode="r",
         iline=189,
         xline=193,
         strict=True,
         ignore_geometry=False):
    """Open a segy file.

    Opens a segy file and tries to figure out its sorting, inline numbers,
    crossline numbers, and offsets, and enables reading and writing to this
    file in a simple manner.

    For reading, the access mode `r` is preferred. All write operations will
    raise an exception. For writing, the mode `r+` is preferred (as `rw` would
    truncate the file). Any mode with `w` will raise an error. The modes used
    are standard C file modes; please refer to that documentation for a
    complete reference.

    Open should be used together with python's ``with`` statement. Please refer
    to the examples. When the ``with`` statement is used the file will
    automatically be closed when the routine completes or an exception is
    raised.

    By default, segyio tries to open in ``strict`` mode. This means the file will
    be assumed to represent a geometry with consistent inline, crosslines and
    offsets. If strict is False, segyio will still try to establish a geometry,
    but it won't abort if it fails. When in non-strict mode is opened,
    geometry-dependent modes such as iline will raise an error.

    If ``ignore_geometry=True``, segyio will *not* try to build iline/xline or
    other geometry related structures, which leads to faster opens. This is
    essentially the same as using ``strict=False`` on a file that has no
    geometry.

    Parameters
    ----------

    filename : str
        Path to file to open

    mode : {'r', 'r+'}
        File access mode, read-only ('r', default) or read-write ('r+')

    iline : int or segyio.TraceField
        Inline number field in the trace headers. Defaults to 189 as per the
        SEG-Y rev1 specification

    xline : int or segyio.TraceField
        Crossline number field in the trace headers. Defaults to 193 as per the
        SEG-Y rev1 specification

    strict : bool, optional
        Abort if a geometry cannot be inferred. Defaults to True.

    ignore_geometry : bool, optional
        Opt out on building geometry information, useful for e.g. shot
        organised files. Defaults to False.

    Returns
    -------

    file : segyio.SegyFile
        An open segyio file handle

    Raises
    ------

    ValueError
        If the mode string contains 'w', as it would truncate the file

    Notes
    -----

    .. versionadded:: 1.1

    When a file is opened non-strict, only raw traces access is allowed, and
    using modes such as ``iline`` raise an error.


    Examples
    --------

    Open a file in read-only mode:

    >>> with segyio.open(path, "r") as f:
    ...     print(f.ilines)
    ...
    [1, 2, 3, 4, 5]

    Open a file in read-write mode:

    >>> with segyio.open(path, "r+") as f:
    ...     f.trace = np.arange(100)


    Open two files at once:

    >>> with segyio.open(path) as src, segyio.open(path, "r+") as dst:
    ...     dst.trace = src.trace # copy all traces from src to dst


    """

    if 'w' in mode:
        problem = 'w in mode would truncate the file'
        solution = 'use r+ to open in read-write'
        raise ValueError(', '.join((problem, solution)))

    f = segyio.SegyFile(str(filename), mode, iline, xline)
    metrics = f.xfd.metrics()

    try:
        dt = segyio.tools.dt(f, fallback_dt=4000.0) / 1000.0
        t0 = f.header[0][segyio.TraceField.DelayRecordingTime]
        samples = metrics['samplecount']
        f._samples = (numpy.arange(samples) * dt) + t0

    except:
        f.close()
        raise

    if ignore_geometry:
        return f

    try:
        cube_metrics = f.xfd.cube_metrics(iline, xline)
        f._sorting = cube_metrics['sorting']
        iline_count = cube_metrics['iline_count']
        xline_count = cube_metrics['xline_count']
        offset_count = cube_metrics['offset_count']
        metrics.update(cube_metrics)

        line_metrics = segyio._segyio.line_metrics(f.sorting, f.tracecount,
                                                   iline_count, xline_count,
                                                   offset_count)

        f._iline_length = line_metrics['iline_length']
        f._iline_stride = line_metrics['iline_stride']

        f._xline_length = line_metrics['xline_length']
        f._xline_stride = line_metrics['xline_stride']

        f._ilines = numpy.zeros(iline_count, dtype=numpy.intc)
        f._xlines = numpy.zeros(xline_count, dtype=numpy.intc)
        f._offsets = numpy.zeros(offset_count, dtype=numpy.intc)
        f.xfd.indices(metrics, f.ilines, f.xlines, f.offsets)

        if numpy.unique(f.ilines).size != f.ilines.size:
            raise ValueError(
                "Inlines inconsistent - expect all inlines to be unique")

        if numpy.unique(f.xlines).size != f.xlines.size:
            raise ValueError(
                "Crosslines inconsistent - expect all crosslines to be unique")

    except:
        if not strict:
            f._ilines = None
            f._xlines = None
            f._offsets = None
        else:
            f.close()
            raise

    return f
Exemplo n.º 6
0
def create(filename, spec):
    """Create a new segy file.

    Create a new segy file with the geometry and properties given by `spec`.
    This enables creating SEGY files from your data. The created file supports
    all segyio modes, but has an emphasis on writing. The spec must be
    complete, otherwise an exception will be raised. A default, empty spec can
    be created with ``segyio.spec()``.

    Very little data is written to the file, so just calling create is not
    sufficient to re-read the file with segyio. Rather, every trace header and
    trace must be written to the file to be considered complete.

    Create should be used together with python's ``with`` statement. This ensure
    the data is written. Please refer to the examples.

    The ``segyio.spec()`` function will default sorting, offsets and everything
    in the mandatory group, except format and samples, and requires the caller
    to fill in *all* the fields in either of the exclusive groups.

    If any field is missing from the first exclusive group, and the tracecount
    is set, the resulting file will be considered unstructured. If the
    tracecount is set, and all fields of the first exclusive group are
    specified, the file is considered structured and the tracecount is inferred
    from the xlines/ilines/offsets. The offsets are defaulted to ``[1]`` by
    ``segyio.spec()``.

    Parameters
    ----------
    filename : str
        Path to file to create
    spec : segyio.spec
        Structure of the segy file

    Returns
    -------
    file : segyio.SegyFile
        An open segyio file handle, similar to that returned by `segyio.open`

    See also
    --------
    segyio.spec : template for the `spec` argument


    Notes
    -----

    .. versionadded:: 1.1

    .. versionchanged:: 1.4
       Support for creating unstructured files

    .. versionchanged:: 1.8
       Support for creating lsb files

    The ``spec`` is any object that has the following attributes

    Mandatory::

        iline   : int or segyio.BinField
        xline   : int or segyio.BinField
        samples : array of int
        format  : { 1, 5 }
            1 = IBM float, 5 = IEEE float

    Exclusive::

        ilines  : array_like of int
        xlines  : array_like of int
        offsets : array_like of int
        sorting : int or segyio.TraceSortingFormat

        OR

        tracecount : int

    Optional::

        ext_headers : int
        endian : str { 'big', 'msb', 'little', 'lsb' }
            defaults to 'big'


    Examples
    --------

    Create a file:

    >>> spec = segyio.spec()
    >>> spec.ilines  = [1, 2, 3, 4]
    >>> spec.xlines  = [11, 12, 13]
    >>> spec.samples = list(range(50))
    >>> spec.sorting = 2
    >>> spec.format  = 1
    >>> with segyio.create(path, spec) as f:
    ...     ## fill the file with data
    ...     pass
    ...

    Copy a file, but shorten all traces by 50 samples:

    >>> with segyio.open(srcpath) as src:
    ...     spec = segyio.spec()
    ...     spec.sorting = src.sorting
    ...     spec.format = src.format
    ...     spec.samples = src.samples[:len(src.samples) - 50]
    ...     spec.ilines = src.ilines
    ...     spec.xline = src.xlines
    ...     with segyio.create(dstpath, spec) as dst:
    ...         dst.text[0] = src.text[0]
    ...         dst.bin = src.bin
    ...         dst.header = src.header
    ...         dst.trace = src.trace

    Copy a file, but shorten all traces by 50 samples (since v1.4):

    >>> with segyio.open(srcpath) as src:
    ...     spec = segyio.tools.metadata(src)
    ...     spec.samples = spec.samples[:len(spec.samples) - 50]
    ...     with segyio.create(dstpath, spec) as dst:
    ...         dst.text[0] = src.text[0]
    ...         dst.bin = src.bin
    ...         dst.header = src.header
    ...         dst.trace = src.trace
    """

    from . import _segyio

    if not structured(spec):
        tracecount = spec.tracecount
    else:
        tracecount = len(spec.ilines) * len(spec.xlines) * len(spec.offsets)

    ext_headers = spec.ext_headers if hasattr(spec, 'ext_headers') else 0
    samples = numpy.asarray(spec.samples)

    endians = {
        'lsb': 256,  # (1 << 8)
        'little': 256,
        'msb': 0,
        'big': 0,
    }
    endian = spec.endian if hasattr(spec, 'endian') else 'big'
    if endian is None:
        endian = 'big'

    if endian not in endians:
        problem = 'unknown endianness {}, expected one of: '
        opts = ' '.join(endians.keys())
        raise ValueError(problem.format(endian) + opts)

    fd = _segyio.segyiofd(str(filename), 'w+', endians[endian])
    fd.segymake(
        samples=len(samples),
        tracecount=tracecount,
        format=int(spec.format),
        ext_headers=int(ext_headers),
    )

    f = segyio.SegyFile(
        fd,
        filename=str(filename),
        mode='w+',
        iline=int(spec.iline),
        xline=int(spec.xline),
        endian=endian,
    )

    f._samples = samples

    if structured(spec):
        sorting = spec.sorting if hasattr(spec, 'sorting') else None
        if sorting is None:
            sorting = TraceSortingFormat.INLINE_SORTING
        f.interpret(spec.ilines, spec.xlines, spec.offsets, sorting)

    f.text[0] = default_text_header(f._il, f._xl, segyio.TraceField.offset)

    if len(samples) == 1:
        interval = int(samples[0] * 1000)
    else:
        interval = int((samples[1] - samples[0]) * 1000)

    f.bin.update(
        ntrpr=tracecount,
        nart=tracecount,
        hdt=interval,
        dto=interval,
        hns=len(samples),
        nso=len(samples),
        format=int(spec.format),
        exth=ext_headers,
    )

    return f
Exemplo n.º 7
0
def open(filename, mode="r", iline=189, xline=193):
    """Open a segy file.

    Opens a segy file and tries to figure out its sorting, inline numbers,
    crossline numbers, and offsets, and enables reading and writing to this
    file in a simple manner.

    For reading, the access mode "r" is preferred. All write operations will
    raise an exception. For writing, the mode "r+" is preferred (as "rw" would
    truncate the file). The modes used are standard C file modes; please refer
    to that documentation for a complete reference.

    Open should be used together with python's `with` statement. Please refer
    to the examples. When the `with` statement is used the file will
    automatically be closed when the routine completes or an exception is
    raised.

    Args:
        filename (str): Path to file to open.
        mode (str, optional): File access mode, defaults to "r".
        iline (TraceField): Inline number field in the trace headers. Defaults
                            to 189 as per the SEGY specification.
        xline (TraceField): Crossline number field in the trace headers.
                            Defaults to 193 as per the SEGY specification.

    Examples:
        Open a file in read-only mode::
            >>> with segyio.open(path, "r") as f:
            ...     print(f.ilines)
            ...

        Open a file in read-write mode::
            >>> with segyio.open(path, "r+") as f:
            ...     f.trace = np.arange(100)
            ...

        Open two files at once::
            >>> with segyio.open(path) as src, segyio.open(path, "r+") as dst:
            ...     dst.trace = src.trace # copy all traces from src to dst
            ...
    :rtype: segyio.SegyFile
    """
    f = segyio.SegyFile(filename, mode, iline, xline)

    try:
        header = f.bin.buf
        metrics = segyio._segyio.init_metrics(f.xfd, header, iline, xline)

        f._samples = metrics['sample_count']
        f._tr0 = metrics['trace0']
        f._fmt = metrics['format']
        f._bsz = metrics['trace_bsize']
        f._ext_headers = (f._tr0 - 3600) / 3200  # should probably be from C

        f._tracecount = metrics['trace_count']

        f._sorting = metrics['sorting']
        f._offsets = metrics['offset_count']

        iline_count, xline_count = metrics['iline_count'], metrics[
            'xline_count']

        line_metrics = segyio._segyio.init_line_metrics(
            f.sorting, f.tracecount, iline_count, xline_count, f.offsets)

        f._ilines = numpy.zeros(iline_count, dtype=numpy.uintc)
        f._xlines = numpy.zeros(xline_count, dtype=numpy.uintc)
        segyio._segyio.init_line_indices(f.xfd, metrics, f.ilines, f.xlines)

        f._iline_length = line_metrics['iline_length']
        f._iline_stride = line_metrics['iline_stride']

        f._xline_length = line_metrics['xline_length']
        f._xline_stride = line_metrics['xline_stride']

    except:
        f.close()
        raise

    return f
Exemplo n.º 8
0
def open(filename,
         mode="r",
         iline=189,
         xline=193,
         strict=True,
         ignore_geometry=False,
         endian='big'):
    """Open a segy file.

    Opens a segy file and tries to figure out its sorting, inline numbers,
    crossline numbers, and offsets, and enables reading and writing to this
    file in a simple manner.

    For reading, the access mode `r` is preferred. All write operations will
    raise an exception. For writing, the mode `r+` is preferred (as `rw` would
    truncate the file). Any mode with `w` will raise an error. The modes used
    are standard C file modes; please refer to that documentation for a
    complete reference.

    Open should be used together with python's ``with`` statement. Please refer
    to the examples. When the ``with`` statement is used the file will
    automatically be closed when the routine completes or an exception is
    raised.

    By default, segyio tries to open in ``strict`` mode. This means the file will
    be assumed to represent a geometry with consistent inline, crosslines and
    offsets. If strict is False, segyio will still try to establish a geometry,
    but it won't abort if it fails. When in non-strict mode is opened,
    geometry-dependent modes such as iline will raise an error.

    If ``ignore_geometry=True``, segyio will *not* try to build iline/xline or
    other geometry related structures, which leads to faster opens. This is
    essentially the same as using ``strict=False`` on a file that has no
    geometry.

    Parameters
    ----------

    filename : str
        Path to file to open

    mode : {'r', 'r+'}
        File access mode, read-only ('r', default) or read-write ('r+')

    iline : int or segyio.TraceField
        Inline number field in the trace headers. Defaults to 189 as per the
        SEG-Y rev1 specification

    xline : int or segyio.TraceField
        Crossline number field in the trace headers. Defaults to 193 as per the
        SEG-Y rev1 specification

    strict : bool, optional
        Abort if a geometry cannot be inferred. Defaults to True.

    ignore_geometry : bool, optional
        Opt out on building geometry information, useful for e.g. shot
        organised files. Defaults to False.

    endian : {'big', 'msb', 'little', 'lsb'}
        File endianness, big/msb (default) or little/lsb

    Returns
    -------

    file : segyio.SegyFile
        An open segyio file handle

    Raises
    ------

    ValueError
        If the mode string contains 'w', as it would truncate the file

    Notes
    -----

    .. versionadded:: 1.1

    .. versionchanged:: 1.8
        endian argument

    When a file is opened non-strict, only raw traces access is allowed, and
    using modes such as ``iline`` raise an error.


    Examples
    --------

    Open a file in read-only mode:

    >>> with segyio.open(path, "r") as f:
    ...     print(f.ilines)
    ...
    [1, 2, 3, 4, 5]

    Open a file in read-write mode:

    >>> with segyio.open(path, "r+") as f:
    ...     f.trace = np.arange(100)

    Open two files at once:

    >>> with segyio.open(path) as src, segyio.open(path, "r+") as dst:
    ...     dst.trace = src.trace # copy all traces from src to dst

    Open a file little-endian file:

    >>> with segyio.open(path, endian = 'little') as f:
    ...     f.trace[0]

    """

    if 'w' in mode:
        problem = 'w in mode would truncate the file'
        solution = 'use r+ to open in read-write'
        raise ValueError(', '.join((problem, solution)))

    endians = {
        'little': 256,  # (1 << 8)
        'lsb': 256,
        'big': 0,
        'msb': 0,
    }

    if endian not in endians:
        problem = 'unknown endianness {}, expected one of: '
        opts = ' '.join(endians.keys())
        raise ValueError(problem.format(endian) + opts)

    from . import _segyio
    fd = _segyio.segyiofd(str(filename), mode, endians[endian])
    fd.segyopen()
    metrics = fd.metrics()

    f = segyio.SegyFile(
        fd,
        filename=str(filename),
        mode=mode,
        iline=iline,
        xline=xline,
        endian=endian,
    )

    try:
        dt = segyio.tools.dt(f, fallback_dt=4000.0) / 1000.0
        t0 = f.header[0][segyio.TraceField.DelayRecordingTime]
        samples = metrics['samplecount']
        f._samples = (numpy.arange(samples) * dt) + t0

    except:
        f.close()
        raise

    if ignore_geometry:
        return f

    return infer_geometry(f, metrics, iline, xline, strict)