예제 #1
0
def metadata(f):
    """ Get survey structural properties and metadata

    Since v1.4

    Create a descriptor object that, when passed to `segyio.create()`, would
    create a new file with the same structure, dimensions and metadata as `f`.

    Takes an open segy file (created with segyio.open) or a file name.

    :type f: SegyFile|str
    :rtype segyio.spec
    """

    if not isinstance(f, segyio.SegyFile):
        with segyio.open(f) as fl:
            return metadata(fl)

    spec = segyio.spec()

    spec.iline = f._il
    spec.xline = f._xl
    spec.samples = f.samples
    spec.format = f.format

    spec.ilines = f.ilines
    spec.xlines = f.xlines
    spec.offsets = f.offsets
    spec.sorting = f.sorting

    spec.tracecount = f.tracecount

    spec.ext_headers = f.ext_headers

    return spec
예제 #2
0
def merge_segy_files(output_path, bar=True, **kwargs):
    """Merge segy files into a single segy file.

    Parameters
    ----------
    output_path : str
        Path to output file.
    bar : bool
        Whether to how progress bar (default = True).
    kwargs : dict
        Keyword arguments to index input segy files.

    Returns
    -------
    """
    segy_index = SegyFilesIndex(**kwargs, name='data')
    spec = segyio.spec()
    spec.sorting = None
    spec.format = 1
    spec.tracecount = sum(segy_index.tracecounts)
    with segyio.open(segy_index.indices[0], strict=False) as file:
        spec.samples = file.samples

    with segyio.create(output_path, spec) as dst:
        i = 0
        iterable = tqdm(segy_index.indices) if bar else segy_index.indices
        for index in iterable:
            with segyio.open(index, strict=False) as src:
                dst.trace[i:i + src.tracecount] = src.trace
                dst.header[i:i + src.tracecount] = src.header
                for j in range(src.tracecount):
                    dst.header[i + j].update(
                        {segyio.TraceField.TRACE_SEQUENCE_FILE: i + j + 1})

            i += src.tracecount
예제 #3
0
    def convert_to_segy(self, out_file):
        spec = segyio.spec()
        spec.samples = self.zslices
        spec.offsets = [0]
        spec.xlines = self.xlines
        spec.ilines = self.ilines
        spec.sorting = 2

        # seimcic-zfp stores the binary header from the source SEG-Y file.
        # In case someone forgot to do this, give them IEEE
        data_sample_format_code = bytes_to_int(
            self.headerbytes[DISK_BLOCK_BYTES + 3225:DISK_BLOCK_BYTES + 3227])
        if data_sample_format_code in [1, 5]:
            spec.format = data_sample_format_code
        else:
            spec.format = 5

        with warnings.catch_warnings():
            # segyio will warn us that out padded cube is not contiguous. This is expected, and safe.
            warnings.filterwarnings(
                "ignore", message="Implicit conversion to contiguous array")
            with segyio.create(out_file, spec) as segyfile:
                self.read_variant_headers()
                # Doing this is fine now there is decent caching on the loader
                segyfile.trace = [
                    self.get_trace(i) for i in range(len(segyfile.trace))
                ]
                segyfile.header = [
                    self.gen_trace_header(i)
                    for i in range(len(segyfile.header))
                ]

        with open(out_file, "r+b") as f:
            f.write(self.headerbytes[DISK_BLOCK_BYTES:DISK_BLOCK_BYTES +
                                     SEGY_FILE_HEADER_BYTES])
예제 #4
0
def learn7():
    read_path = 'E:/Research/data/F3_entire.segy'
    save_path = 'F:/test1.segy'
    col_num = 1000
    with segyio.open(read_path) as src:
        # ----- 输入数据处理
        input_list = src.trace.raw[:col_num]
        header_list = []
        for i1 in range(col_num):
            header_list.append(src.header[i1])
        # -----
        print('@ 开始保存新Segy文件,原文件共{0}条数据,单条长{1};新内容共{2}条数据,单条长{3}。'.format(
            len(src.trace), len(src.samples), len(input_list),
            len(input_list[0])),
              end='')
        spec = segyio.spec()
        spec.sorting = src.sorting
        spec.format = src.format
        spec.samples = input_list[0]
        spec.ilines = src.ilines
        spec.xlines = src.xlines
        spec.tracecount = len(input_list)
        print('SegyIO信息:src.tracecount={0},src.samples长度={1}。'.format(
            src.tracecount, len(src.samples)))
        with segyio.create(save_path, spec) as dst:
            dst.text[0] = src.text[0]
            dst.bin = src.bin
            dst.header = header_list
            dst.trace = input_list
    print('@ 提示:“{0}”文件已经写入完成'.format(save_path))
예제 #5
0
def main():
    if len(sys.argv) < 3:
        sys.exit("Usage: {} [source-file] [destination-file]".format(
            sys.argv[0]))

    sourcefile = sys.argv[1]
    destfile = sys.argv[2]

    with segyio.open(sourcefile) as src:
        spec = segyio.spec()
        spec.sorting = int(src.sorting)
        spec.format = int(src.format)
        spec.samples = 50
        spec.ilines = src.ilines[:5]
        spec.xlines = src.xlines[:5]

        with segyio.create(destfile, spec) as dst:
            # Copy all textual headers, including possible extended
            for i in range(1 + src.ext_headers):
                dst.text[i] = src.text[i]

            # copy the binary header, then insert the modifications needed for
            # the new shape
            dst.bin = src.bin
            dst.bin = {
                segyio.BinField.Samples: 50,
                segyio.BinField.Traces: 5 * 5
            }

            # Copy all headers in the new inlines. Since we know we're copying
            # the five first we don't have to take special care to update
            # headers
            dst.header.iline = src.header.iline
            # the copy traces (in line mode)
            dst.iline = src.iline
예제 #6
0
def main():
    if len(sys.argv) < 2:
        sys.exit('Usage: {} [output]'.format(sys.argv[0]))

    spec = segyio.spec()
    filename = sys.argv[1]

    spec.format = 1
    spec.samples = range(25)
    spec.tracecount = 61

    with segyio.create(filename, spec) as f:

        trno = 0
        keys = [2, 3, 5, 8]
        lens = [10, 12, 13, 26]

        for key, length in zip(keys, lens):
            for i in range(length):

                f.header[trno].update(
                    offset=1,
                    fldr=key,
                    grnofr=(i % 2) + 1,
                    tracf=spec.tracecount - i,
                )

                trace = np.linspace(start=key,
                                    stop=key + 1,
                                    num=len(spec.samples))
                f.trace[trno] = trace
                trno += 1

        f.bin.update()
예제 #7
0
    def test_create_sgy_shorter_traces(self):
        dstfile = self.filename.replace(".sgy", "-shorter.sgy")

        with segyio.open(self.filename, "r") as src:
            spec = segyio.spec()
            spec.format     = int(src.format)
            spec.sorting    = int(src.sorting)
            spec.samples    = 20 # reduces samples per trace
            spec.ilines     = src.ilines
            spec.xlines     = src.xlines

            with segyio.create(dstfile, spec) as dst:
                for i, srch in enumerate(src.header):
                    dst.header[i] = srch
                    d = { TraceField.INLINE_3D: srch[TraceField.INLINE_3D] + 100 }
                    dst.header[i] = d

                for lineno in dst.ilines:
                    dst.iline[lineno] = src.iline[lineno]

                # alternative form using left-hand-side slices
                dst.iline[2:4] = src.iline


                buf = None # reuse buffer for speed
                for lineno in dst.xlines:
                    dst.xline[lineno] = src.xline[lineno, buf]

            with segyio.open(dstfile, "r") as dst:
                self.assertEqual(20, dst.samples)
                self.assertEqual([x + 100 for x in src.ilines], list(dst.ilines))
예제 #8
0
    def convert_to_segy(self, out_file):
        # Currently only works for default SGZ layout (?)
        assert (self.blockshape[0] == 4)
        assert (self.blockshape[1] == 4)

        spec = segyio.spec()
        spec.samples = self.zslices
        spec.offsets = [0]
        spec.xlines = self.xlines
        spec.ilines = self.ilines
        spec.sorting = 2

        # seimcic-zfp stores the binary header from the source SEG-Y file.
        # In case someone forgot to do this, give them IEEE
        data_sample_format_code = bytes_to_int(
            self.headerbytes[DISK_BLOCK_BYTES+3225: DISK_BLOCK_BYTES+3227])
        if data_sample_format_code in [1, 5]:
            spec.format = data_sample_format_code
        else:
            spec.format = 5

        with warnings.catch_warnings():
            # segyio will warn us that out padded cube is not contiguous. This is expected, and safe.
            warnings.filterwarnings("ignore", message="Implicit conversion to contiguous array")
            with segyio.create(out_file, spec) as segyfile:
                self.read_variant_headers()
                for i, iline in enumerate(spec.ilines):
                    if i % self.blockshape[0] == 0:
                        decompressed = self.loader.read_and_decompress_il_set(i)
                    for h in range(i * len(spec.xlines), (i + 1) * len(spec.xlines)):
                        segyfile.header[h] = self.gen_trace_header(h)
                    segyfile.iline[iline] = decompressed[i % self.blockshape[0], 0:self.n_xlines, 0:self.n_samples]

        with open(out_file, "r+b") as f:
            f.write(self.headerbytes[DISK_BLOCK_BYTES: DISK_BLOCK_BYTES + SEGY_FILE_HEADER_BYTES])
def segy_write(data, sourceX, sourceZ, groupX, groupZ, dt, filename, sourceY=None, groupY=None, elevScalar=-1000, coordScalar=-1000):

    nt = data.shape[0]
    nxrec = len(groupX)
    if sourceY is None and groupY is None:
        sourceY = np.zeros(1, dtype='int')
        groupY = np.zeros(nxrec, dtype='int')

    # Create spec object
    spec = segyio.spec()
    spec.ilines = np.arange(nxrec)    # dummy trace count
    spec.xlines = np.zeros(1, dtype='int')  # assume coordinates are already vectorized for 3D
    spec.samples = range(nt)
    spec.format=1
    spec.sorting=1

    with segyio.create(filename, spec) as segyfile:
        for i in range(nxrec):
            segyfile.header[i] = {
                segyio.su.tracl : i+1,
                segyio.su.tracr : i+1,
                segyio.su.fldr : 1,
                segyio.su.tracf : i+1,
                segyio.su.sx : int(np.round(sourceX[0] * np.abs(coordScalar))),
                segyio.su.sy : int(np.round(sourceY[0] * np.abs(coordScalar))),
                segyio.su.selev: int(np.round(sourceZ[0] * np.abs(elevScalar))),
                segyio.su.gx : int(np.round(groupX[i] * np.abs(coordScalar))),
                segyio.su.gy : int(np.round(groupY[i] * np.abs(coordScalar))),
                segyio.su.gelev : int(np.round(groupZ[i] * np.abs(elevScalar))),
                segyio.su.dt : int(np.round(dt, decimals=6)*1e3),
                segyio.su.scalel : int(elevScalar),
                segyio.su.scalco : int(coordScalar)
            }
            segyfile.trace[i] = data[:, i]
        segyfile.dt=int(np.round(dt, decimals=6)*1e3)
예제 #10
0
def from_array_unstructured(
    filename: Path,
    data: np.ndarray,
    format: segyio.SegySampleFormat = segyio.SegySampleFormat.IBM_FLOAT_4_BYTE,
    dt: int = 4000,
    delrt: int = 0,
) -> None:
    dt = int(dt)
    delrt = int(delrt)
    data = np.asarray(data)
    dimensions = len(data.shape)
    if dimensions != 2:
        raise ValueError(f"Expected 2 dimensions, {dimensions} was given")

    spec = segyio.spec()
    spec.format = format
    spec.sorting = segyio.TraceSortingFormat.UNKNOWN_SORTING
    spec.tracecount = np.size(data, 0)
    spec.samples = list(range(np.size(data, 1)))
    samplecount = len(spec.samples)
    with segyio.create(filename, spec) as f:
        for tr in range(f.tracecount):
            f.header[tr] = {
                segyio.su.tracf: tr,
                segyio.su.cdpt: tr,
                segyio.su.ns: samplecount,
                segyio.su.dt: dt,
                segyio.su.delrt: delrt,
            }
            f.trace[tr] = data[tr, :]
        f.bin.update(tsort=spec.sorting, hdt=dt, dto=dt)
예제 #11
0
def make_subcube(path, geometry, path_save, i_range, x_range):
    """ Make subcube from .sgy cube by removing some of its first and
    last ilines and xlines.

    Parameters
    ----------
    path : str
        Location of original .sgy cube.
    geometry : SeismicGeometry
        Infered information about original cube.
    path_save : str
        Place to save subcube.
    i_range : array-like
        Ilines to include in subcube.
    x_range : array-like
        Xlines to include in subcube.

    Notes
    -----
    Common use of this function is to remove not fully filled slices of .sgy cubes.
    """

    i_low, i_high = i_range[0], i_range[-1]
    x_low, x_high = x_range[0], x_range[-1]

    with segyio.open(path, 'r', strict=False) as src:
        src.mmap()
        spec = segyio.spec()
        spec.sorting = int(src.sorting)
        spec.format = int(src.format)
        spec.samples = range(geometry.depth)
        spec.ilines = geometry.ilines[i_low:i_high]
        spec.xlines = geometry.xlines[x_low:x_high]

        with segyio.create(path_save, spec) as dst:
            # Copy all textual headers, including possible extended
            for i in range(1 + src.ext_headers):
                dst.text[i] = src.text[i]

            c = 0
            for il_ in tqdm(spec.ilines):
                for xl_ in spec.xlines:
                    tr_ = geometry.il_xl_trace[(il_, xl_)]
                    dst.header[c] = src.header[tr_]
                    dst.header[c][segyio.TraceField.FieldRecord] = il_
                    dst.header[c][segyio.TraceField.TRACE_SEQUENCE_FILE] = il_

                    dst.header[c][segyio.TraceField.
                                  TraceNumber] = xl_ - geometry.xlines_offset
                    dst.header[c][
                        segyio.TraceField.
                        TRACE_SEQUENCE_LINE] = xl_ - geometry.xlines_offset
                    dst.trace[c] = src.trace[tr_]
                    c += 1
            dst.bin = src.bin
            dst.bin = {segyio.BinField.Traces: c}

    # Check that repaired cube can be opened in 'strict' mode
    with segyio.open(path_save, 'r', strict=True) as _:
        pass
예제 #12
0
def test_create_sgy(small):
    orig = str(small.dirname + '/small.sgy')
    fresh = str(small.dirname + '/fresh.sgy')
    with segyio.open(orig) as src:
        spec = segyio.spec()
        spec.format = int(src.format)
        spec.sorting = int(src.sorting)
        spec.samples = src.samples
        spec.ilines = src.ilines
        spec.xlines = src.xlines

        with segyio.create(fresh, spec) as dst:
            dst.text[0] = src.text[0]
            dst.bin = src.bin

            # copy all headers
            dst.header = src.header

            for i, srctr in enumerate(src.trace):
                dst.trace[i] = srctr

            dst.trace = src.trace

            # this doesn't work yet, some restructuring is necessary
            # if it turns out to be a desired feature it's rather easy to do
            # for dsth, srch in zip(dst.header, src.header):
            #    dsth = srch

            # for dsttr, srctr in zip(dst.trace, src.trace):
            #    dsttr = srctr

    assert filecmp.cmp(orig, fresh)
예제 #13
0
def create_segy(path):
    """ Create file with data suitable for relevant tests.

    | xlines-ilines | 1             | 2             | 3             |
    |---------------|---------------|---------------|---------------|
    | 10            | 100, 101, 102 | 106, 107, 108 | 112, 113, 114 |
    | 11            | 103, 104, 105 | 109, 110, 111 | 115, 116, 177 |

    """
    spec = segyio.spec()

    spec.sorting = 2
    spec.format = 1
    spec.samples = [0, 1, 2]
    spec.ilines = [1, 2, 3]
    spec.xlines = [10, 11]

    with segyio.create(path, spec) as f:
        data = 100
        tr = 0
        for il in spec.ilines:
            for xl in spec.xlines:
                f.header[tr] = {segyio.su.iline: il, segyio.su.xline: xl}
                data = data + len(spec.samples)
                f.trace[tr] = np.arange(start=data - len(spec.samples),
                                        stop=data,
                                        step=1,
                                        dtype=np.single)
                tr += 1

        f.bin.update(tsort=segyio.TraceSortingFormat.INLINE_SORTING)
예제 #14
0
def mklines(fname):
    spec = segyio.spec()
    spec.format = 5
    spec.sorting = 2
    spec.samples = range(10)
    spec.ilines = range(1, 11)
    spec.xlines = range(1, 6)

    # create a file with 10 inlines, with values on the form l.0tv where
    # l = line no
    # t = trace number (within line)
    # v = trace value
    # i.e. 2.043 is the value at inline 2's fourth trace's third value
    with segyio.create(fname, spec) as dst:
        ln = np.arange(start=0,
                       stop=0.001 * (5 * 10),
                       step=0.001,
                       dtype=np.single).reshape(5, 10)

        for il in spec.ilines:
            ln += 1

            dst.header.iline[il] = {TraceField.INLINE_3D: il}
            dst.iline[il] = ln

        for xl in spec.xlines:
            dst.header.xline[xl] = {TraceField.CROSSLINE_3D: xl}
예제 #15
0
def test_create_sgy_skip_lines(tmpdir):
    mklines(tmpdir / "lines.sgy")

    with segyio.open(tmpdir / "lines.sgy") as src:
        spec = segyio.spec()
        spec.format = int(src.format)
        spec.sorting = int(src.sorting)
        spec.samples = src.samples
        spec.ilines = src.ilines[::2]
        spec.xlines = src.xlines[::2]

        with segyio.create(tmpdir / "lines-halved.sgy", spec) as dst:
            # use the inline headers as base
            dst.header.iline = src.header.iline[::2]
            # then update crossline numbers from the crossline headers
            for xl in dst.xlines:
                f = next(src.header.xline[xl])[TraceField.CROSSLINE_3D]
                dst.header.xline[xl] = {TraceField.CROSSLINE_3D: f}

            # but we override the last xline to be 6, not 5
            dst.header.xline[5] = {TraceField.CROSSLINE_3D: 6}
            dst.iline = src.iline[::2]

    with segyio.open(tmpdir / "lines-halved.sgy") as f:
        assert list(f.ilines) == list(spec.ilines)
        assert list(f.xlines) == [1, 3, 6]
        assert 1 == approx(f.iline[1][0][0], abs=1e-4)
        assert 3.004 == approx(f.iline[3][0][4], abs=1e-4)
        assert 3.014 == approx(f.iline[3][1][4], abs=1e-4)
        assert 7.023 == approx(f.iline[7][2][3], abs=1e-4)
예제 #16
0
def test_create_from_naught(tmpdir):
    spec = segyio.spec()
    spec.format = 5
    spec.sorting = 2
    spec.samples = range(150)
    spec.ilines = range(1, 11)
    spec.xlines = range(1, 6)

    with segyio.create(tmpdir / "mk.sgy", spec) as dst:
        tr = np.arange(start=1.000, stop=1.151, step=0.001, dtype=np.single)

        for i in range(len(dst.trace)):
            dst.trace[i] = tr
            tr += 1.000

        for il in spec.ilines:
            dst.header.iline[il] = {TraceField.INLINE_3D: il}

        for xl in spec.xlines:
            dst.header.xline[xl] = {TraceField.CROSSLINE_3D: xl}

        # Set header field 'offset' to 1 in all headers
        dst.header = {TraceField.offset: 1}

    with segyio.open(tmpdir / "mk.sgy") as f:
        assert 1 == approx(f.trace[0][0], abs=1e-4)
        assert 1.001 == approx(f.trace[0][1], abs=1e-4)
        assert 1.149 == approx(f.trace[0][-1], abs=1e-4)
        assert 50.100 == approx(f.trace[-1][100], abs=1e-4)
        assert f.header[0][TraceField.offset] == f.header[1][TraceField.offset]
        assert 1 == f.header[1][TraceField.offset]
예제 #17
0
def test_create_sgy_shorter_traces(small):
    orig = str(small.dirname + '/small.sgy')
    fresh = str(small.dirname + '/small_created_shorter.sgy')
    with segyio.open(orig) as src:
        spec = segyio.spec()
        spec.format = int(src.format)
        spec.sorting = int(src.sorting)
        spec.samples = src.samples[:20]  # reduces samples per trace
        spec.ilines = src.ilines
        spec.xlines = src.xlines

        with segyio.create(fresh, spec) as dst:
            for i, srch in enumerate(src.header):
                dst.header[i] = srch
                d = {TraceField.INLINE_3D: srch[TraceField.INLINE_3D] + 100}
                dst.header[i] = d

            for lineno in dst.ilines:
                dst.iline[lineno] = src.iline[lineno]

            # alternative form using left-hand-side slices
            dst.iline[2:4] = src.iline

            for lineno in dst.xlines:
                dst.xline[lineno] = src.xline[lineno]

        with segyio.open(fresh) as dst:
            assert 20 == len(dst.samples)
            assert [x + 100 for x in src.ilines] == list(dst.ilines)
예제 #18
0
    def test_create_sgy(self):
        with TestContext("create_sgy") as context:
            context.copy_file(self.filename)
            src_file = "small.sgy"
            dst_file = "small_created.sgy"
            with segyio.open(src_file, "r") as src:
                spec = segyio.spec()
                spec.format = int(src.format)
                spec.sorting = int(src.sorting)
                spec.samples = src.samples
                spec.ilines = src.ilines
                spec.xlines = src.xlines

                with segyio.create(dst_file, spec) as dst:
                    dst.text[0] = src.text[0]
                    dst.bin = src.bin

                    # copy all headers
                    dst.header = src.header

                    for i, srctr in enumerate(src.trace):
                        dst.trace[i] = srctr

                    dst.trace = src.trace

                    # this doesn't work yet, some restructuring is necessary
                    # if it turns out to be a desired feature it's rather easy to do
                    #for dsth, srch in zip(dst.header, src.header):
                    #    dsth = srch

                    #for dsttr, srctr in zip(dst.trace, src.trace):
                    #    dsttr = srctr

            self.assertTrue(filecmp.cmp(src_file, dst_file))
예제 #19
0
    def test_create_from_naught(self):
        fname = "test-data/mk.sgy"
        spec = segyio.spec()
        spec.format  = 5
        spec.sorting = 2
        spec.samples = 150
        spec.ilines  = range(1, 11)
        spec.xlines  = range(1, 6)

        with segyio.create(fname, spec) as dst:
            tr = np.arange( start = 1.000, stop = 1.151, step = 0.001, dtype = np.single)

            for i in xrange( len( dst.trace ) ):
                dst.trace[i] = tr
                tr += 1.000

            for il in spec.ilines:
                dst.header.iline[il] = { TraceField.INLINE_3D: il }

            for xl in spec.xlines:
                dst.header.xline[xl] = { TraceField.CROSSLINE_3D: xl }

            # Set header field 'offset' to 1 in all headers
            dst.header = { TraceField.offset: 1 }

        with segyio.open(fname, "r") as f:
            self.assertAlmostEqual(1,      f.trace[0][0],   places = 4)
            self.assertAlmostEqual(1.001,  f.trace[0][1],   places = 4)
            self.assertAlmostEqual(1.149,  f.trace[0][-1],   places = 4)
            self.assertAlmostEqual(50.100, f.trace[-1][100], places = 4)
            self.assertEqual(f.header[0][TraceField.offset], f.header[1][TraceField.offset])
            self.assertEqual(1, f.header[1][TraceField.offset])
예제 #20
0
    def test_create_sgy_skip_lines(self):
        fname = "lines.sgy"
        dstfile = "lines-halved.sgy"

        with TestContext("create_sgy_skip_lines") as context:
            mklines(fname)

            with segyio.open(fname, "r") as src:
                spec = segyio.spec()
                spec.format = int(src.format)
                spec.sorting = int(src.sorting)
                spec.samples = src.samples
                spec.ilines = src.ilines[::2]
                spec.xlines = src.xlines[::2]

                with segyio.create(dstfile, spec) as dst:
                    # use the inline headers as base
                    dst.header.iline = src.header.iline[::2]
                    # then update crossline numbers from the crossline headers
                    for xl in dst.xlines:
                        f = next(src.header.xline[xl])[TraceField.CROSSLINE_3D]
                        dst.header.xline[xl] = {TraceField.CROSSLINE_3D: f}

                    # but we override the last xline to be 6, not 5
                    dst.header.xline[5] = {TraceField.CROSSLINE_3D: 6}
                    dst.iline = src.iline[::2]

            with segyio.open(dstfile, "r") as f:
                self.assertListEqual(list(f.ilines), list(spec.ilines))
                self.assertListEqual(list(f.xlines), [1, 3, 6])
                self.assertAlmostEqual(1, f.iline[1][0][0], places=4)
                self.assertAlmostEqual(3.004, f.iline[3][0][4], places=4)
                self.assertAlmostEqual(3.014, f.iline[3][1][4], places=4)
                self.assertAlmostEqual(7.023, f.iline[7][2][3], places=4)
예제 #21
0
def setup_spec(tmpdir):
    spec = segyio.spec()
    spec.format = 5
    spec.sorting = 2
    spec.samples = range(0, 40, 4)
    spec.ilines = range(2)
    spec.xlines = range(2)
    yield spec
예제 #22
0
def create_temp_segy(n, test_file, skew=False):
    data = np.zeros((n, n, n))
    spec = segyio.spec()
    # to create a file from nothing, we need to tell segyio about the structure of
    # the file, i.e. its inline numbers, crossline numbers, etc. You can also add
    # more structural information, but offsets etc. have sensible defautls. This is
    # the absolute minimal specification for a N-by-M volume
    spec.sorting = 2
    spec.format = 1
    spec.iline = 189
    spec.xline = 193
    spec.samples = range(n)
    if skew:
        spec.ilines = range(n + n - 1)
    else:
        spec.ilines = range(n)
    spec.xlines = range(n)

    xl_val = range(n + 1, n + n + 1, 1)
    il_val = range(1, n + 1, 1)

    cdpx, cdpy = np.meshgrid(il_val, xl_val)

    if skew:
        for i, x in enumerate(cdpx):
            cdpx[i, :] = x + i

    with segyio.create(test_file, spec) as segyf:
        for i, (t, il, xl) in enumerate(
            zip(data.reshape(-1, n), cdpx.ravel(), cdpy.ravel())
        ):
            segyf.header[i] = {
                segyio.su.offset: 1,
                189: il,
                193: xl,
                segyio.su.cdpx: il * 1000,
                segyio.su.cdpy: xl * 1000,
                segyio.su.ns: n,
            }
            segyf.trace[i] = t
        segyf.bin.update(
            tsort=segyio.TraceSortingFormat.INLINE_SORTING,
            hdt=1000,
            mfeet=1,
            jobid=1,
            lino=1,
            reno=1,
            ntrpr=n * n,
            nart=n * n,
            fold=1,
        )

    if not skew:
        put_segy_texthead(test_file, create_default_texthead())
    else:
        put_segy_texthead(
            test_file, create_default_texthead(override={7: "Is Skewed Test"})
        )
예제 #23
0
def create_segy(path):
    """ Create file with data suitable for relevant tests.

    | xlines-ilines | 1             | 2             | 3             |
    |---------------|---------------|---------------|---------------|
    | 10            | 100, 101, 102 | 106, 107, 108 | 112, 113, 114 |
    | 11            | 103, 104, 105 | 109, 110, 111 | 115, 116, 177 |

    UTM coordinates for headers:

    | xlines-ilines | 1           | 2             | 3             |
    |---------------|-------------|---------------|---------------|
    | 10            | x=1, y=3    | x=2.1, y=3    | x=3.2, y=3    |
    | 11            | x=1, y=6.3  | x=2.1, y=6.3  | x=3.2, y=6.3  |
    """
    spec = segyio.spec()

    spec.sorting = 2
    spec.format = 1
    spec.samples = [0, 1, 2]
    spec.ilines = [1, 2, 3]
    spec.xlines = [10, 11]

    # We use scaling constant of -10, meaning that values will be divided by 10
    il_step_x = int(1.1 * 10)
    il_step_y = int(0 * 10)
    xl_step_x = int(0 * 10)
    xl_step_y = int(3.3 * 10)
    ori_x = int(1 * 10)
    ori_y = int(3 * 10)

    with segyio.create(path, spec) as f:
        data = 100
        tr = 0
        for il in spec.ilines:
            for xl in spec.xlines:
                f.header[tr] = {
                    segyio.su.iline:
                    il,
                    segyio.su.xline:
                    xl,
                    segyio.su.cdpx: (il - spec.ilines[0]) * il_step_x +
                    (xl - spec.xlines[0]) * xl_step_x + ori_x,
                    segyio.su.cdpy: (il - spec.ilines[0]) * il_step_y +
                    (xl - spec.xlines[0]) * xl_step_y + ori_y,
                    segyio.su.scalco:
                    -10,
                }
                data = data + len(spec.samples)
                f.trace[tr] = np.arange(start=data - len(spec.samples),
                                        stop=data,
                                        step=1,
                                        dtype=np.single)
                tr += 1

        f.bin.update(tsort=segyio.TraceSortingFormat.INLINE_SORTING)
예제 #24
0
def main():
    if len(sys.argv) < 9:
        sys.exit(" ".join(["Usage: {} [file] [samples]",
                           "[first iline] [last iline]",
                           "[first xline] [last xline]",
                           "[first offset] [last offset]"]
                         ).format(sys.argv[0]))

    spec = segyio.spec()
    filename = sys.argv[1]

    # to create a file from nothing, we need to tell segyio about the structure of
    # the file, i.e. its inline numbers, crossline numbers, etc. You can also add
    # more structural information, This is the absolute minimal specification for a
    # N-by-M volume with K offsets volume
    spec.sorting = 2
    spec.format = 1
    spec.samples = range(int(sys.argv[2]))
    spec.ilines = range(*map(int, sys.argv[3:5]))
    spec.xlines = range(*map(int, sys.argv[5:7]))
    spec.offsets = range(*map(int, sys.argv[7:9]))
    if len(spec.offsets) == 0: spec.offsets = [1]

    with segyio.create(filename, spec) as f:
        # one inline consists of 50 traces
        # which in turn consists of 2000 samples
        start = 0.0
        step = 0.00001
        # fill a trace with predictable values: left-of-comma is the inline
        # number. Immediately right of comma is the crossline number
        # the rightmost digits is the index of the sample in that trace meaning
        # looking up an inline's i's jth crosslines' k should be roughly equal
        # to (offset*100) + i.j0k.
        trace = np.arange(start = start,
                          stop  = start + step * len(spec.samples),
                          step  = step,
                          dtype = np.single)

        # Write the file trace-by-trace and update headers with iline, xline
        # and offset
        tr = 0
        for il in spec.ilines:
            for xl in spec.xlines:
                for off in spec.offsets:
                    f.header[tr] = {
                        segyio.su.offset : off,
                        segyio.su.iline  : il,
                        segyio.su.xline  : xl
                    }
                    f.trace[tr] = trace + (xl / 100.0) + il + (off * 100)
                    tr += 1

        f.bin.update(
            tsort=segyio.TraceSortingFormat.INLINE_SORTING
        )
예제 #25
0
def merge_segy_files(path, output_path, bar=True):
    """Merge segy files into a single segy file.

    Parameters
    ----------
    path : str or list of str
        Paths of files to merge, can use glob patterns
    output_path : str
        Path to output file.
    bar : bool
        Whether to how progress bar (default = True).

    """

    if len(path) == 0:
        raise ValueError("`path` cannot be empty.")

    if isinstance(path, str):
        path = (path, )

    files_list = [f for p in path for f in glob.iglob(p, recursive=True)]

    tracecounts = 0
    samples = None

    for fname in files_list:
        with segyio.open(fname, strict=False, ignore_geometry=True) as f:
            if samples is None:
                samples = f.samples
            else:
                if np.all(samples != f.samples):
                    raise ValueError(
                        "Inconsistent samples in files!" +
                        f"Samples is {f.samples} in {fname}, previous value was {samples}"
                    )
            tracecounts += f.tracecount

    spec = segyio.spec()
    spec.sorting = None
    spec.format = 1
    spec.tracecount = tracecounts
    spec.samples = samples

    with segyio.create(output_path, spec) as dst:
        i = 0
        iterable = tqdm(files_list) if bar else files_list
        for index in iterable:
            with segyio.open(index, strict=False, ignore_geometry=True) as src:
                dst.trace[i:i + src.tracecount] = src.trace
                dst.header[i:i + src.tracecount] = src.header
                for j in range(src.tracecount):
                    dst.header[i + j].update(
                        {segyio.TraceField.TRACE_SEQUENCE_FILE: i + j + 1})

            i += src.tracecount
예제 #26
0
def main():
    if len(sys.argv) < 9:
        sys.exit(" ".join(["Usage: {} [file] [samples]",
                           "[first iline] [last iline]",
                           "[first xline] [last xline]",
                           "[first offset] [last offset]"]
                         ).format(sys.argv[0]))

    spec = segyio.spec()
    filename = sys.argv[1]

    # to create a file from nothing, we need to tell segyio about the structure of
    # the file, i.e. its inline numbers, crossline numbers, etc. You can also add
    # more structural information, This is the absolute minimal specification for a
    # N-by-M volume with K offsets volume
    spec.sorting = 2
    spec.format = 1
    spec.samples = range(int(sys.argv[2]))
    spec.ilines = range(*map(int, sys.argv[3:5]))
    spec.xlines = range(*map(int, sys.argv[5:7]))
    spec.offsets = range(*map(int, sys.argv[7:9]))
    if len(spec.offsets) == 0: spec.offsets = [1]

    with segyio.create(filename, spec) as f:
        # one inline consists of 50 traces
        # which in turn consists of 2000 samples
        start = 0.0
        step = 0.00001
        # fill a trace with predictable values: left-of-comma is the inline
        # number. Immediately right of comma is the crossline number
        # the rightmost digits is the index of the sample in that trace meaning
        # looking up an inline's i's jth crosslines' k should be roughly equal
        # to (offset*100) + i.j0k.
        trace = np.arange(start = start,
                          stop  = start + step * len(spec.samples),
                          step  = step,
                          dtype = np.single)

        nx, no = len(spec.xlines), len(spec.offsets)
        # one inline is N traces concatenated. We fill in the xline number
        line = np.concatenate([trace + (xl / 100.0) for xl in spec.xlines])
        line = line.reshape( (nx, len(spec.samples)) )

        for ilindex, ilno in enumerate(spec.ilines):
            iline = line + ilno
            for tr, xlno in enumerate(spec.xlines):
                for offset_index, offset in enumerate(spec.offsets):
                    ix = (ilindex * nx * no) + (tr * no) + offset_index
                    f.trace[ix] = iline[tr] + (offset * 100)
                    f.header[ix] = { segyio.TraceField.INLINE_3D: ilno,
                                     segyio.TraceField.CROSSLINE_3D: xlno,
                                     segyio.TraceField.offset: offset }
예제 #27
0
def test_create_unstructured_hasattrs(tmpdir):
    spec = segyio.spec()
    spec.format = 5
    spec.samples = range(150)
    spec.tracecount = 50

    with segyio.create(tmpdir / "mk.sgy", spec) as dst:
        # accessing the sorting, inline and crossline attributes should work,
        # but not raise errors
        assert not dst.sorting
        assert not dst.ilines
        assert not dst.xlines
        assert dst.unstructured
예제 #28
0
    def create_segy():
        spec = segyio.spec()
        spec.format = 5
        spec.samples = [0, 1]
        spec.ilines = [1]
        spec.xlines = [1]
        spec.endian = "little"

        s1 = 3
        s2 = 5.5
        with segyio.create(path, spec) as f:
            f.header[0] = {segyio.su.iline: 1, segyio.su.xline: 1}
            f.trace[0] = [s1, s2]
예제 #29
0
def from_array_crossline(
    filename: Path,
    data: np.ndarray,
    iline: int = 189,
    xline: int = 193,
    format: segyio.SegySampleFormat = segyio.SegySampleFormat.IBM_FLOAT_4_BYTE,
    dt: int = 4000,
    delrt: int = 0,
) -> None:
    dt = int(dt)
    delrt = int(delrt)
    data = np.asarray(data)
    dimensions = len(data.shape)
    if dimensions not in range(3, 5):
        raise ValueError(f"Expected 3 or 4 dimensions, {dimensions} was given")

    spec = segyio.spec()
    spec.iline = iline
    spec.xline = xline
    spec.format = format
    spec.sorting = segyio.TraceSortingFormat.CROSSLINE_SORTING
    spec.ilines = list(range(1, np.size(data, 0) + 1))
    spec.xlines = list(range(1, np.size(data, 1) + 1))
    if dimensions == 3:
        spec.samples = list(range(np.size(data, 2)))
    else:
        spec.offsets = list(range(1, np.size(data, 2) + 1))
        spec.samples = list(range(np.size(data, 3)))

    samplecount = len(spec.samples)
    with segyio.create(filename, spec) as f:
        tr = 0
        for xlno, xl in enumerate(spec.xlines):
            for ilno, il in enumerate(spec.ilines):
                for offno, off in enumerate(spec.offsets):
                    f.header[tr] = {
                        segyio.su.tracf: tr,
                        segyio.su.cdpt: tr,
                        segyio.su.offset: off,
                        segyio.su.ns: samplecount,
                        segyio.su.dt: dt,
                        segyio.su.delrt: delrt,
                        segyio.su.iline: il,
                        segyio.su.xline: xl,
                    }
                    if dimensions == 3:
                        f.trace[tr] = data[ilno, xlno, :]
                    else:
                        f.trace[tr] = data[ilno, xlno, offno, :]
                    tr += 1
        f.bin.update(tsort=spec.sorting, hdt=dt, dto=dt)
예제 #30
0
def main():
    if len(sys.argv) < 7:
        sys.exit(
            "Usage: {} [file] [samples] [first iline] [last iline] [first xline] [last xline]"
            .format(sys.argv[0]))

    spec = segyio.spec()
    filename = sys.argv[1]

    # to create a file from nothing, we need to tell segyio about the structure of
    # the file, i.e. its inline numbers, crossline numbers, etc. You can also add
    # more structural information, but offsets etc. have sensible defautls. This is
    # the absolute minimal specification for a N-by-M volume
    spec.sorting = 2
    spec.format = 1
    spec.samples = range(int(sys.argv[2]))
    spec.ilines = range(*map(int, sys.argv[3:5]))
    spec.xlines = range(*map(int, sys.argv[5:7]))

    with segyio.create(filename, spec) as f:
        # one inline consists of 50 traces
        # which in turn consists of 2000 samples
        start = 0.0
        step = 0.00001
        # fill a trace with predictable values: left-of-comma is the inline
        # number. Immediately right of comma is the crossline number
        # the rightmost digits is the index of the sample in that trace meaning
        # looking up an inline's i's jth crosslines' k should be roughly equal
        # to i.j0k
        trace = np.arange(start=start,
                          stop=start + step * len(spec.samples),
                          step=step,
                          dtype=np.single)

        # one inline is N traces concatenated. We fill in the xline number
        line = np.concatenate([trace + (xl / 100.0) for xl in spec.xlines])
        line = line.reshape((len(spec.xlines), len(spec.samples)))

        # write the line itself to the file
        # write the inline number in all this line's headers
        for ilno in spec.ilines:
            f.iline[ilno] = (line + ilno)
            f.header.iline[ilno] = {
                segyio.TraceField.INLINE_3D: ilno,
                segyio.TraceField.offset: 1
            }

        # then do the same for xlines
        for xlno in spec.xlines:
            f.header.xline[xlno] = {segyio.TraceField.CROSSLINE_3D: xlno}