def depth(self, depth): "data of a depth slice" depth_idx = int((depth - self.startDepth) // self.stepDepth) with segyio.open(self.segy_file, 'r') as segyfile: segyfile.mmap() data = segyfile.depth_slice[depth_idx] return data
def cdp(self, cdp): "data of a cdp" with segyio.open(self.segy_file, 'r') as segyfile: segyfile.mmap() data = segyfile.gather[cdp] data = data.reshape((data.shape[-1],)) return data
def _parse_segy(self): with segyio.open(self.segy_file, 'r') as segyfile: segyfile.mmap() self.startInline = segyfile.ilines[0] self.endInline = segyfile.ilines[-1] self.nEast = len(segyfile.ilines) self.stepInline = (self.endInline - self.startInline) // \ (self.nEast - 1) self.startCrline = segyfile.xlines[0] self.endCrline = segyfile.xlines[-1] self.nNorth = len(segyfile.xlines) self.stepCrline = (self.endCrline - self.startCrline) // \ (self.nNorth - 1) self.startDepth = segyfile.samples[0] self.endDepth = segyfile.samples[-1] self.nDepth = len(segyfile.samples) self.stepDepth = (self.endDepth - self.startDepth) // \ (self.nDepth - 1) inline_A = self.startInline crline_A = self.startCrline index_A = 0 x_A = segyfile.header[index_A][segyio.su.cdpx] y_A = segyfile.header[index_A][segyio.su.cdpy] inline_B = inline_A crline_B = self.startCrline + 2 * self.stepCrline index_B = 2 x_B = segyfile.header[index_B][segyio.su.cdpx] y_B = segyfile.header[index_B][segyio.su.cdpy] inline_C = self.startInline + 2 * self.stepInline crline_C = crline_B index_C = 2 * self.nNorth + 2 x_C = segyfile.header[index_C][segyio.su.cdpx] y_C = segyfile.header[index_C][segyio.su.cdpy] setting_dict = { "inline_range": [ self.startInline, self.endInline, self.stepInline], "crline_range": [ self.startCrline, self.endCrline, self.stepCrline], "z_range": [ self.startDepth, self.endDepth, self.stepDepth, "unknown"], "point_A": [inline_A, crline_A, x_A, y_A], "point_B": [inline_B, crline_B, x_B, y_B], "point_C": [inline_C, crline_C, x_C, y_C] } self.survey_setting = SurveySetting(ThreePoints(setting_dict))
def test_header_dict_methods(self): with segyio.open(self.filename, "r") as f: self.assertEqual(89, len(list(f.header[0].keys()))) self.assertEqual(89, len(list(f.header[1].values()))) self.assertEqual(89, len(list(f.header[2].items()))) self.assertEqual(89, len(list(f.header[3]))) self.assertTrue(0 not in f.header[0]) self.assertTrue(1 in f.header[0]) self.assertTrue(segyio.su.cdpx in f.header[0]) iter(f.header[0]) self.assertEqual(30, len(f.bin.keys())) self.assertEqual(30, len(list(f.bin.values()))) self.assertEqual(30, len(list(f.bin.items()))) self.assertEqual(30, len(f.bin)) iter(f.bin)
def set_source_filename(self, filename, **kwargs): if filename: try: source = segyio.open(filename, "r", **kwargs) except: raise else: self._close_current_file() self._source = source self._source.mmap() samples = self._source.samples else: self._close_current_file() self._source = EmptyDataSource() self.slice_data_source_changed.emit()
def test_header_dict_methods(): with segyio.open("test-data/small.sgy") as f: assert 89 == len(list(f.header[0].keys())) assert 89 == len(list(f.header[1].values())) assert 89 == len(list(f.header[2].items())) assert 89 == len(list(f.header[3])) assert 0 not in f.header[0] assert 1 in f.header[0] assert segyio.su.cdpx in f.header[0] iter(f.header[0]) assert 30 == len(f.bin.keys()) assert 30 == len(list(f.bin.values())) assert 30 == len(list(f.bin.items())) assert 30 == len(f.bin) iter(f.bin)
def test_traces_slicing(): with segyio.open("test-data/small.sgy") as f: traces = list(map(np.copy, f.trace[0:6:2])) assert len(traces) == 3 assert traces[0][49] == f.trace[0][49] assert traces[1][49] == f.trace[2][49] assert traces[2][49] == f.trace[4][49] rev_traces = list(map(np.copy, f.trace[4::-2])) assert rev_traces[0][49] == f.trace[4][49] assert rev_traces[1][49] == f.trace[2][49] assert rev_traces[2][49] == f.trace[0][49] # make sure buffers can be reused for i, trace in enumerate(f.trace[0:6:2]): assert np.array_equal(trace, traces[i])
def resample(segy, sample_rate=4, outpath=pathlib.Path.cwd()): '''Create a resample segy file (increase sampling rate) Creates a resampled segy file from an original segy. Note that the new sampling rate has to be a strict multiple of the original one. Parameters ---------- segy : vmlib.seis.segy.io.Segy() instance of the source segyfile as loaded by vmlib.seis.segy.io sample_rate : float, optional destination sampling rate in milliseconds (defaults to 4 [ms]) outpath : pathlib.Path, optional path to destination folder (defaults is pathlib.Path.cwd()) Returns ------- pathlib.Path path to the created, resampled, segy file Raises ------ ValueError if the desired sample rate is not a strict multiple of the original one ''' # Resolve destination file filename, extension = segy.info['filename'].split('.') destination = outpath.joinpath(f'{filename}_resample.{extension}') # Check new sampling rate if (sample_rate % segy.info['sample_rate']) == 0: ratio = int(sample_rate / segy.info['sample_rate']) # Process file with segyio.open(segy.info['file'], ignore_geometry=True) as src: spec = segyio.tools.metadata(src) spec.samples = spec.samples[:int(src.samples.size / ratio) - 1] with segyio.create(destination, spec) as dst: dst.text[0] = src.text[0] dst.bin = src.bin for ix, trace in enumerate(src.trace): dst.trace[ix] = sps.resample(trace, int(len(trace) / ratio)) dst.bin.update(hdt=sample_rate * 1000) dst.bin.update(hns=len(spec.samples)) dst.header = src.header return destination else: raise ValueError('Check sample rate to be multiple of the original')
def put_segy_texthead(segyfile, ebcidc, ext_headers=False, line_counter=True, **segyio_kwargs): header = "" if isinstance(ebcidc, dict): for key in ebcidc: if not isinstance(key, int): warn( "ebcidc dict contains not integer keys that will be ignored", UserWarning, ) for line in range(1, 41): if line_counter: lc = f"C{line:02d} " n = 75 content = "{:<76}" else: lc = "" n = 79 content = "{:<80}" try: test = ebcidc[line] if len(test) > 75: warn(f"EBCIDC line {line} is too long - truncating", UserWarning) header = header + lc + content.format(ebcidc[line][:n]) except KeyError: # line not specified in dictionary header = header + lc + " " * n header = bytes(header, "utf8") elif isinstance(ebcidc, bytes): if len(ebcidc) > 3200: warn("Byte EBCIDC is too large - truncating", UserWarning) header = ebcidc[:3200] elif isinstance(ebcidc, str): if len(ebcidc) > 3200: warn("String EBCIDC is too large - truncating", UserWarning) header = bytes(ebcidc[:3200], "utf8") else: raise ValueError("Unknown ebcidc type") segyio_kwargs["ignore_geometry"] = True with segyio.open(segyfile, "r+", **segyio_kwargs) as segyf: segyf.text[0] = header
def get_segy_texthead(segyfile, ext_headers=False, no_richstr=False, **segyio_kwargs): """Return the ebcidc Args: segyfile (str): Segy File Path ext_headers (bool): Return EBCIDC and extended headers in list. Defaults to False no_richstr (bool, optional): Defaults to False. If true the returned string will not be updated for pretty HTML printing. segyio_kwargs: Key word arguments to pass to segyio.open Returns: str: Returns the EBCIDC text as a formatted paragraph. """ with open(segyfile, mode="rb") as f: f.seek(0, 0) # Locate our position to first byte of file data = f.read(3200) # Read the first 3200 byte from our position if _isascii(data) and ext_headers == False: text = data.decode("ascii") # EBCDIC encoding text = _text_fixes(text) text = segyio.tools.wrap(text) elif ext_headers == False: text = data.decode("cp500") # text is ebcidc text = _text_fixes(text) text = segyio.tools.wrap(text) else: segyio_kwargs["ignore_geometry"] = True try: # pray that the encoding is ebcidc with segyio.open(segyfile, "r", **segyio_kwargs) as segyf: text = segyf.text[0].decode("ascii", "replace") text = _text_fixes(text) text = segyio.tools.wrap(text) if segyf.ext_headers and ext_headers: text2 = segyf.text[1].decode("ascii", "replace") text = [text, text2] except UnicodeDecodeError as err: print(err) print("The segy text header could not be decoded.") if no_richstr: return text else: return _upgrade_txt_richstr(text)
def metadata(f): """Get survey structural properties and metadata Create a description 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. Parameters ---------- f : str or segyio.SegyFile Returns ------- spec : segyio.spec Notes ----- .. versionadded:: 1.4 """ 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 spec.endian = f.endian return spec
def test_create_from_naught_prestack(self): with TestContext("create_from_naught_prestack"): fname = "mk-ps.sgy" spec = segyio.spec() spec.format = 5 spec.sorting = 2 spec.samples = range(7) spec.ilines = range(1, 4) spec.xlines = range(1, 3) spec.offsets = range(1, 6) with segyio.create(fname, spec) as dst: arr = np.arange(start=0.000, stop=0.007, step=0.001, dtype=np.single) arr = np.concatenate([[arr + 0.01], [arr + 0.02]], axis=0) lines = [arr + i for i in spec.ilines] cube = [(off * 100) + line for line in lines for off in spec.offsets] dst.iline[:, :] = cube for of in spec.offsets: for il in spec.ilines: dst.header.iline[il, of] = { TraceField.INLINE_3D: il, TraceField.offset: of } for xl in spec.xlines: dst.header.xline[xl, of] = { TraceField.CROSSLINE_3D: xl } with segyio.open(fname, "r") as f: self.assertAlmostEqual(101.010, f.trace[0][0], places=4) self.assertAlmostEqual(101.011, f.trace[0][1], places=4) self.assertAlmostEqual(101.016, f.trace[0][-1], places=4) self.assertAlmostEqual(503.025, f.trace[-1][5], places=4) self.assertNotEqual(f.header[0][TraceField.offset], f.header[1][TraceField.offset]) self.assertEqual(1, f.header[0][TraceField.offset]) self.assertEqual(2, f.header[1][TraceField.offset]) for x, y in zip(f.iline[:, :], cube): self.assertListEqual(list(x.flatten()), list(y.flatten()))
def test_attributes(): with segyio.open("test-data/small.sgy") as f: il = TraceField.INLINE_3D xl = TraceField.CROSSLINE_3D assert 1 == f.attributes(il)[0] assert 20 == f.attributes(xl)[0] assert f.tracecount == len(f.attributes(il)) assert iter(f.attributes(il)) ils = [(i // 5) + 1 for i in range(25)] attrils = list(map(int, f.attributes(il)[:])) assert ils == attrils xls = [(i % 5) + 20 for i in range(25)] attrxls = list(map(int, f.attributes(xl)[:])) assert xls == attrxls ils = [(i // 5) + 1 for i in range(25)][::-1] attrils = list(map(int, f.attributes(il)[::-1])) assert ils == attrils xls = [(i % 5) + 20 for i in range(25)][::-1] attrxls = list(map(int, f.attributes(xl)[::-1])) assert xls == attrxls assert f.header[0][il] == f.attributes(il)[0] f.mmap() assert f.header[0][il] == f.attributes(il)[0] ils = [(i // 5) + 1 for i in range(25)][1:21:3] attrils = list(map(int, f.attributes(il)[1:21:3])) assert ils == attrils xls = [(i % 5) + 20 for i in range(25)][2:17:5] attrxls = list(map(int, f.attributes(xl)[2:17:5])) assert xls == attrxls ils = [1, 2, 3, 4, 5] attrils = list(map(int, f.attributes(il)[[0, 5, 11, 17, 23]])) assert ils == attrils ils = [1, 2, 3, 4, 5] indices = np.asarray([0, 5, 11, 17, 23]) attrils = list(map(int, f.attributes(il)[indices])) assert ils == attrils
def _segy2d_xr( segyfile, ds, segyio_kwargs, n0, ns, head_df, head_loc, vert_domain="TWT", silent=False, ): """Helper function to load 2d data into an xarray with the seisnc form.""" if vert_domain == "TWT": dims = DimensionKeyField.twod_twt elif vert_domain == "DEPTH": dims = DimensionKeyField.twod_depth else: raise ValueError(f"Unknown vert_domain: {vert_domain}") with segyio.open(segyfile, "r", **segyio_kwargs) as segyf: segyf.mmap() pb = tqdm(total=segyf.tracecount, desc="Converting SEGY", disable=silent, **TQDM_ARGS) shape = [ds.dims[d] for d in dims] volume = np.zeros(shape, dtype=np.float32) percentiles = np.zeros_like(PERCENTILES) # this can probably be done as a block - leaving for now just incase sorting becomes an issue for trc, val in head_df.iterrows(): volume[int(val.cdp_index), :] = segyf.trace[trc][n0:ns + 1] pb.update() percentiles = (np.percentile(segyf.trace[trc][n0:ns + 1], PERCENTILES) + percentiles) / 2.0 pb.close() ds[VariableKeyField.data] = ( dims, volume[:, n0:ns + 1], ) ds.attrs[AttrKeyField.percentiles] = list(percentiles) return ds
def test_fopen_error(): # non-existent file with pytest.raises(IOError): segyio.open("no_dir/no_file") # non-existant mode with pytest.raises(ValueError): segyio.open("test-data/small.sgy", "foo") with pytest.raises(ValueError): segyio.open("test-data/small.sgy", "r+b+toolong")
def test_fopen_error(self): # non-existent file with self.assertRaises(IOError): segyio.open("no_dir/no_file", "r") # non-existant mode with self.assertRaises(ValueError): segyio.open(self.filename, "foo") with self.assertRaises(ValueError): segyio.open(self.filename, "r+b+toolong")
def learn5(): path2 = 'E:/Research/data/F3_entire.segy' path3 = 'E:/Research/data/test1.segy' with segyio.open(path2) as src: spec = segyio.spec() spec.sorting = src.sorting spec.format = src.format spec.samples = src.samples spec.ilines = src.ilines spec.xlines = src.xlines spec.tracecount = src.tracecount print(len(src.samples)) with segyio.create(path3, spec) as dst: dst.text[0] = src.text[0] dst.bin = src.bin dst.header = src.header dst.trace = src.trace
def test_dt_fallback(self): with TestContext("dt_fallback") as context: context.copy_file(self.filename) with segyio.open("small.sgy", "r+") as f: # Both zero f.bin[BinField.Interval] = 0 f.header[0][TraceField.TRACE_SAMPLE_INTERVAL] = 0 f.flush() fallback_dt = 4 np.testing.assert_almost_equal(segyio.dt(f, fallback_dt), fallback_dt) # dt in bin header different from first trace f.bin[BinField.Interval] = 6000 f.header[0][TraceField.TRACE_SAMPLE_INTERVAL] = 1000 f.flush() fallback_dt = 4 np.testing.assert_almost_equal(segyio.dt(f, fallback_dt), fallback_dt)
def load_segy(fn_sgy, *args, **kwargs): """Load segy data. This is very generic for now, need to do work if there are particular types of segy files that need to be read. We cannot yet support a generic SEGY file, even if complies to some standard set. """ if not SEGY: raise ImportError('Need segyio to load SGY files') segy_data = RadarData(None) segy_data.fn = fn_sgy f = segyio.open(fn_sgy, ignore_geometry=True) segy_data.data = segyio.tools.collect(f.trace).transpose() segy_data.snum = f.bin[segyio.BinField.Samples] segy_data.tnum = segy_data.data.shape[1] segy_data.dt = f.bin[segyio.BinField.Interval] * 1.0e-12 segy_data.travel_time = np.arange(segy_data.snum) * segy_data.dt * 1.0e6 segy_data.trace_num = np.arange(segy_data.data.shape[1]) + 1 segy_data.flags = RadarFlags() # segy_data.travel_time = np.atleast_2d(np.arange(0, # segy_data.dt * segy_data.snum, segy_data.dt)).transpose() # + segy_data.dt # TODO these next ones are filler # right now, they are selected so that they read in the delores data segy_data.trace_int = 1 segy_data.chan = 1 segy_data.trig = np.zeros((segy_data.tnum, )) segy_data.decday = np.zeros((segy_data.tnum, )) segy_data.x_coord = f.attributes(segyio.TraceField.CDP_X)[:] / 10.0 segy_data.y_coord = f.attributes(segyio.TraceField.CDP_Y)[:] / 10.0 segy_data.dist = np.hstack( ([0], np.cumsum( np.sqrt( np.diff(segy_data.x_coord)**2.0 + np.diff(segy_data.y_coord)**2.0)))) / 1000. segy_data.long = np.zeros((segy_data.tnum, )) segy_data.lat = np.zeros((segy_data.tnum, )) segy_data.elev = np.zeros((segy_data.tnum, )) segy_data.trig_level = np.zeros((segy_data.tnum, )) segy_data.pressure = np.zeros((segy_data.tnum, )) segy_data.check_attrs() return segy_data
def getFileInfo(dirName): """ This function will read all of the *.segy or & *.sgy files in a given directory. It returns a list with the file name and the shot location. This information will be passed to the GUI to display the file names. At a latter time it might be worth extracting other things from the headers and storing them in this list. DEPENDENCIES: GLOB - this is used to get the file names in the directory segyio - this is used to read the segy files and extract header info INPUTS: dirName (str) = this is a string to the directory that contains all of the segy files from the survey. OUTPUTS: fileInfo is a list that is total Files by 2. Column 1 (str) = file name Column 2 (float) = shot location (units assumed to be m) NOTES: At this stage I use two if statemetns to check for segy files. If there are no segy files fileInfo will be an empty list and the user will get an error. Though I am not sure where error goes in a GUI? - It depends, but we will be able to use try-except blocks for them It might be worth adding columns to this list if we need more info from the files later on """ files = glb.glob(os.path.join(dirName, "*.sgy")) if files == []: files = glb.glob(os.path.join(dirName, "*.segy")) if files == []: print("No files with *.sgy or *.segy exist in this directory") # Column 1: File Name (str) # Column 2: SX (float) fileInfo = [] for file in files: filename = os.path.basename(file) # print(filename) with segyio.open(file, strict=False) as f: shotLoc = f.header[0][segyio.TraceField.SourceX] # print(shotLoc) fileInfo.append([filename, shotLoc]) return fileInfo
def test_depth_slice_writing(tmpdir): buf = np.empty(shape=(5, 5), dtype=np.single) def value(x, y): return x + (1.0 // 5) * y for x, y in itertools.product(range(5), range(5)): buf[x][y] = value(x, y) with segyio.open(tmpdir / "small.sgy", "r+") as f: f.depth_slice[7] = buf * 3.14 # assign to depth 7 assert np.allclose(f.depth_slice[7], buf * 3.14) f.depth_slice = [buf * i for i in range(len(f.depth_slice))] # assign to all depths for index, depth_slice in enumerate(f.depth_slice): assert np.allclose(depth_slice, buf * index)
def btnArquivoPressed(self): options = QFileDialog.Options() #options |= QFileDialog.FileType("*.segy") fileName, _ = QFileDialog.getOpenFileName( self, "QFileDialog.getOpenFileName()", "", "Seg-Y (*.segy);; Seg-Y (*.sgy)", options=options) if fileName: self.txtArquivo.setText(fileName) sgy = segyio.open(self.txtArquivo.text(), ignore_geometry=True) Dx = np.array(sgy.trace) self.dado = Dx [self.nt, self.nr] = self.dado.shape self.txtNt.setText(str(self.nt)) self.txtNr.setText(str(self.nr))
def location(self): if self._data_type[0][-3: ] == 'bin': self._location['inline_start'] = self._data_type[2][0] self._location['xline_start'] = self._data_type[2][1] self._location['time_start'] = self._data_type[2][2] self._location['sample_interval'] = self._data_type[2][3] self.location_out = self._location pass elif self._data_type[0][-3: ] == 'sgy': with segyio.open(self._data_type[0]) as f: self._location['inline_start'] = f.ilines[0] self._location['xline_start'] = f.xlines[0] self._location['time_start'] = int(f.samples[0]) self._location['sample_interval'] = int(f.samples[1] - f.samples[0]) self.location_out = self._location pass return
def openSegy3D(filename): """ Open 3D seismic volume in SEGY or SGY format """ import segyio try: with segyio.open(filename) as f: data = segyio.tools.cube(f) inlines = f.ilines crosslines = f.xlines twt = f.samples sample_rate = segyio.tools.dt(f) / 1000 print('Successfully read \n') print('Inline range from', inlines[0], 'to', inlines[-1]) print('Crossline range from', crosslines[0], 'to', crosslines[-1]) print('TWT from', twt[0], 'to', twt[-1]) print('Sample rate:', sample_rate, 'ms') try: rot, cdpx, cdpy = segyio.tools.rotation(f, line="fast") print('Survey rotation: {:.2f} deg'.format(rot)) except: print("Survey rotation not recognized") cube = dict({"data": data, "inlines": inlines, "crosslines": crosslines, "twt": twt, "sample_rate": sample_rate}) # See Stackoverflow: https://stackoverflow.com/questions/4984647/accessing-dict-keys-like-an-attribute class AttrDict(dict): def __init__(self, *args, **kwargs): super(AttrDict, self).__init__(*args, **kwargs) self.__dict__ = self cube = AttrDict(cube) except: print("openSegy cannot read your data") return cube
def make_segy_index(filename, extra_headers=None, limits=None): """Index traces in a single SEGY file. Parameters ---------- filename : str Path to SEGY file. extra_headers : array-like or str Additional headers to put unto DataFrme. If 'all', all headers are included. limits : slice or int, default to None If int, index only first ```limits``` traces. If slice, index only traces within given range. If None, index all traces. Returns ------- df : pandas.DataFrame DataFrame with trace indexing. """ if not isinstance(limits, slice): limits = slice(limits) with segyio.open(filename, strict=False) as segyfile: segyfile.mmap() if extra_headers == 'all': headers = [h.__str__() for h in segyio.TraceField.enums()] elif extra_headers is None: headers = DEFAULT_SEGY_HEADERS + SUPPORT_SEGY_HEADERS else: extra_headers = [extra_headers] if isinstance( extra_headers, str) else list(extra_headers) headers = set(DEFAULT_SEGY_HEADERS + extra_headers + SUPPORT_SEGY_HEADERS) meta = dict() for k in headers: meta[k] = segyfile.attributes(getattr(segyio.TraceField, k))[limits] meta['file_id'] = np.repeat(filename, segyfile.tracecount)[limits] meta['RecieverID'] = np.array( [hash(pair) for pair in zip(meta['GroupX'], meta['GroupY'])]) df = pd.DataFrame(meta) return df
def convert_segy_stream(self, bits_per_voxel, blockshape, reduce_iops=False): """Memory-efficient method of compressing SEG-Y file larger than machine memory. Requires at least n_crosslines x n_samples x blockshape[2] x 4 bytes of available memory""" t0 = time.time() if not os.path.exists(self.in_filename): msg = "With searching comes loss, and the presence of absence: 'My Segy' not found." raise FileNotFoundError(msg) with segyio.open(self.in_filename, mode='r', strict=False) as segyfile: if self.geom is None: if segyfile.unstructured: print("SEG-Y file is unstructured and no geometry provided. Determining this may take some time...") traces_ref = {(h[189], h[193]): i for i, h in enumerate(segyfile.header)} self.geom = InferredGeometry(traces_ref) print("... inferred geometry is:", self.geom) else: self.geom = Geometry(0, len(segyfile.ilines), 0, len(segyfile.xlines)) n_traces = len(self.geom.ilines) * len(self.geom.xlines) inline_set_bytes = blockshape[0] * (len(self.geom.xlines) * len(segyfile.samples)) * 4 headers_to_store = get_unique_headerwords(segyfile) numpy_headers_arrays = [np.zeros(n_traces, dtype=np.int32) for _ in range(len(headers_to_store))] if inline_set_bytes > virtual_memory().total // 2: print("One inline set is {} bytes, machine memory is {} bytes".format(inline_set_bytes, virtual_memory().total)) print("Try using fewer inlines in the blockshape, or compressing a subcube") raise RuntimeError("ABORTED effort: Close all that you have. You ask way too much.") max_queue_length = min(16, (virtual_memory().total // 2) // inline_set_bytes) print("VirtualMemory={}MB, InlineSet={}MB : Using queue of length {}".format(virtual_memory().total/(1024*1024), inline_set_bytes/(1024*1024), max_queue_length)) run_conversion_loop(self.in_filename, self.out_filename, bits_per_voxel, blockshape, headers_to_store, numpy_headers_arrays, self.geom, queuesize=max_queue_length, reduce_iops=reduce_iops) with open(self.out_filename, 'ab') as f: for header_array in numpy_headers_arrays: f.write(header_array.tobytes()) t3 = time.time() print("Total conversion time: {} ".format(t3-t0))
def _read_velocity(self, vcube, cell_corners): """ Read velocity from segy file. Upscale. :param vcube: :param cell_corners: :return: """ with segyio.open(vcube) as f: x = np.empty(f.tracecount, dtype=np.float64) y = np.empty(f.tracecount, dtype=np.float64) dt = segyio.dt(f) / 1e6 nt = len(f.samples) for i, h in enumerate(f.header): scalar = h[TraceField.SourceGroupScalar] if scalar < 0: scalar = -1.0 / scalar x[i] = h[TraceField.CDP_X] * scalar y[i] = h[TraceField.CDP_Y] * scalar ny = len(f.xlines) nx = len(f.ilines) # memory issue might happen if volume becomes too large traces = f.trace.raw[:] if f.sorting == segyio.TraceSortingFormat.INLINE_SORTING: x = x.reshape(ny, nx) y = y.reshape(ny, nx) traces = traces.reshape(ny, nx, nt) x = np.transpose(x) y = np.transpose(y) traces = np.transpose(traces, (1, 0, 2)) elif f.sorting == segyio.TraceSortingFormat.CROSSLINE_SORTING: x = x.reshape(nx, ny) y = y.reshape(nx, ny) traces = traces.reshape(nx, ny, nt) else: raise RuntimeError x, y, traces, nt, dt = self._upscale_velocity(cell_corners, x, y, traces, nt, dt) return x, y, traces, nt, dt
def read_2Dmodel(self, path): """ Build a 2D velocity model from a SEG-Y format. It uses the 'segyio' from https://github.com/equinor/segyio """ with segyio.open(path, ignore_geometry=True) as f: n_samples = len(f.samples) n_traces = len(f.trace) data = np.zeros(shape=(n_samples, n_traces), dtype=np.float32) index = 0 for trace in f.trace: data[:, index] = trace index += 1 # data = 2d data # n_samples = height # n_traces = length self.model = data
def test_open_fails_unstructured(self): with segyio.open(self.filename, "r", 37, strict=False) as f: with self.assertRaises(ValueError): f.iline[10] with self.assertRaises(ValueError): f.iline[:, :] with self.assertRaises(ValueError): f.xline[:, :] with self.assertRaises(ValueError): f.depth_slice[2] # operations that don't rely on geometry still works self.assertEqual(f.header[2][189], 1) self.assertListEqual(list(f.attributes(189)[:]), [(i // 5) + 1 for i in range(len(f.trace))])
def test_traces_slicing(self): with segyio.open(self.filename, "r") as f: traces = list(map(np.copy, f.trace[0:6:2])) self.assertEqual(len(traces), 3) self.assertEqual(traces[0][49], f.trace[0][49]) self.assertEqual(traces[1][49], f.trace[2][49]) self.assertEqual(traces[2][49], f.trace[4][49]) rev_traces = list(map(np.copy, f.trace[4::-2])) self.assertEqual(rev_traces[0][49], f.trace[4][49]) self.assertEqual(rev_traces[1][49], f.trace[2][49]) self.assertEqual(rev_traces[2][49], f.trace[0][49]) # make sure buffers can be reused buf = None for i, trace in enumerate(f.trace[0:6:2, buf]): self.assertTrue(np.array_equal(trace, traces[i]))
def compress_and_compare_zgy(zgy_file, sgy_file, tmp_path, bits_per_voxel, rtol): out_sgz = os.path.join( str(tmp_path), 'test_{}_{}_.sgz'.format( os.path.splitext(os.path.basename(zgy_file))[0], bits_per_voxel)) with ZgyConverter(zgy_file) as converter: converter.run(out_sgz, bits_per_voxel=bits_per_voxel) with SgzReader(out_sgz) as reader: sgz_data = reader.read_volume() sgz_ilines = reader.ilines with segyio.open(sgy_file) as f: ref_ilines = f.ilines assert np.allclose(sgz_data, segyio.tools.cube(sgy_file), rtol=rtol) assert all([a == b for a, b in zip(sgz_ilines, ref_ilines)])
def main(): if len(sys.argv) < 2: sys.exit("Usage: trace_headers_to_dataframe.py [file]") filename = sys.argv[1] # Open file with segyio.open(filename, ignore_geometry=True) as f: # Get all header keys: header_keys = segyio.tracefield.keys # Initialize df with trace id as index and headers as columns trace_headers = pd.DataFrame(index=range(1, f.tracecount + 1), columns=header_keys.keys()) # Fill dataframe with all trace headers values for k, v in header_keys.items(): trace_headers[k] = f.attributes(v)[:] print(trace_headers.head())
def test_open_fails_unstructured(): with segyio.open("test-data/small.sgy", "r", 37, strict=False) as f: with pytest.raises(ValueError): _ = f.iline[10] with pytest.raises(ValueError): _ = f.iline[:, :] with pytest.raises(ValueError): _ = f.xline[:, :] with pytest.raises(ValueError): _ = f.depth_slice[2] # operations that don't rely on geometry still works assert f.header[2][189] == 1 assert (list(f.attributes(189)[:]) == [(i // 5) + 1 for i in range(len(f.trace))])
def update(self, index, data): """ Update data with ndarray Parameters ---------- index : InlineIndex data : 2-d ndarray data for updating Inline """ try: if not isinstance(index, InlineIndex): raise TypeError("has to be InlineIndex") if data.shape != (self.nNorth, self.nDepth): raise ValueError with segyio.open(self.segy_file, 'r+') as segyfile: segyfile.mmap() segyfile.iline[index.value] = data except Exception as er: print(er.message)
def inline(self, inline): "data of a inline section" with segyio.open(self.segy_file, 'r') as segyfile: segyfile.mmap() data = segyfile.iline[inline] return data
def crline(self, crline): "data of a crossline section" with segyio.open(self.segy_file, 'r') as segyfile: segyfile.mmap() data = segyfile.xline[crline] return data