├── .gitignore ├── LICENSE ├── LICENSE.txt ├── MANIFEST.in ├── Pipfile ├── Pipfile.lock ├── PyOSGPUP.egg-info ├── PKG-INFO ├── SOURCES.txt ├── dependency_links.txt ├── requires.txt └── top_level.txt ├── PyOSGPUP ├── __init__.py ├── __pycache__ │ ├── __init__.cpython-36.pyc │ ├── segypy.cpython-36.pyc │ ├── signal.cpython-36.pyc │ ├── signalpy.cpython-36.pyc │ ├── tuning_wedge_acces.cpython-36.pyc │ └── wavelet.cpython-36.pyc ├── segypy.py ├── signalpy.py ├── synthe_seismo.py ├── tuning_wedge_acces.py └── wavelet.py ├── README.md ├── README.rst ├── build └── lib │ ├── PyOSGPUP │ ├── __init__.py │ ├── segypy.py │ ├── signalpy.py │ ├── synthe_seismo.py │ ├── tuning_wedge_acces.py │ └── wavelet.py │ └── sample │ ├── __init__.py │ └── package_data.dat ├── dist └── PyOSGPUP-1.0.3-py3-none-any.whl ├── example ├── readsegy.png ├── seis1.png ├── seis2.png ├── seis3.png └── wavelet.png ├── requirements.txt ├── setup.cfg ├── setup.py └── tox.ini /.gitignore: -------------------------------------------------------------------------------- 1 | # Python: 2 | ## Byte-compiled / optimized / DLL files 3 | __pycache__/ 4 | *.py[cod] 5 | *$py.class 6 | 7 | ## C extensions 8 | *.so 9 | 10 | ## PyInstaller 11 | *.manifest 12 | *.spec 13 | 14 | ## Installer logs 15 | pip-log.txt 16 | pip-delete-this-directory.txt 17 | 18 | ## Unit test / coverage reports 19 | htmlcov/ 20 | .tox/ 21 | .coverage 22 | .coverage.* 23 | .cache 24 | nosetests.xml 25 | coverage.xml 26 | *.cover 27 | .hypothesis/ 28 | 29 | ## Sphinx documentation 30 | docs/_build/ 31 | 32 | ## dotenv 33 | .env 34 | 35 | ## virtualenv 36 | .venv 37 | venv/ 38 | ENV/ 39 | 40 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 Komputasi Geofisika 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | Copyright (c) 2016 The Python Packaging Authority (PyPA) 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy of 4 | this software and associated documentation files (the "Software"), to deal in 5 | the Software without restriction, including without limitation the rights to 6 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 7 | of the Software, and to permit persons to whom the Software is furnished to do 8 | so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in all 11 | copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 19 | SOFTWARE. 20 | -------------------------------------------------------------------------------- /MANIFEST.in: -------------------------------------------------------------------------------- 1 | # Include the license file 2 | include LICENSE.txt 3 | 4 | # Include the data files 5 | recursive-include data * 6 | -------------------------------------------------------------------------------- /Pipfile: -------------------------------------------------------------------------------- 1 | [[source]] 2 | 3 | url = "https://pypi.python.org/simple" 4 | verify_ssl = true 5 | name = "pypi" 6 | 7 | 8 | [packages] 9 | 10 | requests = "*" 11 | 12 | 13 | [dev-packages] 14 | 15 | 16 | 17 | [requires] 18 | 19 | python_version = "3.6" 20 | -------------------------------------------------------------------------------- /Pipfile.lock: -------------------------------------------------------------------------------- 1 | { 2 | "_meta": { 3 | "hash": { 4 | "sha256": "33a0ec7c8e3bae6f62dd618f847de92ece20e2bd4efb496927e2524b9c7b8df8" 5 | }, 6 | "pipfile-spec": 6, 7 | "requires": { 8 | "python_version": "3.6" 9 | }, 10 | "sources": [ 11 | { 12 | "name": "pypi", 13 | "url": "https://pypi.python.org/simple", 14 | "verify_ssl": true 15 | } 16 | ] 17 | }, 18 | "default": { 19 | "certifi": { 20 | "hashes": [ 21 | "sha256:14131608ad2fd56836d33a71ee60fa1c82bc9d2c8d98b7bdbc631fe1b3cd1296", 22 | "sha256:edbc3f203427eef571f79a7692bb160a2b0f7ccaa31953e99bd17e307cf63f7d" 23 | ], 24 | "version": "==2018.1.18" 25 | }, 26 | "chardet": { 27 | "hashes": [ 28 | "sha256:84ab92ed1c4d4f16916e05906b6b75a6c0fb5db821cc65e70cbd64a3e2a5eaae", 29 | "sha256:fc323ffcaeaed0e0a02bf4d117757b98aed530d9ed4531e3e15460124c106691" 30 | ], 31 | "version": "==3.0.4" 32 | }, 33 | "idna": { 34 | "hashes": [ 35 | "sha256:2c6a5de3089009e3da7c5dde64a141dbc8551d5b7f6cf4ed7c2568d0cc520a8f", 36 | "sha256:8c7309c718f94b3a625cb648ace320157ad16ff131ae0af362c9f21b80ef6ec4" 37 | ], 38 | "version": "==2.6" 39 | }, 40 | "requests": { 41 | "hashes": [ 42 | "sha256:6a1b267aa90cac58ac3a765d067950e7dbbf75b1da07e895d1f594193a40a38b", 43 | "sha256:9c443e7324ba5b85070c4a818ade28bfabedf16ea10206da1132edaa6dda237e" 44 | ], 45 | "version": "==2.18.4" 46 | }, 47 | "urllib3": { 48 | "hashes": [ 49 | "sha256:06330f386d6e4b195fbfc736b297f58c5a892e4440e54d294d7004e3a9bbea1b", 50 | "sha256:cc44da8e1145637334317feebd728bd869a35285b93cbb4cca2577da7e62db4f" 51 | ], 52 | "version": "==1.22" 53 | } 54 | }, 55 | "develop": {} 56 | } 57 | -------------------------------------------------------------------------------- /PyOSGPUP.egg-info/PKG-INFO: -------------------------------------------------------------------------------- 1 | Metadata-Version: 1.2 2 | Name: PyOSGPUP 3 | Version: 1.0.3 4 | Summary: An open-source library for geophysical data processing, modeling, and interpretation based on Python. 5 | Home-page: https://sites.google.com/site/metkomup/ 6 | Author: Komputasi Geofisika - Universitas Pertamina 7 | Author-email: metkom.up@gmail.com 8 | License: UNKNOWN 9 | Project-URL: Bug Reports, https://github.com/Metkom/PyOSGPUP/issues 10 | Project-URL: Say Thanks!, https://sites.google.com/site/metkomup/pyosgpup 11 | Project-URL: Source, https://github.com/Metkom/PyOSGPUP 12 | Description-Content-Type: UNKNOWN 13 | Description: PyOSGPUP: Python, Open-source 14 | ============================= 15 | 16 | PuOSGPUP: Python Library that is Open-source created by 17 | Geophysical Engineering, Universitas Pertamina 18 | 19 | A python packages for geophysical data processing, modeling, and interpretation. 20 | 21 | Teknik Geofisika, Universitas Pertamina 22 | Jl. Teuku Nyak Arief, Simprug, South Jakarta, DKI Jakarta, Indonesia, 12220. 23 | email: metkom.up@gmail.com 24 | Keywords: geophysical data processing,modeling,and interpretation 25 | Platform: Windows 26 | Platform: Linux 27 | Platform: Mac OS-X 28 | Classifier: Development Status :: 3 - Alpha 29 | Classifier: Intended Audience :: Developers 30 | Classifier: Topic :: Software Development :: Build Tools 31 | Classifier: License :: OSI Approved :: MIT License 32 | Classifier: Programming Language :: Python :: 3.4 33 | Classifier: Programming Language :: Python :: 3.5 34 | Classifier: Programming Language :: Python :: 3.6 35 | -------------------------------------------------------------------------------- /PyOSGPUP.egg-info/SOURCES.txt: -------------------------------------------------------------------------------- 1 | LICENSE.txt 2 | MANIFEST.in 3 | README.rst 4 | setup.cfg 5 | setup.py 6 | PyOSGPUP/__init__.py 7 | PyOSGPUP/segypy.py 8 | PyOSGPUP/signalpy.py 9 | PyOSGPUP/synthe_seismo.py 10 | PyOSGPUP/tuning_wedge_acces.py 11 | PyOSGPUP/wavelet.py 12 | PyOSGPUP.egg-info/PKG-INFO 13 | PyOSGPUP.egg-info/SOURCES.txt 14 | PyOSGPUP.egg-info/dependency_links.txt 15 | PyOSGPUP.egg-info/requires.txt 16 | PyOSGPUP.egg-info/top_level.txt -------------------------------------------------------------------------------- /PyOSGPUP.egg-info/dependency_links.txt: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /PyOSGPUP.egg-info/requires.txt: -------------------------------------------------------------------------------- 1 | numpy 2 | matplotlib 3 | -------------------------------------------------------------------------------- /PyOSGPUP.egg-info/top_level.txt: -------------------------------------------------------------------------------- 1 | PyOSGPUP 2 | -------------------------------------------------------------------------------- /PyOSGPUP/__init__.py: -------------------------------------------------------------------------------- 1 | from __future__ import print_function 2 | 3 | from PyOSGPUP import wavelet 4 | from PyOSGPUP import segypy 5 | from PyOSGPUP import tuning_wedge_acces 6 | from PyOSGPUP import signalpy 7 | 8 | __version__ = '1.0.3' 9 | __author__ = 'PyOSGPUP Team' 10 | __license__ = 'MIT' 11 | __copyright__ = '2018, PyOSGPUP Team, https://sites.google.com/site/metkomup/pyosgpup' 12 | -------------------------------------------------------------------------------- /PyOSGPUP/__pycache__/__init__.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Metkom/PyOSGPUP/93b2e153b3dd4e1f644a704a0d7c62ca3bda8f26/PyOSGPUP/__pycache__/__init__.cpython-36.pyc -------------------------------------------------------------------------------- /PyOSGPUP/__pycache__/segypy.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Metkom/PyOSGPUP/93b2e153b3dd4e1f644a704a0d7c62ca3bda8f26/PyOSGPUP/__pycache__/segypy.cpython-36.pyc -------------------------------------------------------------------------------- /PyOSGPUP/__pycache__/signal.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Metkom/PyOSGPUP/93b2e153b3dd4e1f644a704a0d7c62ca3bda8f26/PyOSGPUP/__pycache__/signal.cpython-36.pyc -------------------------------------------------------------------------------- /PyOSGPUP/__pycache__/signalpy.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Metkom/PyOSGPUP/93b2e153b3dd4e1f644a704a0d7c62ca3bda8f26/PyOSGPUP/__pycache__/signalpy.cpython-36.pyc -------------------------------------------------------------------------------- /PyOSGPUP/__pycache__/tuning_wedge_acces.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Metkom/PyOSGPUP/93b2e153b3dd4e1f644a704a0d7c62ca3bda8f26/PyOSGPUP/__pycache__/tuning_wedge_acces.cpython-36.pyc -------------------------------------------------------------------------------- /PyOSGPUP/__pycache__/wavelet.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Metkom/PyOSGPUP/93b2e153b3dd4e1f644a704a0d7c62ca3bda8f26/PyOSGPUP/__pycache__/wavelet.cpython-36.pyc -------------------------------------------------------------------------------- /PyOSGPUP/segypy.py: -------------------------------------------------------------------------------- 1 | """ 2 | A python module for reading/writing/manipuating 3 | SEG-Y formatted filed 4 | 5 | segy.readSegy : Read SEGY file 6 | segy.getSegyHeader : Get SEGY header 7 | segy.getSegyTraceHeader : Get SEGY Trace header 8 | segy.getAllSegyTraceHeaders : Get all SEGY Trace headers 9 | segy.getSegyTrace : Get SEGY Trace heder and trace data for one trace 10 | 11 | segy.writeSegy : Write a data to a SEGY file 12 | segy.writeSegyStructure : Writes a segypy data structure to a SEGY file 13 | 14 | segy.getValue : Get a value from a binary string 15 | segy.ibm2ieee : Convert IBM floats to IEEE 16 | 17 | segy.version : The version of SegyPY 18 | segy.verbose : Amount of verbose information to the screen 19 | """ 20 | # 21 | # segypy : A Python module for reading and writing SEG-Y formatted data 22 | # 23 | # (C) Thomas Mejer Hansen, 2005-2016 24 | # 25 | # contributions from 26 | # - Pete Forman 27 | # 28 | # modified by Andrew Squelch 2007 : sub-version 0.3.1 29 | from __future__ import division 30 | from __future__ import print_function 31 | 32 | import struct, sys # modified by A Squelch 33 | 34 | import numpy as np 35 | 36 | 37 | # SOME GLOBAL PARAMETERS 38 | version = '0.3.1' # modified by A Squelch 39 | verbose = 1; 40 | 41 | # endian='>' # Big Endian # modified by A Squelch 42 | # endian='<' # Little Endian 43 | # endian='=' # Native 44 | 45 | l_int = struct.calcsize('i') 46 | l_uint = struct.calcsize('I') 47 | l_long = 4; 48 | # Next line gives wrong result on Linux!! (gives 8 instead of 4) 49 | # l_long = struct.calcsize('l') 50 | l_ulong = struct.calcsize('L') 51 | l_short = struct.calcsize('h') 52 | l_ushort = struct.calcsize('H') 53 | l_char = struct.calcsize('c') 54 | l_uchar = struct.calcsize('B') 55 | l_float = struct.calcsize('f') 56 | 57 | ############## 58 | # INIT 59 | 60 | ############## 61 | # %% Initialize SEGY HEADER 62 | SH_def = {"Job": {"pos": 3200, "type": "int32", "def": 0}} 63 | SH_def["Line"] = {"pos": 3204, "type": "int32", "def": 0} 64 | SH_def["Reel"] = {"pos": 3208, "type": "int32", "def": 0} 65 | SH_def["DataTracePerEnsemble"] = {"pos": 3212, "type": "int16", "def": 0} 66 | SH_def["AuxiliaryTracePerEnsemble"] = {"pos": 3214, "type": "int16", "def": 0} 67 | SH_def["dt"] = {"pos": 3216, "type": "uint16", "def": 1000} 68 | SH_def["dtOrig"] = {"pos": 3218, "type": "uint16", "def": 1000} 69 | SH_def["ns"] = {"pos": 3220, "type": "uint16", "def": 0} 70 | SH_def["nsOrig"] = {"pos": 3222, "type": "uint16", "def": 0} 71 | SH_def["DataSampleFormat"] = {"pos": 3224, "type": "int16", "def": 5} 72 | SH_def["DataSampleFormat"]["descr"] = {0: { 73 | 1: "IBM Float", 74 | 2: "32 bit Integer", 75 | 3: "16 bit Integer", 76 | 8: "8 bit Integer"}} 77 | 78 | SH_def["DataSampleFormat"]["descr"][1] = { 79 | 1: "IBM Float", 80 | 2: "32 bit Integer", 81 | 3: "16 bit Integer", 82 | 5: "IEEE", 83 | 8: "8 bit Integer"} 84 | 85 | SH_def["DataSampleFormat"]["bps"] = {0: { 86 | 1: 4, 87 | 2: 4, 88 | 3: 2, 89 | 8: 1}} 90 | SH_def["DataSampleFormat"]["bps"][1] = { 91 | 1: 4, 92 | 2: 4, 93 | 3: 2, 94 | 5: 4, 95 | 8: 1} 96 | SH_def["DataSampleFormat"]["datatype"] = {0: { 97 | 1: 'ibm', 98 | 2: 'l', 99 | 3: 'h', 100 | 8: 'B'}} 101 | SH_def["DataSampleFormat"]["datatype"][1] = { 102 | 1: 'ibm', 103 | 2: 'l', 104 | 3: 'h', 105 | # 5: 'float', 106 | 5: 'f', 107 | 8: 'B'} 108 | 109 | SH_def["EnsembleFold"] = {"pos": 3226, "type": "int16", "def": 0} 110 | SH_def["TraceSorting"] = {"pos": 3228, "type": "int16", "def": 0} 111 | SH_def["VerticalSumCode"] = {"pos": 3230, "type": "int16", "def": 0} 112 | SH_def["SweepFrequencyEnd"] = {"pos": 3234, "type": "int16", "def": 0} 113 | SH_def["SweepLength"] = {"pos": 3236, "type": "int16", "def": 0} 114 | SH_def["SweepType"] = {"pos": 3238, "type": "int16", "def": 0} 115 | SH_def["SweepChannel"] = {"pos": 3240, "type": "int16", "def": 0} 116 | SH_def["SweepTaperlengthStart"] = {"pos": 3242, "type": "int16", "def": 0} 117 | SH_def["SweepTaperLengthEnd"] = {"pos": 3244, "type": "int16", "def": 0} 118 | SH_def["TaperType"] = {"pos": 3246, "type": "int16", "def": 0} 119 | SH_def["CorrelatedDataTraces"] = {"pos": 3248, "type": "int16", "def": 0} 120 | SH_def["BinaryGain"] = {"pos": 3250, "type": "int16", "def": 0} 121 | SH_def["AmplitudeRecoveryMethod"] = {"pos": 3252, "type": "int16", "def": 0} 122 | SH_def["MeasurementSystem"] = {"pos": 3254, "type": "int16", "def": 0} 123 | SH_def["ImpulseSignalPolarity"] = {"pos": 3256, "type": "int16", "def": 0} 124 | SH_def["VibratoryPolarityCode"] = {"pos": 3258, "type": "int16", "def": 0} 125 | SH_def["Unassigned1"] = {"pos": 3260, "type": "int16", "n": 120, "def": 0} 126 | SH_def["SegyFormatRevisionNumber"] = {"pos": 3500, "type": "uint16", "def": 100} 127 | SH_def["FixedLengthTraceFlag"] = {"pos": 3502, "type": "uint16", "def": 0} 128 | SH_def["NumberOfExtTextualHeaders"] = {"pos": 3504, "type": "uint16", "def": 0} 129 | SH_def["Unassigned2"] = {"pos": 3506, "type": "int16", "n": 47, "def": 0} 130 | 131 | ############## 132 | # %% Initialize SEGY TRACE HEADER SPECIFICATION 133 | STH_def = {"TraceSequenceLine": {"pos": 0, "type": "int32"}} 134 | STH_def["TraceSequenceFile"] = {"pos": 4, "type": "int32"} 135 | STH_def["FieldRecord"] = {"pos": 8, "type": "int32"} 136 | STH_def["TraceNumber"] = {"pos": 12, "type": "int32"} 137 | STH_def["EnergySourcePoint"] = {"pos": 16, "type": "int32"} 138 | STH_def["cdp"] = {"pos": 20, "type": "int32"} 139 | STH_def["cdpTrace"] = {"pos": 24, "type": "int32"} 140 | STH_def["TraceIdenitifactionCode"] = {"pos": 28, "type": "uint16"} # 'int16'); % 28 141 | STH_def["TraceIdenitifactionCode"]["descr"] = {0: { 142 | 1: "Seismic data", 143 | 2: "Dead", 144 | 3: "Dummy", 145 | 4: "Time Break", 146 | 5: "Uphole", 147 | 6: "Sweep", 148 | 7: "Timing", 149 | 8: "Water Break"}} 150 | STH_def["TraceIdenitifactionCode"]["descr"][1] = { 151 | -1: "Other", 152 | 0: "Unknown", 153 | 1: "Seismic data", 154 | 2: "Dead", 155 | 3: "Dummy", 156 | 4: "Time break", 157 | 5: "Uphole", 158 | 6: "Sweep", 159 | 7: "Timing", 160 | 8: "Waterbreak", 161 | 9: "Near-field gun signature", 162 | 10: "Far-field gun signature", 163 | 11: "Seismic pressure sensor", 164 | 12: "Multicomponent seismic sensor - Vertical component", 165 | 13: "Multicomponent seismic sensor - Cross-line component", 166 | 14: "Multicomponent seismic sensor - In-line component", 167 | 15: "Rotated multicomponent seismic sensor - Vertical component", 168 | 16: "Rotated multicomponent seismic sensor - Transverse component", 169 | 17: "Rotated multicomponent seismic sensor - Radial component", 170 | 18: "Vibrator reaction mass", 171 | 19: "Vibrator baseplate", 172 | 20: "Vibrator estimated ground force", 173 | 21: "Vibrator reference", 174 | 22: "Time-velocity pairs"} 175 | STH_def["NSummedTraces"] = {"pos": 30, "type": "int16"} # 'int16'); % 30 176 | STH_def["NStackedTraces"] = {"pos": 32, "type": "int16"} # 'int16'); % 32 177 | STH_def["DataUse"] = {"pos": 34, "type": "int16"} # 'int16'); % 34 178 | STH_def["DataUse"]["descr"] = {0: { 179 | 1: "Production", 180 | 2: "Test"}} 181 | STH_def["DataUse"]["descr"][1] = STH_def["DataUse"]["descr"][0] 182 | STH_def["offset"] = {"pos": 36, "type": "int32"} # 'int32'); %36 183 | STH_def["ReceiverGroupElevation"] = {"pos": 40, "type": "int32"} # 'int32'); %40 184 | STH_def["SourceSurfaceElevation"] = {"pos": 44, "type": "int32"} # 'int32'); %44 185 | STH_def["SourceDepth"] = {"pos": 48, "type": "int32"} # 'int32'); %48 186 | STH_def["ReceiverDatumElevation"] = {"pos": 52, "type": "int32"} # 'int32'); %52 187 | STH_def["SourceDatumElevation"] = {"pos": 56, "type": "int32"} # 'int32'); %56 188 | STH_def["SourceWaterDepth"] = {"pos": 60, "type": "int32"} # 'int32'); %60 189 | STH_def["GroupWaterDepth"] = {"pos": 64, "type": "int32"} # 'int32'); %64 190 | STH_def["ElevationScalar"] = {"pos": 68, "type": "int16"} # 'int16'); %68 191 | STH_def["SourceGroupScalar"] = {"pos": 70, "type": "int16"} # 'int16'); %70 192 | STH_def["SourceX"] = {"pos": 72, "type": "int32"} # 'int32'); %72 193 | STH_def["SourceY"] = {"pos": 76, "type": "int32"} # 'int32'); %76 194 | STH_def["GroupX"] = {"pos": 80, "type": "int32"} # 'int32'); %80 195 | STH_def["GroupY"] = {"pos": 84, "type": "int32"} # 'int32'); %84 196 | STH_def["CoordinateUnits"] = {"pos": 88, "type": "int16"} # 'int16'); %88 197 | STH_def["CoordinateUnits"]["descr"] = {1: { 198 | 1: "Length (meters or feet)", 199 | 2: "Seconds of arc"}} 200 | STH_def["CoordinateUnits"]["descr"][1] = { 201 | 1: "Length (meters or feet)", 202 | 2: "Seconds of arc", 203 | 3: "Decimal degrees", 204 | 4: "Degrees, minutes, seconds (DMS)"} 205 | STH_def["WeatheringVelocity"] = {"pos": 90, "type": "int16"} # 'int16'); %90 206 | STH_def["SubWeatheringVelocity"] = {"pos": 92, "type": "int16"} # 'int16'); %92 207 | STH_def["SourceUpholeTime"] = {"pos": 94, "type": "int16"} # 'int16'); %94 208 | STH_def["GroupUpholeTime"] = {"pos": 96, "type": "int16"} # 'int16'); %96 209 | STH_def["SourceStaticCorrection"] = {"pos": 98, "type": "int16"} # 'int16'); %98 210 | STH_def["GroupStaticCorrection"] = {"pos": 100, "type": "int16"} # 'int16'); %100 211 | STH_def["TotalStaticApplied"] = {"pos": 102, "type": "int16"} # 'int16'); %102 212 | STH_def["LagTimeA"] = {"pos": 104, "type": "int16"} # 'int16'); %104 213 | STH_def["LagTimeB"] = {"pos": 106, "type": "int16"} # 'int16'); %106 214 | STH_def["DelayRecordingTime"] = {"pos": 108, "type": "int16"} # 'int16'); %108 215 | STH_def["MuteTimeStart"] = {"pos": 110, "type": "int16"} # 'int16'); %110 216 | STH_def["MuteTimeEND"] = {"pos": 112, "type": "int16"} # 'int16'); %112 217 | STH_def["ns"] = {"pos": 114, "type": "uint16"} # 'uint16'); %114 218 | STH_def["dt"] = {"pos": 116, "type": "uint16"} # 'uint16'); %116 219 | STH_def["GainType"] = {"pos": 119, "type": "int16"} # 'int16'); %118 220 | STH_def["GainType"]["descr"] = {0: { 221 | 1: "Fixes", 222 | 2: "Binary", 223 | 3: "Floating point"}} 224 | STH_def["GainType"]["descr"][1] = STH_def["GainType"]["descr"][0] 225 | STH_def["InstrumentGainConstant"] = {"pos": 120, "type": "int16"} # 'int16'); %120 226 | STH_def["InstrumentInitialGain"] = {"pos": 122, "type": "int16"} # 'int16'); %%122 227 | STH_def["Correlated"] = {"pos": 124, "type": "int16"} # 'int16'); %124 228 | STH_def["Correlated"]["descr"] = {0: { 229 | 1: "No", 230 | 2: "Yes"}} 231 | STH_def["Correlated"]["descr"][1] = STH_def["Correlated"]["descr"][0] 232 | 233 | STH_def["SweepFrequenceStart"] = {"pos": 126, "type": "int16"} # 'int16'); %126 234 | STH_def["SweepFrequenceEnd"] = {"pos": 128, "type": "int16"} # 'int16'); %128 235 | STH_def["SweepLength"] = {"pos": 130, "type": "int16"} # 'int16'); %130 236 | STH_def["SweepType"] = {"pos": 132, "type": "int16"} # 'int16'); %132 237 | STH_def["SweepType"]["descr"] = {0: { 238 | 1: "linear", 239 | 2: "parabolic", 240 | 3: "exponential", 241 | 4: "other"}} 242 | STH_def["SweepType"]["descr"][1] = STH_def["SweepType"]["descr"][0] 243 | 244 | STH_def["SweepTraceTaperLengthStart"] = {"pos": 134, "type": "int16"} # 'int16'); %134 245 | STH_def["SweepTraceTaperLengthEnd"] = {"pos": 136, "type": "int16"} # 'int16'); %136 246 | STH_def["TaperType"] = {"pos": 138, "type": "int16"} # 'int16'); %138 247 | STH_def["TaperType"]["descr"] = {0: { 248 | 1: "linear", 249 | 2: "cos2c", 250 | 3: "other"}} 251 | STH_def["TaperType"]["descr"][1] = STH_def["TaperType"]["descr"][0] 252 | 253 | STH_def["AliasFilterFrequency"] = {"pos": 140, "type": "int16"} # 'int16'); %140 254 | STH_def["AliasFilterSlope"] = {"pos": 142, "type": "int16"} # 'int16'); %142 255 | STH_def["NotchFilterFrequency"] = {"pos": 144, "type": "int16"} # 'int16'); %144 256 | STH_def["NotchFilterSlope"] = {"pos": 146, "type": "int16"} # 'int16'); %146 257 | STH_def["LowCutFrequency"] = {"pos": 148, "type": "int16"} # 'int16'); %148 258 | STH_def["HighCutFrequency"] = {"pos": 150, "type": "int16"} # 'int16'); %150 259 | STH_def["LowCutSlope"] = {"pos": 152, "type": "int16"} # 'int16'); %152 260 | STH_def["HighCutSlope"] = {"pos": 154, "type": "int16"} # 'int16'); %154 261 | STH_def["YearDataRecorded"] = {"pos": 156, "type": "int16"} # 'int16'); %156 262 | STH_def["DayOfYear"] = {"pos": 158, "type": "int16"} # 'int16'); %158 263 | STH_def["HourOfDay"] = {"pos": 160, "type": "int16"} # 'int16'); %160 264 | STH_def["MinuteOfHour"] = {"pos": 162, "type": "int16"} # 'int16'); %162 265 | STH_def["SecondOfMinute"] = {"pos": 164, "type": "int16"} # 'int16'); %164 266 | STH_def["TimeBaseCode"] = {"pos": 166, "type": "int16"} # 'int16'); %166 267 | STH_def["TimeBaseCode"]["descr"] = {0: { 268 | 1: "Local", 269 | 2: "GMT", 270 | 3: "Other"}} 271 | STH_def["TimeBaseCode"]["descr"][1] = { 272 | 1: "Local", 273 | 2: "GMT", 274 | 3: "Other", 275 | 4: "UTC"} 276 | STH_def["TraceWeightningFactor"] = {"pos": 168, "type": "int16"} # 'int16'); %170 277 | STH_def["GeophoneGroupNumberRoll1"] = {"pos": 170, "type": "int16"} # 'int16'); %172 278 | STH_def["GeophoneGroupNumberFirstTraceOrigField"] = {"pos": 172, "type": "int16"} # 'int16'); %174 279 | STH_def["GeophoneGroupNumberLastTraceOrigField"] = {"pos": 174, "type": "int16"} # 'int16'); %176 280 | STH_def["GapSize"] = {"pos": 176, "type": "int16"} # 'int16'); %178 281 | STH_def["OverTravel"] = {"pos": 178, "type": "int16"} # 'int16'); %178 282 | STH_def["OverTravel"]["descr"] = {0: { 283 | 1: "down (or behind)", 284 | 2: "up (or ahead)", 285 | 3: "other"}} 286 | STH_def["OverTravel"]["descr"][1] = STH_def["OverTravel"]["descr"][0] 287 | 288 | STH_def["cdpX"] = {"pos": 180, "type": "int32"} # 'int32'); %180 289 | STH_def["cdpY"] = {"pos": 184, "type": "int32"} # 'int32'); %184 290 | STH_def["Inline3D"] = {"pos": 188, "type": "int32"} # 'int32'); %188 291 | STH_def["Crossline3D"] = {"pos": 192, "type": "int32"} # 'int32'); %192 292 | STH_def["ShotPoint"] = {"pos": 192, "type": "int32"} # 'int32'); %196 293 | STH_def["ShotPointScalar"] = {"pos": 200, "type": "int16"} # 'int16'); %200 294 | STH_def["TraceValueMeasurementUnit"] = {"pos": 202, "type": "int16"} # 'int16'); %202 295 | STH_def["TraceValueMeasurementUnit"]["descr"] = {1: { 296 | -1: "Other", 297 | 0: "Unknown (should be described in Data Sample Measurement Units Stanza) ", 298 | 1: "Pascal (Pa)", 299 | 2: "Volts (V)", 300 | 3: "Millivolts (v)", 301 | 4: "Amperes (A)", 302 | 5: "Meters (m)", 303 | 6: "Meters Per Second (m/s)", 304 | 7: "Meters Per Second squared (m/&s2)Other", 305 | 8: "Newton (N)", 306 | 9: "Watt (W)"}} 307 | STH_def["TransductionConstantMantissa"] = {"pos": 204, "type": "int32"} # 'int32'); %204 308 | STH_def["TransductionConstantPower"] = {"pos": 208, "type": "int16"} # 'int16'); %208 309 | STH_def["TransductionUnit"] = {"pos": 210, "type": "int16"} # 'int16'); %210 310 | STH_def["TransductionUnit"]["descr"] = STH_def["TraceValueMeasurementUnit"]["descr"] 311 | STH_def["TraceIdentifier"] = {"pos": 212, "type": "int16"} # 'int16'); %212 312 | STH_def["ScalarTraceHeader"] = {"pos": 214, "type": "int16"} # 'int16'); %214 313 | STH_def["SourceType"] = {"pos": 216, "type": "int16"} # 'int16'); %216 314 | STH_def["SourceType"]["descr"] = {1: { 315 | -1: "Other (should be described in Source Type/Orientation stanza)", 316 | 0: "Unknown", 317 | 1: "Vibratory - Vertical orientation", 318 | 2: "Vibratory - Cross-line orientation", 319 | 3: "Vibratory - In-line orientation", 320 | 4: "Impulsive - Vertical orientation", 321 | 5: "Impulsive - Cross-line orientation", 322 | 6: "Impulsive - In-line orientation", 323 | 7: "Distributed Impulsive - Vertical orientation", 324 | 8: "Distributed Impulsive - Cross-line orientation", 325 | 9: "Distributed Impulsive - In-line orientation"}} 326 | 327 | STH_def["SourceEnergyDirectionMantissa"] = {"pos": 218, "type": "int32"} # 'int32'); %218 328 | STH_def["SourceEnergyDirectionExponent"] = {"pos": 222, "type": "int16"} # 'int16'); %222 329 | STH_def["SourceMeasurementMantissa"] = {"pos": 224, "type": "int32"} # 'int32'); %224 330 | STH_def["SourceMeasurementExponent"] = {"pos": 228, "type": "int16"} # 'int16'); %228 331 | STH_def["SourceMeasurementUnit"] = {"pos": 230, "type": "int16"} # 'int16'); %230 332 | STH_def["SourceMeasurementUnit"]["descr"] = {1: { 333 | -1: "Other (should be described in Source Measurement Unit stanza)", 334 | 0: "Unknown", 335 | 1: "Joule (J)", 336 | 2: "Kilowatt (kW)", 337 | 3: "Pascal (Pa)", 338 | 4: "Bar (Bar)", 339 | 4: "Bar-meter (Bar-m)", 340 | 5: "Newton (N)", 341 | 6: "Kilograms (kg)"}} 342 | STH_def["UnassignedInt1"] = {"pos": 232, "type": "int32"} # 'int32'); %232 343 | STH_def["UnassignedInt2"] = {"pos": 236, "type": "int32"} # 'int32'); %236 344 | 345 | 346 | ############## 347 | # %% FUNCTIONS 348 | 349 | def image(Data, SH={}, maxval=-1): 350 | """ 351 | image(Data,SH,maxval) 352 | Image segy Data 353 | """ 354 | import matplotlib.pylab as plt 355 | 356 | if (maxval<=0): 357 | Dmax = np.max(Data) 358 | maxval = -1*maxval*Dmax 359 | 360 | if 'time' in SH: 361 | t = SH['time'] 362 | ntraces = SH['ntraces'] 363 | ns = SH['ns'] 364 | else: 365 | ns = Data.shape[0] 366 | t = np.arange(ns) 367 | ntraces = Data.shape[1] 368 | x = np.arange(ntraces)+1 369 | 370 | print(maxval) 371 | plt.pcolor(x, t, Data, vmin=-1*maxval, vmax=maxval) 372 | plt.colorbar() 373 | plt.axis('normal') 374 | plt.xlabel('Trace number') 375 | if 'time' in SH: 376 | plt.ylabel('Time (ms)') 377 | else: 378 | plt.ylabel('Sample number') 379 | if 'filename' in SH: 380 | plt.title(SH['filename']) 381 | plt.gca().invert_yaxis() 382 | 383 | #plt.grid(True) 384 | plt.show() 385 | 386 | 387 | # %% 388 | def wiggle(Data, SH={}, maxval=-1, skipt=1, lwidth=.1): 389 | """ 390 | wiggle(Data,SH) 391 | """ 392 | import matplotlib.pylab as plt 393 | import numpy as np 394 | 395 | if 'time' in SH: 396 | t = SH['time'] 397 | ntraces = SH['ntraces'] 398 | ns = SH['ns'] 399 | else: 400 | ns=Data.shape[0] 401 | t=np.arange(ns) 402 | ntraces = Data.shape[1] 403 | 404 | 405 | if (maxval<=0): 406 | Dmax = np.max(Data) 407 | maxval = -1*maxval*Dmax 408 | 409 | for i in range(0, ntraces, skipt): 410 | trace = Data[:, i] 411 | trace[0] = 0 412 | trace[ns - 1] = 0 413 | plt.plot(i + trace / maxval, t, color='black', linewidth=lwidth) 414 | for a in range(len(trace)): 415 | if (trace[a] < 0): 416 | trace[a] = 0; 417 | # pylab.fill(i+Data[:,i]/maxval,t,color='k',facecolor='g') 418 | plt.fill(i + Data[:, i] / maxval, t, 'k', linewidth=0) 419 | 420 | plt.grid(True) 421 | plt.gca().invert_yaxis() 422 | 423 | plt.xlabel('Trace number') 424 | if 'time' in SH: 425 | plt.ylabel('Time (ms)') 426 | else: 427 | plt.ylabel('Sample number') 428 | if 'filename' in SH: 429 | plt.title(SH['filename']) 430 | plt.axes().set_xlim(-1, ntraces) 431 | plt.show() 432 | 433 | 434 | # %% 435 | def getDefaultSegyHeader(ntraces=100, ns=100): 436 | """ 437 | SH=getDefaultSegyHeader() 438 | """ 439 | # INITIALIZE DICTIONARY 440 | SH = {"Job": {"pos": 3200, "type": "int32", "def": 0}} 441 | 442 | for key in SH_def.keys(): 443 | 444 | tmpkey = SH_def[key] 445 | if (tmpkey.has_key('def')): 446 | val = tmpkey['def'] 447 | else: 448 | val = 0 449 | SH[key] = val 450 | 451 | SH["ntraces"] = ntraces; 452 | SH["ns"] = ns; 453 | 454 | return SH 455 | 456 | 457 | # %% 458 | def getDefaultSegyTraceHeaders(ntraces=100, ns=100, dt=1000): 459 | """ 460 | SH=getDefaultSegyTraceHeader() 461 | """ 462 | # INITIALIZE DICTIONARY 463 | STH = {"TraceSequenceLine": {"pos": 0, "type": "int32"}} 464 | 465 | for key in STH_def.keys(): 466 | 467 | tmpkey = STH_def[key] 468 | if (tmpkey.has_key('def')): 469 | val = tmpkey['def'] 470 | else: 471 | val = 0 472 | STH[key] = np.zeros(ntraces) 473 | 474 | for a in range(ntraces): 475 | STH["TraceSequenceLine"][a] = a + 1 476 | STH["TraceSequenceFile"][a] = a + 1 477 | STH["FieldRecord"][a] = 1000 478 | STH["TraceNumber"][a] = a + 1 479 | STH["ns"][a] = ns 480 | STH["dt"][a] = dt 481 | return STH 482 | 483 | 484 | # %% 485 | def getSegyTraceHeader(SH, THN='cdp', data='none', endian='>'): # modified by A Squelch 486 | """ 487 | getSegyTraceHeader(SH,TraceHeaderName) 488 | """ 489 | 490 | bps = getBytePerSample(SH) 491 | 492 | if (data == 'none'): 493 | data = open(SH["filename"], 'rb').read() 494 | 495 | # MAKE SOME LOOKUP TABLE THAT HOLDS THE LOCATION OF HEADERS 496 | # THpos=TraceHeaderPos[THN] 497 | THpos = STH_def[THN]["pos"] 498 | THformat = STH_def[THN]["type"] 499 | ntraces = SH["ntraces"] 500 | thv = np.zeros(ntraces) 501 | for itrace in range(1, ntraces + 1, 1): 502 | i = itrace 503 | 504 | pos = THpos + 3600 + (SH["ns"] * bps + 240) * (itrace - 1); 505 | 506 | txt = "getSegyTraceHeader : Reading trace header " + THN + " " + str(itrace) + " of " + str( 507 | ntraces) + " " + str(pos) 508 | 509 | printverbose(txt, 20); 510 | thv[itrace - 1], index = getValue(data, pos, THformat, endian, 1) 511 | txt = "getSegyTraceHeader : " + THN + "=" + str(thv[itrace - 1]) 512 | printverbose(txt, 30); 513 | 514 | return thv 515 | 516 | 517 | # %% 518 | def getLastSegyTraceHeader(SH, THN='cdp', data='none', endian='>'): # added by A Squelch 519 | """ 520 | getLastSegyTraceHeader(SH,TraceHeaderName) 521 | """ 522 | 523 | bps = getBytePerSample(SH) 524 | 525 | if (data == 'none'): 526 | data = open(SH["filename"]).read() 527 | 528 | # SET PARAMETERS THAT DEFINE THE LOCATION OF THE LAST HEADER 529 | # AND THE TRACE NUMBER KEY FIELD 530 | THpos = STH_def[THN]["pos"] 531 | THformat = STH_def[THN]["type"] 532 | ntraces = SH["ntraces"] 533 | 534 | pos = THpos + 3600 + (SH["ns"] * bps + 240) * (ntraces - 1); 535 | 536 | txt = "getLastSegyTraceHeader : Reading last trace header " + THN + " " + str(pos) 537 | 538 | printverbose(txt, 20); 539 | thv, index = getValue(data, pos, THformat, endian, 1) 540 | txt = "getLastSegyTraceHeader : " + THN + "=" + str(thv) 541 | printverbose(txt, 30); 542 | 543 | return thv 544 | 545 | 546 | # %% 547 | def getAllSegyTraceHeaders(SH, data='none'): 548 | SegyTraceHeaders = {'filename': SH["filename"]} 549 | 550 | printverbose('getAllSegyTraceHeaders : trying to get all segy trace headers', 2) 551 | 552 | if (data == 'none'): 553 | data = open(SH["filename"], 'rb').read() 554 | 555 | for key in STH_def.keys(): 556 | sth = getSegyTraceHeader(SH, key, data) 557 | SegyTraceHeaders[key] = sth 558 | txt = "getAllSegyTraceHeaders : " + key 559 | printverbose(txt, 10) 560 | 561 | return SegyTraceHeaders 562 | 563 | 564 | # %% 565 | def readSegy(filename, endian='>'): # modified by A Squelch 566 | """ 567 | Data,SegyHeader,SegyTraceHeaders=getSegyHeader(filename) 568 | """ 569 | 570 | printverbose("readSegy : Trying to read " + filename, 0) 571 | 572 | data = open(filename, 'rb').read() 573 | 574 | filesize = len(data) 575 | 576 | SH = getSegyHeader(filename, endian) # modified by A Squelch 577 | 578 | bps = getBytePerSample(SH) 579 | 580 | ntraces = (filesize - 3600) / (SH['ns'] * bps + 240) 581 | # ntraces = 100 582 | 583 | printverbose("readSegy : Length of data : " + str(filesize), 2) 584 | 585 | SH["ntraces"] = np.int(ntraces); 586 | 587 | # ndummy_samples=240/bps # modified by A Squelch 588 | # printverbose("readSegy : ndummy_samples="+str(ndummy_samples),6) # modified by A Squelch 589 | printverbose("readSegy : ntraces=" + str(ntraces) + " nsamples=" + str(SH['ns']), 2) 590 | 591 | # GET TRACE 592 | index = 3600; 593 | nd = int((filesize - 3600) / bps) 594 | 595 | printverbose("filesize=%d" % filesize) 596 | printverbose("bps=%5d" % bps) 597 | printverbose("nd=%5d" % nd) 598 | 599 | # modified by A Squelch 600 | # this portion replaced by call to new function: readSegyData 601 | Data, SH, SegyTraceHeaders = readSegyData(data, SH, nd, bps, index, endian) 602 | 603 | printverbose("readSegy : Read segy data", 2) # modified by A Squelch 604 | 605 | return Data, SH, SegyTraceHeaders 606 | 607 | 608 | # %% 609 | def readSegyData(data, SH, nd, bps, index, endian='>'): # added by A Squelch 610 | """ 611 | Data,SegyHeader,SegyTraceHeaders=readSegyData(data,SH,nd,bps,index) 612 | 613 | This function separated out from readSegy so that it can also be 614 | called from other external functions - by A Squelch. 615 | """ 616 | 617 | # Calulate number of dummy samples needed to account for Trace Headers 618 | ndummy_samples = int(240 / bps) 619 | printverbose("readSegyData : ndummy_samples=" + str(ndummy_samples), 6) 620 | 621 | # READ ALL SEGY TRACE HEADRES 622 | STH = getAllSegyTraceHeaders(SH, data) 623 | 624 | printverbose("readSegyData : Reading segy data", 1) 625 | 626 | # READ ALL DATA EXCEPT FOR SEGY HEADER 627 | # Data = np.zeros((SH['ns'],ntraces)) 628 | 629 | revision = SH["SegyFormatRevisionNumber"] 630 | if (revision == 100): 631 | revision = 1 632 | if (revision == 256): # added by A Squelch 633 | revision = 1 634 | 635 | dsf = SH["DataSampleFormat"] 636 | 637 | try: # block added by A Squelch 638 | DataDescr = SH_def["DataSampleFormat"]["descr"][revision][dsf] 639 | except KeyError: 640 | print("") 641 | print(" An error has ocurred interpreting a SEGY binary header key") 642 | print(" Please check the Endian setting for this file: ", SH["filename"]) 643 | sys.exit() 644 | 645 | printverbose("readSegyData : SEG-Y revision = " + str(revision), 1) 646 | printverbose("readSegyData : DataSampleFormat=" + str(dsf) + "(" + DataDescr + ")", 1) 647 | 648 | if (SH["DataSampleFormat"] == 1): 649 | printverbose("readSegyData : Assuming DSF=1, IBM FLOATS", 2) 650 | Data1 = getValue(data, index, 'ibm', endian, nd) 651 | elif (SH["DataSampleFormat"] == 2): 652 | printverbose("readSegyData : Assuming DSF=" + str(SH["DataSampleFormat"]) + ", 32bit INT", 2) 653 | Data1 = getValue(data, index, 'l', endian, nd) 654 | elif (SH["DataSampleFormat"] == 3): 655 | printverbose("readSegyData : Assuming DSF=" + str(SH["DataSampleFormat"]) + ", 16bit INT", 2) 656 | Data1 = getValue(data, index, 'h', endian, nd) 657 | elif (SH["DataSampleFormat"] == 5): 658 | printverbose("readSegyData : Assuming DSF=" + str(SH["DataSampleFormat"]) + ", IEEE", 2) 659 | Data1 = getValue(data, index, 'float', endian, nd) 660 | elif (SH["DataSampleFormat"] == 8): 661 | printverbose("readSegyData : Assuming DSF=" + str(SH["DataSampleFormat"]) + ", 8bit CHAR", 2) 662 | Data1 = getValue(data, index, 'B', endian, nd) 663 | else: 664 | printverbose("readSegyData : DSF=" + str(SH["DataSampleFormat"]) + ", NOT SUPORTED", 2) 665 | 666 | Data = Data1[0] 667 | 668 | printverbose("readSegyData : - reshaping", 2) 669 | printverbose(" ns=" + str(SH['ns']),-2) 670 | Data = np.reshape(np.array(Data), (SH['ntraces'], SH['ns'] + ndummy_samples)) 671 | printverbose("readSegyData : - stripping header dummy data", 2) 672 | Data = Data[:, ndummy_samples:(SH['ns'] + ndummy_samples)] 673 | printverbose("readSegyData : - transposing", 2) 674 | Data = np.transpose(Data) 675 | 676 | # SOMEONE NEEDS TO IMPLEMENT A NICER WAY DO DEAL WITH DSF=8 677 | if (SH["DataSampleFormat"] == 8): 678 | for i in np.arange(SH['ntraces']): 679 | for j in np.arange(SH['ns']): 680 | if Data[i][j] > 128: 681 | Data[i][j] = Data[i][j] - 256 682 | 683 | printverbose("readSegyData : Finished reading segy data", 1) 684 | 685 | return Data, SH, STH 686 | 687 | 688 | # %% 689 | def getSegyTrace(SH, itrace, endian='>'): # modified by A Squelch 690 | """ 691 | SegyTraceHeader,SegyTraceData=getSegyTrace(SegyHeader,itrace) 692 | itrace : trace number to read 693 | THIS DEF IS NOT UPDATED. NOT READY TO USE 694 | """ 695 | data = open(SH["filename"], 'rb').read() 696 | 697 | bps = getBytePerSample(SH) 698 | 699 | # GET TRACE HEADER 700 | index = 3200 + (itrace - 1) * (240 + SH['ns'] * bps) 701 | SegyTraceHeader = []; 702 | # print index 703 | 704 | # GET TRACE 705 | index = 3200 + (itrace - 1) * (240 + SH['ns'] * bps) + 240 706 | SegyTraceData = getValue(data, index, 'float', endian, SH['ns']) 707 | return SegyTraceHeader, SegyTraceData 708 | 709 | 710 | # %% 711 | def getSegyHeader(filename, endian='>'): # modified by A Squelch 712 | """ 713 | SegyHeader=getSegyHeader(filename) 714 | """ 715 | 716 | data = open(filename, 'rb').read() 717 | 718 | SegyHeader = {'filename': filename} 719 | 720 | j = 0; 721 | for key in SH_def.keys(): 722 | j = j + 1; 723 | pos = SH_def[key]["pos"] 724 | format = SH_def[key]["type"] 725 | 726 | txt = "i=%3d, pos=%5d, format=%2s, key=%s" % (j, pos, format, key); 727 | printverbose(txt, 10) 728 | 729 | SegyHeader[key], index = getValue(data, pos, format, endian); 730 | 731 | txt = "SegyHeader[%s] = %f" % (key, SegyHeader[key]) 732 | printverbose(txt, 2) 733 | 734 | # SET NUMBER OF BYTES PER DATA SAMPLE 735 | bps = getBytePerSample(SegyHeader) 736 | 737 | filesize = len(data) 738 | ntraces = (filesize - 3600) / (SegyHeader['ns'] * bps + 240) 739 | SegyHeader["ntraces"] = ntraces 740 | SegyHeader["time"]=np.arange(SegyHeader['ns']) * SegyHeader['dt'] / 1e+6 741 | 742 | 743 | printverbose('getSegyHeader : succesfully read ' + filename, 1) 744 | 745 | return SegyHeader 746 | 747 | 748 | # %% 749 | def writeSegy(filename, Data, dt=1000, STHin={}, SHin={}): 750 | """ 751 | writeSegy(filename,Data,dt) 752 | 753 | Write SEGY 754 | 755 | See also readSegy 756 | 757 | (c) 2005, Thomas Mejer Hansen 758 | 759 | MAKE OPTIONAL INPUT FOR ALL SEGYHTRACEHEADER VALUES 760 | 761 | """ 762 | 763 | printverbose("writeSegy : Trying to write " + filename, 0) 764 | 765 | N = Data.shape 766 | ns = N[0] 767 | ntraces = N[1] 768 | print(ntraces) 769 | print(ns) 770 | 771 | SH = getDefaultSegyHeader(ntraces, ns); 772 | STH = getDefaultSegyTraceHeaders(ntraces, ns, dt) 773 | 774 | # ADD STHin, if exists... 775 | for key in STHin.keys(): 776 | print(key) 777 | for a in range(ntraces): 778 | STH[key] = STHin[key][a] 779 | 780 | # ADD SHin, if exists... 781 | for key in SHin.keys(): 782 | print(key) 783 | SH[key] = SHin[key] 784 | 785 | writeSegyStructure(filename, Data, SH, STH) 786 | 787 | 788 | # %% 789 | def writeSegyStructure(filename, Data, SH, STH, endian='>'): # modified by A Squelch 790 | """ 791 | writeSegyStructure(filename,Data,SegyHeader,SegyTraceHeaders) 792 | 793 | Write SEGY file using SegyPy data structures 794 | 795 | See also readSegy 796 | 797 | (c) 2005, Thomas Mejer Hansen 798 | 799 | """ 800 | 801 | printverbose("writeSegyStructure : Trying to write " + filename, 0) 802 | 803 | f = open(filename, 'wb') 804 | 805 | # VERBOSE INF 806 | revision = SH["SegyFormatRevisionNumber"] 807 | dsf = SH["DataSampleFormat"] 808 | if (revision == 100): 809 | revision = 1 810 | if (revision == 256): # added by A Squelch 811 | revision = 1 812 | 813 | try: # block added by A Squelch 814 | DataDescr = SH_def["DataSampleFormat"]["descr"][revision][dsf] 815 | except KeyError: 816 | print("") 817 | print(" An error has ocurred interpreting a SEGY binary header key") 818 | print(" Please check the Endian setting for this file: ", SH["filename"]) 819 | sys.exit() 820 | 821 | printverbose("writeSegyStructure : SEG-Y revision = " + str(revision), 1) 822 | printverbose("writeSegyStructure : DataSampleFormat=" + str(dsf) + "(" + DataDescr + ")", 1) 823 | 824 | # WRITE SEGY HEADER 825 | 826 | for key in SH_def.keys(): 827 | pos = SH_def[key]["pos"] 828 | format = SH_def[key]["type"] 829 | value = SH[key] 830 | 831 | # SegyHeader[key],index = putValue(value,f,pos,format,endian); 832 | putValue(value, f, pos, format, endian); 833 | 834 | txt = str(pos) + " " + str(format) + " Reading " + key + "=" + str(value) 835 | # +"="+str(SegyHeader[key]) 836 | # printverbose(txt,-1) 837 | 838 | # SEGY TRACES 839 | 840 | ctype = SH_def['DataSampleFormat']['datatype'][revision][dsf] 841 | bps = SH_def['DataSampleFormat']['bps'][revision][dsf] 842 | 843 | sizeT = 240 + SH['ns'] * bps; 844 | 845 | for itrace in range(SH['ntraces']): 846 | index = 3600 + itrace * sizeT 847 | printverbose('Writing Trace #' + str(itrace + 1) + '/' + str(SH['ntraces']), 10) 848 | # WRITE SEGY TRACE HEADER 849 | for key in STH_def.keys(): 850 | pos = index + STH_def[key]["pos"] 851 | format = STH_def[key]["type"] 852 | value = STH[key][itrace] 853 | txt = str(pos) + " " + str(format) + " Writing " + key + "=" + str(value) 854 | printverbose(txt, 40) 855 | putValue(value, f, pos, format, endian); 856 | 857 | # Write Data 858 | cformat = endian + ctype 859 | for s in range(SH['ns']): 860 | strVal = struct.pack(cformat, Data[s, itrace]) 861 | f.seek(index + 240 + s * struct.calcsize(cformat)) 862 | f.write(strVal); 863 | 864 | f.close 865 | 866 | # return segybuffer 867 | 868 | 869 | # %% 870 | def putValue(value, fileid, index, ctype='l', endian='>', number=1): 871 | """ 872 | putValue(data,index,ctype,endian,number) 873 | """ 874 | if (ctype == 'l') | (ctype == 'long') | (ctype == 'int32'): 875 | size = l_long 876 | ctype = 'l' 877 | elif (ctype == 'L') | (ctype == 'ulong') | (ctype == 'uint32'): 878 | size = l_ulong 879 | ctype = 'L' 880 | elif (ctype == 'h') | (ctype == 'short') | (ctype == 'int16'): 881 | size = l_short 882 | ctype = 'h' 883 | elif (ctype == 'H') | (ctype == 'ushort') | (ctype == 'uint16'): 884 | size = l_ushort 885 | ctype = 'H' 886 | elif (ctype == 'c') | (ctype == 'char'): 887 | size = l_char 888 | ctype = 'c' 889 | elif (ctype == 'B') | (ctype == 'uchar'): 890 | size = l_uchar 891 | ctype = 'B' 892 | elif (ctype == 'f') | (ctype == 'float'): 893 | size = l_float 894 | ctype = 'f' 895 | elif (ctype == 'ibm'): 896 | size = l_float 897 | else: 898 | printverbose('Bad Ctype : ' + ctype, -1) 899 | 900 | cformat = endian + ctype * number 901 | 902 | printverbose('putValue : cformat : ' + cformat + ' ctype=' + ctype, 40) 903 | 904 | strVal = struct.pack(cformat, value) 905 | fileid.seek(index) 906 | fileid.write(strVal); 907 | 908 | return 1 909 | 910 | 911 | # %% 912 | def getValue(data, index, ctype='l', endian='>', number=1): 913 | """ 914 | getValue(data,index,ctype,endian,number) 915 | """ 916 | if (ctype == 'l') | (ctype == 'long') | (ctype == 'int32'): 917 | size = l_long 918 | ctype = 'l' 919 | elif (ctype == 'L') | (ctype == 'ulong') | (ctype == 'uint32'): 920 | size = l_ulong 921 | ctype = 'L' 922 | elif (ctype == 'h') | (ctype == 'short') | (ctype == 'int16'): 923 | size = l_short 924 | ctype = 'h' 925 | elif (ctype == 'H') | (ctype == 'ushort') | (ctype == 'uint16'): 926 | size = l_ushort 927 | ctype = 'H' 928 | elif (ctype == 'c') | (ctype == 'char'): 929 | size = l_char 930 | ctype = 'c' 931 | elif (ctype == 'B') | (ctype == 'uchar'): 932 | size = l_uchar 933 | ctype = 'B' 934 | elif (ctype == 'f') | (ctype == 'float'): 935 | size = l_float 936 | ctype = 'f' 937 | elif (ctype == 'ibm'): 938 | size = l_float 939 | ctype = 'ibm' 940 | else: 941 | printverbose('Bad Ctype : ' + ctype, -1) 942 | 943 | index_end = index + size * number 944 | 945 | printverbose("index=%d, number=%d, size=%d, ctype=%s" % (index, number, size, ctype), 8); 946 | printverbose("index, index_end = " + str(index) + "," + str(index_end), 9) 947 | 948 | if (ctype == 'ibm'): 949 | # ASSUME IBM FLOAT DATA 950 | Value = list(range(int(number))) 951 | for i in np.arange(number): 952 | index_ibm_start = i * 4 + index 953 | index_ibm_end = index_ibm_start + 4; 954 | ibm_val = ibm2ieee2(data[index_ibm_start:index_ibm_end]) 955 | Value[i] = ibm_val; 956 | # this resturn an array as opposed to a tuple 957 | else: 958 | # ALL OTHER TYPES OF DATA 959 | cformat = 'f' * number 960 | cformat = endian + ctype * number 961 | 962 | printverbose("getValue : cformat : '" + cformat + "'", 11) 963 | 964 | Value = struct.unpack(cformat, data[index:index_end]) 965 | 966 | if (ctype == 'B'): 967 | printverbose('getValue : Ineficient use of 1byte Integer...', -1) 968 | 969 | vtxt = 'getValue : ' + 'start=' + str(index) + ' size=' + str(size) + ' number=' + str( 970 | number) + ' Value=' + str(Value) + ' cformat=' + str(cformat) 971 | printverbose(vtxt, 20) 972 | 973 | if number == 1: 974 | return Value[0], index_end 975 | else: 976 | return Value, index_end 977 | 978 | 979 | # %% 980 | def print_version(): 981 | print('SegyPY version is ', version) 982 | 983 | 984 | # %% 985 | def printverbose(txt, level=1): 986 | if level <= verbose: 987 | print('SegyPY' + version + ': ', txt) 988 | 989 | 990 | # %% 991 | ############## 992 | # MISC FUNCTIONS 993 | def ibm2Ieee(ibm_float): 994 | """ 995 | ibm2Ieee(ibm_float) 996 | Used by permission 997 | (C) Secchi Angelo 998 | with thanks to Howard Lightstone and Anton Vredegoor. 999 | """ 1000 | """ 1001 | I = struct.unpack('>I',ibm_float)[0] 1002 | sign = [1,-1][bool(i & 0x100000000L)] 1003 | characteristic = ((i >> 24) & 0x7f) - 64 1004 | fraction = (i & 0xffffff)/float(0x1000000L) 1005 | return sign*16**characteristic*fraction 1006 | """ 1007 | 1008 | 1009 | def ibm2ieee2(ibm_float): 1010 | """ 1011 | ibm2ieee2(ibm_float) 1012 | Used by permission 1013 | (C) Secchi Angelo 1014 | with thanks to Howard Lightstone and Anton Vredegoor. 1015 | """ 1016 | dividend = float(16 ** 6) 1017 | 1018 | if ibm_float == 0: 1019 | return 0.0 1020 | istic, a, b, c = struct.unpack('>BBBB', ibm_float) 1021 | if istic >= 128: 1022 | sign = -1.0 1023 | istic = istic - 128 1024 | else: 1025 | sign = 1.0 1026 | mant = float(a << 16) + float(b << 8) + float(c) 1027 | return sign * 16 ** (istic - 64) * (mant / dividend) 1028 | 1029 | 1030 | def getBytePerSample(SH): 1031 | revision = SH["SegyFormatRevisionNumber"] 1032 | if (revision == 100): 1033 | revision = 1 1034 | if (revision == 256): # added by A Squelch 1035 | revision = 1 1036 | 1037 | dsf = SH["DataSampleFormat"] 1038 | 1039 | try: # block added by A Squelch 1040 | bps = SH_def["DataSampleFormat"]["bps"][revision][dsf] 1041 | except KeyError: 1042 | print("") 1043 | print(" An error has ocurred interpreting a SEGY binary header key") 1044 | print(" Please check the Endian setting for this file: ", SH["filename"]) 1045 | sys.exit() 1046 | 1047 | printverbose("getBytePerSample : bps=" + str(bps), 21); 1048 | 1049 | return bps 1050 | 1051 | 1052 | ############## 1053 | # segy class 1054 | class SegyTraceheaderClass: 1055 | def __init__(self): 1056 | self.cdp = 0 1057 | 1058 | 1059 | class SegyHeaderClass: 1060 | def __str__(self): 1061 | return "SegyHeaderClass " 1062 | 1063 | def __init__(self): 1064 | self.filename = 0 1065 | self.Trace = version 1066 | 1067 | def cdp(self): 1068 | return "Getting CDP trace header" 1069 | 1070 | def InlineX(self): 1071 | return "Getting CDP trace header" 1072 | 1073 | 1074 | class SegyClass: 1075 | STH_def = STH_def 1076 | SH_def = SH_def 1077 | STH = SegyTraceheaderClass() 1078 | SH = SegyHeaderClass() 1079 | 1080 | def __init__(self): 1081 | self.THOMAS = 'Thomas' 1082 | -------------------------------------------------------------------------------- /PyOSGPUP/signalpy.py: -------------------------------------------------------------------------------- 1 | 2 | import numpy as np 3 | import numpy.fft import fft, ifft 4 | 5 | def hilbert(mag): 6 | """Compute the modified 1D discrete Hilbert transform 7 | 8 | Parameters 9 | ---------- 10 | mag : ndarray 11 | The magnitude spectrum. Should be 1D with an even length, and 12 | preferably a fast length for FFT/IFFT. 13 | """ 14 | # Adapted based on code by Niranjan Damera-Venkata, 15 | # Brian L. Evans and Shawn R. McCaslin (see refs for `minimum_phase`) 16 | sig = np.zeros(len(mag)) 17 | # Leave Nyquist and DC at 0, knowing np.abs(fftfreq(N)[midpt]) == 0.5 18 | midpt = len(mag) // 2 19 | sig[1:midpt] = 1 20 | sig[midpt+1:] = -1 21 | # eventually if we want to support complex filters, we will need a 22 | # np.abs() on the mag inside the log, and should remove the .real 23 | recon = ifft(mag * np.exp(fft(sig * ifft(np.log(mag))))).real 24 | return recon 25 | 26 | -------------------------------------------------------------------------------- /PyOSGPUP/synthe_seismo.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | import matplotlib.pyplot as plt 3 | import PyOSGPUP.wavelet as wavelet 4 | 5 | 6 | def getPlotLog(d, log, dmax=200): 7 | d = np.array(d, dtype=float) 8 | log = np.array(log, dtype=float) 9 | 10 | dplot = np.kron(d, np.ones(2)) 11 | logplot = np.kron(log, np.ones(2)) 12 | 13 | # dplot = dplot[1:] 14 | dplot = np.append(dplot[1:], dmax) 15 | 16 | return dplot, logplot 17 | 18 | 19 | def getImpedance(rholog, vlog): 20 | """ 21 | Acoustic Impedance is the product of density and velocity 22 | $$ 23 | Z = \\rho v 24 | $$ 25 | """ 26 | rholog, vlog = np.array(rholog, dtype=float), np.array(vlog, dtype=float), 27 | return rholog * vlog 28 | 29 | 30 | def getReflectivity(d, rho, v, usingT=True): 31 | """ 32 | The reflection coefficient of an interface is $$ R_i = \\frac{Z_{i+1} - Z_{i}}{Z_{i+1}+Z_{i}} $$ The reflectivity 33 | can also include the effect of transmission through above layers, in which case the reflectivity is given by $$ 34 | \\text{reflectivity} = R_i \\pi_{j = 1}^{i-1}(1-R_j^2) $$ 35 | """ 36 | Z = getImpedance(rho, v) # acoustic impedance 37 | dZ = (Z[1:] - Z[:-1]) 38 | sZ = (Z[:-1] + Z[1:]) 39 | R = dZ / sZ # reflection coefficients 40 | 41 | nlayer = len(v) # number of layers 42 | 43 | rseries = R 44 | 45 | if usingT: 46 | for i in range(nlayer - 1): 47 | rseries[i + 1:] = rseries[i + 1:] * (1. - R[i] ** 2) 48 | 49 | return rseries, R 50 | 51 | 52 | def getTimeDepth(d,v,dmax=200): 53 | """ 54 | The time depth conversion is computed by determining the two-way travel time for a reflection from a given depth. 55 | """ 56 | 57 | d = np.sort(d) 58 | d = np.append(d,dmax) 59 | 60 | twttop = 2.*np.diff(d)/v # 2-way travel time within each layer 61 | twttop = np.append(0.,twttop) 62 | twttop = np.cumsum(twttop) # 2-way travel time from surface to top of each layer 63 | 64 | return d, twttop 65 | 66 | 67 | def getLogs(d, rho, v, usingT=True): 68 | """ 69 | Function to make plotting convenient 70 | """ 71 | dpth, rholog = getPlotLog(d, rho) 72 | _, vlog = getPlotLog(d, v) 73 | zlog = getImpedance(rholog, vlog) 74 | rseries, _ = getReflectivity(d, rho, v, usingT) 75 | return dpth, rholog, vlog, zlog, rseries 76 | 77 | 78 | def plotLogFormat(log, dpth, xlim, col='blue'): 79 | """ 80 | Nice formatting for plotting logs as a function of depth 81 | """ 82 | ax = plt.plot(log, dpth, linewidth=2, color=col) 83 | plt.xlim(xlim) 84 | plt.ylim((dpth.min(), dpth.max())) 85 | plt.grid() 86 | plt.gca().invert_yaxis() 87 | plt.setp(plt.xticks()[1], rotation='90', fontsize=9) 88 | plt.setp(plt.yticks()[1], fontsize=9) 89 | 90 | return ax 91 | 92 | 93 | def plotLogs(d, rho, v, usingT=True): 94 | """ 95 | Plotting wrapper to plot density, velocity, acoustic impedance and reflectivity as a function of depth. 96 | """ 97 | d = np.sort(d) 98 | 99 | dpth, rholog, vlog, zlog, rseries = getLogs(d, rho, v, usingT) 100 | nd = len(dpth) 101 | 102 | xlimrho = (1.95, 5.05) 103 | xlimv = (0.25, 4.05) 104 | xlimz = (xlimrho[0] * xlimv[0], xlimrho[1] * xlimv[1]) 105 | 106 | # Plot Density 107 | plt.figure(1) 108 | 109 | plt.subplot(141) 110 | plotLogFormat(rholog * 10 ** -3, dpth, xlimrho, 'blue') 111 | plt.title('$\\rho$') 112 | plt.xlabel('Density \n $\\times 10^3$ (kg /m$^3$)', fontsize=9) 113 | plt.ylabel('Depth (m)', fontsize=9) 114 | 115 | plt.subplot(142) 116 | plotLogFormat(vlog * 10 ** -3, dpth, xlimv, 'red') 117 | plt.title('$v$') 118 | plt.xlabel('Velocity \n $\\times 10^3$ (m/s)', fontsize=9) 119 | plt.setp(plt.yticks()[1], visible=False) 120 | 121 | plt.subplot(143) 122 | plotLogFormat(zlog * 10. ** -6., dpth, xlimz, 'green') 123 | plt.gca().set_title('$Z = \\rho v$') 124 | plt.gca().set_xlabel('Impedance \n $\\times 10^{6}$ (kg m$^{-2}$ s$^{-1}$)', fontsize=9) 125 | plt.setp(plt.yticks()[1], visible=False) 126 | 127 | plt.subplot(144) 128 | plt.hlines(d[1:], np.zeros(nd - 1), rseries, linewidth=2) 129 | plt.plot(np.zeros(nd), dpth, linewidth=2, color='black') 130 | plt.title('Reflectivity') 131 | plt.xlim((-1., 1.)) 132 | plt.gca().set_xlabel('Reflectivity') 133 | plt.grid() 134 | plt.gca().invert_yaxis() 135 | plt.setp(plt.xticks()[1], rotation='90', fontsize=9) 136 | plt.setp(plt.yticks()[1], visible=False) 137 | 138 | plt.tight_layout() 139 | plt.show() 140 | 141 | 142 | def plotLogsInteract(d2, d3, rho1, rho2, rho3, v1, v2, v3, usingT=False): 143 | """ 144 | interactive wrapper of plotLogs 145 | """ 146 | d = np.array((0., d2, d3), dtype=float) 147 | rho = np.array((rho1, rho2, rho3), dtype=float) 148 | v = np.array((v1, v2, v3), dtype=float) 149 | plotLogs(d, rho, v, usingT) 150 | 151 | 152 | def plotTimeDepth(d,v): 153 | """ 154 | Wrapper to plot time-depth conversion based on the provided velocity model 155 | """ 156 | 157 | dpth,t = getTimeDepth(d,v) 158 | plt.figure() 159 | plt.plot(dpth,t,linewidth=2) 160 | plt.title('Depth-Time') 161 | plt.grid() 162 | plt.gca().set_xlabel('Depth (m)',fontsize=9) 163 | plt.gca().set_ylabel('Two Way Time (s)',fontsize=9) 164 | 165 | plt.tight_layout() 166 | plt.show() 167 | 168 | 169 | def syntheticSeismogram(d, rho, v, wavf, wavA=1., usingT=True, wavtyp = 'RICKER', dt=0.0001, dmax=200): 170 | """ 171 | function syntheticSeismogram(d, rho, v, wavtyp, wavf, usingT) 172 | syntheicSeismogram generates a synthetic seismogram for 173 | a simple 1-D layered model. 174 | Inputs: 175 | d : depth to the top of each layer (m) 176 | rho : density of each layer (kg/m^3) 177 | v : velocity of each layer (m/s) 178 | The last layer is assumed to be a half-space 179 | wavf : wavelet frequency 180 | wavA : wavelet amplitude 181 | usintT : using Transmission coefficients? 182 | wavtyp : type of Wavelet 183 | The wavelet options are: 184 | Ricker: takes one frequency 185 | Gaussian: still in progress 186 | Ormsby: takes 4 frequencies 187 | Klauder: takes 2 frequencies 188 | usingT : use transmission coefficients? 189 | Lindsey Heagy 190 | lheagy@eos.ubc.ca 191 | Created: November 30, 2013 192 | Modified: October 3, 2014 193 | """ 194 | 195 | v, rho, d = np.array(v, dtype=float), np.array(rho, dtype=float), np.array(d, dtype=float) 196 | usingT = np.array(usingT, dtype=bool) 197 | 198 | _, t = getTimeDepth(d,v,dmax) 199 | rseries,R = getReflectivity(d,rho,v) 200 | 201 | # time for reflectivity series 202 | tref = t[1:-1] 203 | 204 | # create time vector 205 | t = np.arange(t.min(),t.max(),dt) 206 | 207 | # make wavelet 208 | twav = np.arange(-2.0/np.min(wavf), 2.0/np.min(wavf), dt) 209 | 210 | # Get source wavelet 211 | wav = {'RICKER':wavelet.getRicker, 'ORMSBY':wavelet.getOrmsby, 'KLAUDER':wavelet.getKlauder}[wavtyp](wavf,twav) 212 | wav = wavA*wav 213 | 214 | rseriesconv = np.zeros(len(t)) 215 | for i in range(len(tref)): 216 | index = np.abs(t - tref[i]).argmin() 217 | rseriesconv[index] = rseries[i] 218 | 219 | # Do the convolution 220 | seis = np.convolve(wav,rseriesconv) 221 | tseis = np.min(twav)+dt*np.arange(len(seis)) 222 | index = np.logical_and(tseis >= 0, tseis <= np.max(t)) 223 | tseis = tseis[index] 224 | seis = seis[index] 225 | 226 | return tseis, seis, twav, wav, tref, rseries 227 | 228 | 229 | def plotSeismogram(d, rho, v, wavf, wavA=1., noise = 0., usingT=True, wavtyp='RICKER'): 230 | """ 231 | Plotting function to show physical property logs (in depth) and seismogram (in time). 232 | """ 233 | 234 | dpth, rholog, vlog, zlog, rseries = getLogs(d, rho, v, usingT) 235 | tseis, seis, twav, wav, tref, rseriesconv = syntheticSeismogram(d, rho, v, wavf, wavA, usingT,wavtyp) 236 | 237 | noise = noise*np.max(np.abs(seis))*np.random.randn(seis.size) 238 | filt = np.arange(1.,21.) 239 | filtr = filt[::-1] 240 | filt = np.append(filt,filtr[1:])*1./21. 241 | noise = np.convolve(noise,filt) 242 | noise = noise[0:seis.size] 243 | 244 | xlimrho = (1.95,5.05) 245 | xlimv = (0.25,4.05) 246 | xlimz = (xlimrho[0]*xlimv[0], xlimrho[1]*xlimv[1]) 247 | 248 | seis = seis + noise 249 | 250 | plt.figure() 251 | 252 | plt.subplot(131) 253 | plotLogFormat(rholog*10**-3,dpth,xlimrho,'blue') 254 | plt.title('$\\rho$') 255 | plt.xlabel('Density \n $\\times 10^3$ (kg /m$^3$)',fontsize=9) 256 | plt.ylabel('Depth (m)',fontsize=9) 257 | 258 | plt.subplot(132) 259 | plotLogFormat(vlog*10**-3,dpth,xlimv,'red') 260 | plt.title('$v$') 261 | plt.xlabel('Velocity \n $\\times 10^3$ (m/s)',fontsize=9) 262 | plt.ylabel('Depth (m)',fontsize=9) 263 | 264 | plt.subplot(133) 265 | plt.plot(seis,tseis,color='black',linewidth=1) 266 | plt.title('Seismogram') 267 | plt.grid() 268 | plt.ylim((tseis.min(),tseis.max())) 269 | plt.gca().invert_yaxis() 270 | plt.xlim((-0.5,0.5)) 271 | plt.setp(plt.xticks()[1],rotation='90',fontsize=9) 272 | plt.setp(plt.yticks()[1],fontsize=9) 273 | plt.gca().set_xlabel('Amplitude',fontsize=9) 274 | plt.gca().set_ylabel('Time (s)',fontsize=9) 275 | 276 | plt.tight_layout() 277 | plt.show() -------------------------------------------------------------------------------- /PyOSGPUP/tuning_wedge_acces.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | from matplotlib import gridspec 3 | import matplotlib.pyplot as plt 4 | from PyOSGPUP.signalpy import hilbert 5 | 6 | 7 | def plot_vawig(axhdl, data, t, excursion, highlight=None): 8 | [ntrc, nsamp] = data.shape 9 | 10 | t = np.hstack([0, t, t.max()]) 11 | 12 | for i in range(0, ntrc): 13 | tbuf = excursion * data[i] / np.max(np.abs(data)) + i 14 | 15 | tbuf = np.hstack([i, tbuf, i]) 16 | 17 | if i == highlight: 18 | lw = 2 19 | else: 20 | lw = 0.5 21 | 22 | axhdl.plot(tbuf, t, color='black', linewidth=lw) 23 | 24 | plt.fill_betweenx(t, tbuf, i, where=tbuf > i, facecolor=[0.6, 0.6, 1.0], linewidth=0) 25 | plt.fill_betweenx(t, tbuf, i, where=tbuf < i, facecolor=[1.0, 0.7, 0.7], linewidth=0) 26 | 27 | axhdl.set_xlim((-excursion, ntrc + excursion)) 28 | axhdl.xaxis.tick_top() 29 | axhdl.xaxis.set_label_position('top') 30 | axhdl.invert_yaxis() 31 | 32 | 33 | def ricker(cfreq, phase, dt, wvlt_length): 34 | ''' 35 | Calculate a ricker wavelet 36 | 37 | Usage: 38 | ------ 39 | t, wvlt = wvlt_ricker(cfreq, phase, dt, wvlt_length) 40 | 41 | cfreq: central frequency of wavelet in Hz 42 | phase: wavelet phase in degrees 43 | dt: sample rate in seconds 44 | wvlt_length: length of wavelet in seconds 45 | ''' 46 | 47 | nsamp = int(wvlt_length / dt + 1) 48 | t_max = wvlt_length * 0.5 49 | t_min = -t_max 50 | 51 | t = np.arange(t_min, t_max, dt) 52 | 53 | t = np.linspace(-wvlt_length / 2, (wvlt_length - dt) / 2, wvlt_length / dt) 54 | wvlt = (1.0 - 2.0 * (np.pi ** 2) * (cfreq ** 2) * (t ** 2)) * np.exp(-(np.pi ** 2) * (cfreq ** 2) * (t ** 2)) 55 | 56 | if phase != 0: 57 | phase = phase * np.pi / 180.0 58 | wvlth = hilbert(wvlt) 59 | wvlth = np.imag(wvlth) 60 | wvlt = np.cos(phase) * wvlt - np.sin(phase) * wvlth 61 | 62 | return t, wvlt 63 | 64 | 65 | def wvlt_bpass(f1, f2, f3, f4, phase, dt, wvlt_length): 66 | ''' 67 | Calculate a trapezoidal bandpass wavelet 68 | 69 | Usage: 70 | ------ 71 | t, wvlt = wvlt_ricker(f1, f2, f3, f4, phase, dt, wvlt_length) 72 | 73 | f1: Low truncation frequency of wavelet in Hz 74 | f2: Low cut frequency of wavelet in Hz 75 | f3: High cut frequency of wavelet in Hz 76 | f4: High truncation frequency of wavelet in Hz 77 | phase: wavelet phase in degrees 78 | dt: sample rate in seconds 79 | wvlt_length: length of wavelet in seconds 80 | ''' 81 | 82 | from numpy.fft import fft, ifft, fftfreq, fftshift, ifftshift 83 | 84 | nsamp = int(wvlt_length / dt + 1) 85 | 86 | freq = fftfreq(nsamp, dt) 87 | freq = fftshift(freq) 88 | aspec = freq * 0.0 89 | pspec = freq * 0.0 90 | 91 | # Calculate slope and y-int for low frequency ramp 92 | M1 = 1 / (f2 - f1) 93 | b1 = -M1 * f1 94 | 95 | # Calculate slop and y-int for high frequency ramp 96 | M2 = -1 / (f4 - f3) 97 | b2 = -M2 * f4 98 | 99 | # Build initial frequency and filter arrays 100 | freq = fftfreq(nsamp, dt) 101 | freq = fftshift(freq) 102 | filt = np.zeros(nsamp) 103 | 104 | # Build LF ramp 105 | idx = np.nonzero((np.abs(freq) >= f1) & (np.abs(freq) < f2)) 106 | filt[idx] = M1 * np.abs(freq)[idx] + b1 107 | 108 | # Build central filter flat 109 | idx = np.nonzero((np.abs(freq) >= f2) & (np.abs(freq) <= f3)) 110 | filt[idx] = 1.0 111 | 112 | # Build HF ramp 113 | idx = np.nonzero((np.abs(freq) > f3) & (np.abs(freq) <= f4)) 114 | filt[idx] = M2 * np.abs(freq)[idx] + b2 115 | 116 | # Unshift the frequencies and convert filter to fourier coefficients 117 | filt2 = ifftshift(filt) 118 | Af = filt2 * np.exp(np.zeros(filt2.shape) * 1j) 119 | 120 | # Convert filter to time-domain wavelet 121 | wvlt = fftshift(ifft(Af)) 122 | wvlt = np.real(wvlt) 123 | wvlt = wvlt / np.max(np.abs(wvlt)) # normalize wavelet by peak amplitude 124 | 125 | # Generate array of wavelet times 126 | t = np.linspace(-wvlt_length * 0.5, wvlt_length * 0.5, nsamp) 127 | 128 | # Apply phase rotation if desired 129 | if phase != 0: 130 | phase = phase * np.pi / 180.0 131 | wvlth = hilbert(wvlt) 132 | wvlth = np.imag(wvlth) 133 | wvlt = np.cos(phase) * wvlt - np.sin(phase) * wvlth 134 | 135 | return t, wvlt 136 | 137 | 138 | def calc_rc(vp_mod, rho_mod): 139 | ''' 140 | rc_int = calc_rc(vp_mod, rho_mod) 141 | ''' 142 | 143 | nlayers = len(vp_mod) 144 | nint = nlayers - 1 145 | 146 | rc_int = [] 147 | for i in range(0, nint): 148 | buf1 = vp_mod[i + 1] * rho_mod[i + 1] - vp_mod[i] * rho_mod[i] 149 | buf2 = vp_mod[i + 1] * rho_mod[i + 1] + vp_mod[i] * rho_mod[i] 150 | buf3 = buf1 / buf2 151 | rc_int.append(buf3) 152 | 153 | return rc_int 154 | 155 | def calc_times(z_int, vp_mod): 156 | ''' 157 | t_int = calc_times(z_int, vp_mod) 158 | ''' 159 | 160 | nlayers = len(vp_mod) 161 | nint = nlayers - 1 162 | 163 | t_int = [] 164 | for i in range(0, nint): 165 | if i == 0: 166 | tbuf = z_int[i] / vp_mod[i] 167 | t_int.append(tbuf) 168 | else: 169 | zdiff = z_int[i] - z_int[i - 1] 170 | tbuf = 2 * zdiff / vp_mod[i] + t_int[i - 1] 171 | t_int.append(tbuf) 172 | 173 | return t_int 174 | 175 | def digitize_model(rc_int, t_int, t): 176 | ''' 177 | rc = digitize_model(rc, t_int, t) 178 | 179 | rc = reflection coefficients corresponding to interface times 180 | t_int = interface times 181 | t = regularly sampled time series defining model sampling 182 | ''' 183 | 184 | import numpy as np 185 | 186 | nlayers = len(rc_int) 187 | nint = nlayers - 1 188 | nsamp = len(t) 189 | 190 | rc = list(np.zeros(nsamp, dtype='float')) 191 | lyr = 0 192 | 193 | for i in range(0, nsamp): 194 | 195 | if t[i] >= t_int[lyr]: 196 | rc[i] = rc_int[lyr] 197 | lyr = lyr + 1 198 | 199 | if lyr > nint: 200 | break 201 | 202 | return rc 203 | 204 | 205 | def wedge_tuning(mod,bound_mod,wave_parm,freq,trace_parm,plot_parm): 206 | ########################################################### 207 | # 208 | # DEFINE MODELING PARAMETERS HERE 209 | # 210 | 211 | # 3-Layer Model Parameters [Layer1, Layer2, Layer 3] 212 | vp_mod = mod[0] # P-wave velocity (m/s) 213 | vs_mod = mod[1] # S-wave velocity (m/s) 214 | rho_mod = mod[2] # Density (g/cc) 215 | 216 | dz_min = bound_mod[0] # Minimum thickness of Layer 2 (m) 217 | dz_max = bound_mod[1] # Maximum thickness of Layer 2 (m) 218 | dz_step = bound_mod[2] # Thickness step from trace-to-trace (normally 1.0 m) 219 | 220 | # Wavelet Parameters 221 | wvlt_type = wave_parm[0] # Valid values: 'ricker' or 'bandpass' 222 | wvlt_length = wave_parm[1] # Wavelet length in seconds 223 | wvlt_phase = wave_parm[2] # Wavelet phase in degrees 224 | wvlt_scalar = wave_parm[3] # Multiplier to scale wavelet amplitude (default = 1.0) 225 | wvlt_cfreq = wave_parm[4] # Ricker wavelet central frequency 226 | f1 = freq[0] # Bandpass wavelet low truncation frequency 227 | f2 = freq[1] # Bandpass wavelet low cut frequency 228 | f3 = freq[2] # Bandpass wavelet high cut frequency 229 | f4 = freq[3] # Bandpass wavelet high truncation frequency 230 | 231 | # Trace Parameters 232 | tmin = trace_parm[0] 233 | tmax = trace_parm[1] 234 | dt = trace_parm[2] # changing this from 0.0001 can affect the display quality 235 | 236 | # Plot Parameters 237 | min_plot_time = plot_parm[0] 238 | max_plot_time = plot_parm[1] 239 | excursion = plot_parm[2] 240 | 241 | ########################################################### 242 | # 243 | # DEFINE MODELING PARAMETERS HERE 244 | # 245 | 246 | # Some handy constants 247 | nlayers = len(vp_mod) 248 | nint = nlayers - 1 249 | nmodel = int((dz_max - dz_min) / dz_step + 1) 250 | 251 | 252 | # Generate wavelet 253 | if wvlt_type == 'ricker': 254 | wvlt_t, wvlt_amp = ricker(wvlt_cfreq, wvlt_phase, dt, wvlt_length) 255 | 256 | elif wvlt_type == 'bandpass': 257 | wvlt_t, wvlt_amp = wvlt_bpass(f1, f2, f3, f4, wvlt_phase, dt, wvlt_length) 258 | 259 | # Apply amplitude scale factor to wavelet (to match seismic amplitude values) 260 | wvlt_amp = wvlt_scalar * wvlt_amp 261 | 262 | # Calculate reflectivities from model parameters 263 | rc_int = calc_rc(vp_mod, rho_mod) 264 | 265 | syn_zo = [] 266 | rc_zo = [] 267 | lyr_times = [] 268 | for model in range(0, nmodel): 269 | 270 | # Calculate interface depths 271 | z_int = [500.0] 272 | z_int.append(z_int[0] + dz_min + dz_step * model) 273 | 274 | # Calculate interface times 275 | t_int = calc_times(z_int, vp_mod) 276 | lyr_times.append(t_int) 277 | 278 | # Digitize 3-layer model 279 | nsamp = int((tmax - tmin) / dt) + 1 280 | t = [] 281 | for i in range(0, nsamp): 282 | t.append(i * dt) 283 | 284 | rc = digitize_model(rc_int, t_int, t) 285 | rc_zo.append(rc) 286 | 287 | # Convolve wavelet with reflectivities 288 | syn_buf = np.convolve(rc, wvlt_amp, mode='same') 289 | syn_buf = list(syn_buf) 290 | syn_zo.append(syn_buf) 291 | print("finished step %i" % (model)) 292 | 293 | syn_zo = np.array(syn_zo) 294 | t = np.array(t) 295 | lyr_times = np.array(lyr_times) 296 | lyr_indx = np.array(np.round(lyr_times / dt), dtype='int16') 297 | 298 | # Use the transpose because rows are traces; 299 | # columns are time samples. 300 | tuning_trace = np.argmax(np.abs(syn_zo.T)) % syn_zo.T.shape[1] 301 | tuning_thickness = tuning_trace * dz_step 302 | 303 | # Plotting Code 304 | [ntrc, nsamp] = syn_zo.shape 305 | 306 | fig = plt.figure(figsize=(12, 14)) 307 | fig.set_facecolor('white') 308 | 309 | gs = gridspec.GridSpec(3, 1, height_ratios=[1, 1, 1]) 310 | 311 | ax0 = fig.add_subplot(gs[0]) 312 | ax0.plot(lyr_times[:, 0], color='blue', lw=1.5) 313 | ax0.plot(lyr_times[:, 1], color='red', lw=1.5) 314 | ax0.set_ylim((min_plot_time, max_plot_time)) 315 | ax0.invert_yaxis() 316 | ax0.set_xlabel('Thickness (m)') 317 | ax0.set_ylabel('Time (s)') 318 | plt.text(2, 319 | min_plot_time + (lyr_times[0, 0] - min_plot_time) / 2., 320 | 'Layer 1', 321 | fontsize=16) 322 | plt.text(dz_max / dz_step - 2, 323 | lyr_times[-1, 0] + (lyr_times[-1, 1] - lyr_times[-1, 0]) / 2., 324 | 'Layer 2', 325 | fontsize=16, 326 | horizontalalignment='right') 327 | plt.text(2, 328 | lyr_times[0, 0] + (max_plot_time - lyr_times[0, 0]) / 2., 329 | 'Layer 3', 330 | fontsize=16) 331 | plt.gca().xaxis.tick_top() 332 | plt.gca().xaxis.set_label_position('top') 333 | ax0.set_xlim((-excursion, ntrc + excursion)) 334 | 335 | ax1 = fig.add_subplot(gs[1]) 336 | plot_vawig(ax1, syn_zo, t, excursion, highlight=tuning_trace) 337 | ax1.plot(lyr_times[:, 0], color='blue', lw=1.5) 338 | ax1.plot(lyr_times[:, 1], color='red', lw=1.5) 339 | ax1.set_ylim((min_plot_time, max_plot_time)) 340 | ax1.invert_yaxis() 341 | ax1.set_xlabel('Thickness (m)') 342 | ax1.set_ylabel('Time (s)') 343 | 344 | ax2 = fig.add_subplot(gs[2]) 345 | ax2.plot(syn_zo[:, lyr_indx[:, 0]], color='blue') 346 | ax2.set_xlim((-excursion, ntrc + excursion)) 347 | ax2.axvline(tuning_trace, color='k', lw=2) 348 | ax2.grid() 349 | ax2.set_title('Upper interface amplitude') 350 | ax2.set_xlabel('Thickness (m)') 351 | ax2.set_ylabel('Amplitude') 352 | plt.text(tuning_trace + 2, 353 | plt.ylim()[0] * 1.1, 354 | 'tuning thickness = {0} m'.format(str(tuning_thickness)), 355 | fontsize=16) 356 | 357 | plt.show() 358 | 359 | 360 | 361 | 362 | 363 | -------------------------------------------------------------------------------- /PyOSGPUP/wavelet.py: -------------------------------------------------------------------------------- 1 | # Ref: https://gist.github.com/rowanc1/8338665 2 | import numpy as np 3 | pi = np.pi 4 | 5 | 6 | def getRicker(f, t): 7 | #assert len(f) == 1, 'Ricker wavelet needs 1 frequency as input' 8 | # f = f[0] 9 | pift = pi * f * t 10 | wav = (1 - 2 * pift ** 2) * np.exp(-pift ** 2) 11 | return wav 12 | 13 | 14 | def getOrmsby(f, t): 15 | assert len(f) == 4, 'Ormsby wavelet needs 4 frequencies as input' 16 | f = np.sort(f) # Ormsby wavelet frequencies must be in increasing order 17 | pif = pi * f 18 | den1 = pif[3] - pif[2] 19 | den2 = pif[1] - pif[0] 20 | term1 = (pif[3] * np.sinc(pif[3] * t)) ** 2 - (pif[2] * np.sinc(pif[2])) ** 2 21 | term2 = (pif[1] * np.sinc(pif[1] * t)) ** 2 - (pif[0] * np.sinc(pif[0])) ** 2 22 | 23 | wav = term1 / den1 - term2 / den2 24 | return wav 25 | 26 | 27 | def getKlauder(f, t, T=5.0): 28 | assert len(f) == 2, 'Klauder wavelet needs 2 frequencies as input' 29 | 30 | k = np.diff(f) / T 31 | f0 = np.sum(f) / 2.0 32 | wav = np.real(np.sin(pi * k * t * (T - t)) / (pi * k * t) * np.exp(2 * pi * 1j * f0 * t)) 33 | return wav 34 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # PyOSGPUP 2 | 3 | [![GitHub version](https://badge.fury.io/gh/Metkom%2FPyOSGPUP.svg)](https://badge.fury.io/gh/Metkom%2FPyOSGPUP) 4 | [![Build Status](https://travis-ci.org/dwyl/esta.svg?branch=master)](https://travis-ci.org/Metkom/PyOSGPUP) 5 | ![GitHub top language](https://img.shields.io/github/languages/top/Metkom/PyOSGPUP.svg) 6 | [![PyPI version](https://badge.fury.io/py/PyOSGPUP.svg)](https://badge.fury.io/py/PyOSGPUP) 7 | [![PyPI license](https://img.shields.io/pypi/l/PyOSGPUP.svg)](https://pypi.python.org/pypi/PyOSGPUP/) 8 | ![PyPI - Status](https://img.shields.io/pypi/status/PyOSGPUP.svg) 9 | ![PyPI - Wheel](https://img.shields.io/pypi/wheel/PyOSGPUP) 10 | 11 | ![GitHub last commit](https://img.shields.io/github/last-commit/Metkom/PyOSGPUP.svg) 12 | ![GitHub Release Date](https://img.shields.io/github/release-date/Metkom/PyOSGPUP.svg) 13 | [![HitCount](http://hits.dwyl.com/Metkom/PyOSGPUP.svg)](http://hits.dwyl.com/Metkom/PyOSGPUP) 14 | [![PyPI download month](https://img.shields.io/pypi/dm/PyOSGPUP.svg)](https://pypi.python.org/pypi/PyOSGPUP/) 15 | ![GitHub All Releases](https://img.shields.io/github/downloads/Metkom/PyOSGPUP/total.svg) 16 | ![GitHub forks](https://img.shields.io/github/forks/Metkom/PyOSGPUP.svg?style=social) 17 | 18 | [![Inline docs](http://inch-ci.org/github/dwyl/hapi-auth-jwt2.svg?branch=master)](http://inch-ci.org/mheriyanto/PyOSGPUP/hapi-auth-jwt2) 19 | [![contributions welcome](https://img.shields.io/badge/contributions-welcome-brightgreen.svg?style=flat)](https://github.com/Metkom/PyOSGPUP/issues) 20 | ![GitHub contributors](https://img.shields.io/github/contributors/Metkom/PyOSGPUP.svg) 21 | 22 | A python packages for geophysical data processing modeling, inversion and interpretation. Please check here: for [official website](https://sites.google.com/site/metkomup/pyosgpup) and [package](https://pypi.org/project/PyOSGPUP/). 23 | 24 | Teknik Geofisika, Universitas Pertamina Jl. Teuku Nyak Arief, Simprug, South Jakarta, DKI Jakarta, Indonesia, 12220. email: metkom.up@gmail.com 25 | 26 | ## Requirement 27 | 28 | ``` 29 | pip3 install -r requirements.txt 30 | ``` 31 | 32 | 33 | ## Installation 34 | 35 | ``` 36 | pip install PyOSGPUP 37 | or 38 | pip3 install PyOSGPUP 39 | ``` 40 | ## User Manual 41 | User manual for this package avalaible in Bahasa ([download](https://figshare.com/articles/Petunjuk_Penggunaan_PyOSGPUP_versi_1_0_3/7325723)). Short example: 42 | 43 | **1. Create wavelet** 44 | ```python 45 | import numpy as np 46 | import PyOSGPUP.wavelet as wav 47 | import matplotlib.pyplot as plt 48 | 49 | t = np.arange(-0.4 / 2, (0.4 / 2) + 0.004, 0.004) 50 | # frequency 51 | fgR = np.array([10]) # 1 freq 52 | fgO = np.array([5, 10, 15, 20]) # 4 fred 53 | fgK = np.array([5, 10]) # 2 fred 54 | gR = wav.getRicker(fgR, t) 55 | gO = wav.getOrmsby(fgO, t) 56 | gK = wav.getKlauder(fgK, t) 57 | 58 | plt.figure() 59 | plt.plot(t, gR, linewidth=2, color="blue") 60 | plt.plot(t, gO, linewidth=2, color="red") 61 | plt.plot(t, gK, linewidth=2, color="green") 62 | plt.title('Wavelet') 63 | plt.xlabel('time [ms]') 64 | plt.ylabel('amplitude') 65 | plt.legend(['Ricker', 'Ormsby', 'Kaluder']) 66 | plt.show() 67 | ``` 68 | 69 | 70 | 71 | 72 | 73 | **2. Read data segy** 74 | 75 | Please put [shotgather.sgy](https://github.com/cultpenguin/segypy/blob/master/example/shotgather.sgy) file in your directory code. 76 | 77 | ```python 78 | import PyOSGPUP.segypy as segypy 79 | 80 | filename = 'shotgather.sgy' 81 | 82 | # Set verbose level 83 | segypy.verbose = 1 84 | SH = segypy.getSegyHeader(filename) 85 | 86 | # Read Segy File 87 | [Data, SH, STH] = segypy.readSegy(filename) 88 | 89 | # Plot Segy filwe 90 | scale = 1e-9 91 | 92 | # wiggle plot 93 | segypy.wiggle(Data, SH, 1e-9) 94 | 95 | # image plot 96 | segypy.image(Data, SH, scale) 97 | ``` 98 | 99 | 100 | 101 | 102 | 103 | **3. Create synthetic seismogram** 104 | ```python 105 | from PyOSGPUP.synthe_seismo import plotLogsInteract, plotTimeDepth, plotSeismogram 106 | import matplotlib.pyplot as plt 107 | 108 | # Synthetic Seismogram 109 | d = [0., 50., 100.] # Position of top of each layer (m) 110 | v = [500., 1000., 1500.] # Velocity of each layer (m/s) 111 | rho = [2000., 2300., 2500.] # Density of each layer (kg/m^3) 112 | wavtyp = 'RICKER' # Wavelet type 113 | wavf = 50. # Wavelet Frequency 114 | usingT = False # Use Transmission Coefficients? 115 | 116 | plotLogsInteract(d[1], d[2], rho[0], rho[1], rho[2], v[0], v[1], v[2]) 117 | plt.show() 118 | 119 | plotTimeDepth(d, v) 120 | plt.show() 121 | 122 | plotSeismogram(d, rho, v, 50., wavA=1., noise=0., usingT=True, wavtyp='RICKER') 123 | plt.show() 124 | ``` 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | ## Citation 137 | If you find this project useful for your research, please use the following BibTeX entry. 138 | 139 | 140 | -------------------------------------------------------------------------------- /README.rst: -------------------------------------------------------------------------------- 1 | PyOSGPUP: Python, Open-source 2 | ============================= 3 | 4 | PuOSGPUP: Python Library that is Open-source created by 5 | Geophysical Engineering, Universitas Pertamina 6 | 7 | A python packages for geophysical data processing, modeling, and interpretation. 8 | 9 | Teknik Geofisika, Universitas Pertamina 10 | Jl. Teuku Nyak Arief, Simprug, South Jakarta, DKI Jakarta, Indonesia, 12220. 11 | email: metkom.up@gmail.com -------------------------------------------------------------------------------- /build/lib/PyOSGPUP/__init__.py: -------------------------------------------------------------------------------- 1 | from __future__ import print_function 2 | 3 | from PyOSGPUP import wavelet 4 | from PyOSGPUP import segypy 5 | from PyOSGPUP import tuning_wedge_acces 6 | from PyOSGPUP import signalpy 7 | 8 | __version__ = '1.0.3' 9 | __author__ = 'PyOSGPUP Team' 10 | __license__ = 'MIT' 11 | __copyright__ = '2018, PyOSGPUP Team, https://sites.google.com/site/metkomup/pyosgpup' 12 | -------------------------------------------------------------------------------- /build/lib/PyOSGPUP/segypy.py: -------------------------------------------------------------------------------- 1 | """ 2 | A python module for reading/writing/manipuating 3 | SEG-Y formatted filed 4 | 5 | segy.readSegy : Read SEGY file 6 | segy.getSegyHeader : Get SEGY header 7 | segy.getSegyTraceHeader : Get SEGY Trace header 8 | segy.getAllSegyTraceHeaders : Get all SEGY Trace headers 9 | segy.getSegyTrace : Get SEGY Trace heder and trace data for one trace 10 | 11 | segy.writeSegy : Write a data to a SEGY file 12 | segy.writeSegyStructure : Writes a segypy data structure to a SEGY file 13 | 14 | segy.getValue : Get a value from a binary string 15 | segy.ibm2ieee : Convert IBM floats to IEEE 16 | 17 | segy.version : The version of SegyPY 18 | segy.verbose : Amount of verbose information to the screen 19 | """ 20 | # 21 | # segypy : A Python module for reading and writing SEG-Y formatted data 22 | # 23 | # (C) Thomas Mejer Hansen, 2005-2016 24 | # 25 | # contributions from 26 | # - Pete Forman 27 | # 28 | # modified by Andrew Squelch 2007 : sub-version 0.3.1 29 | from __future__ import division 30 | from __future__ import print_function 31 | 32 | import struct, sys # modified by A Squelch 33 | 34 | import numpy as np 35 | 36 | 37 | # SOME GLOBAL PARAMETERS 38 | version = '0.3.1' # modified by A Squelch 39 | verbose = 1; 40 | 41 | # endian='>' # Big Endian # modified by A Squelch 42 | # endian='<' # Little Endian 43 | # endian='=' # Native 44 | 45 | l_int = struct.calcsize('i') 46 | l_uint = struct.calcsize('I') 47 | l_long = 4; 48 | # Next line gives wrong result on Linux!! (gives 8 instead of 4) 49 | # l_long = struct.calcsize('l') 50 | l_ulong = struct.calcsize('L') 51 | l_short = struct.calcsize('h') 52 | l_ushort = struct.calcsize('H') 53 | l_char = struct.calcsize('c') 54 | l_uchar = struct.calcsize('B') 55 | l_float = struct.calcsize('f') 56 | 57 | ############## 58 | # INIT 59 | 60 | ############## 61 | # %% Initialize SEGY HEADER 62 | SH_def = {"Job": {"pos": 3200, "type": "int32", "def": 0}} 63 | SH_def["Line"] = {"pos": 3204, "type": "int32", "def": 0} 64 | SH_def["Reel"] = {"pos": 3208, "type": "int32", "def": 0} 65 | SH_def["DataTracePerEnsemble"] = {"pos": 3212, "type": "int16", "def": 0} 66 | SH_def["AuxiliaryTracePerEnsemble"] = {"pos": 3214, "type": "int16", "def": 0} 67 | SH_def["dt"] = {"pos": 3216, "type": "uint16", "def": 1000} 68 | SH_def["dtOrig"] = {"pos": 3218, "type": "uint16", "def": 1000} 69 | SH_def["ns"] = {"pos": 3220, "type": "uint16", "def": 0} 70 | SH_def["nsOrig"] = {"pos": 3222, "type": "uint16", "def": 0} 71 | SH_def["DataSampleFormat"] = {"pos": 3224, "type": "int16", "def": 5} 72 | SH_def["DataSampleFormat"]["descr"] = {0: { 73 | 1: "IBM Float", 74 | 2: "32 bit Integer", 75 | 3: "16 bit Integer", 76 | 8: "8 bit Integer"}} 77 | 78 | SH_def["DataSampleFormat"]["descr"][1] = { 79 | 1: "IBM Float", 80 | 2: "32 bit Integer", 81 | 3: "16 bit Integer", 82 | 5: "IEEE", 83 | 8: "8 bit Integer"} 84 | 85 | SH_def["DataSampleFormat"]["bps"] = {0: { 86 | 1: 4, 87 | 2: 4, 88 | 3: 2, 89 | 8: 1}} 90 | SH_def["DataSampleFormat"]["bps"][1] = { 91 | 1: 4, 92 | 2: 4, 93 | 3: 2, 94 | 5: 4, 95 | 8: 1} 96 | SH_def["DataSampleFormat"]["datatype"] = {0: { 97 | 1: 'ibm', 98 | 2: 'l', 99 | 3: 'h', 100 | 8: 'B'}} 101 | SH_def["DataSampleFormat"]["datatype"][1] = { 102 | 1: 'ibm', 103 | 2: 'l', 104 | 3: 'h', 105 | # 5: 'float', 106 | 5: 'f', 107 | 8: 'B'} 108 | 109 | SH_def["EnsembleFold"] = {"pos": 3226, "type": "int16", "def": 0} 110 | SH_def["TraceSorting"] = {"pos": 3228, "type": "int16", "def": 0} 111 | SH_def["VerticalSumCode"] = {"pos": 3230, "type": "int16", "def": 0} 112 | SH_def["SweepFrequencyEnd"] = {"pos": 3234, "type": "int16", "def": 0} 113 | SH_def["SweepLength"] = {"pos": 3236, "type": "int16", "def": 0} 114 | SH_def["SweepType"] = {"pos": 3238, "type": "int16", "def": 0} 115 | SH_def["SweepChannel"] = {"pos": 3240, "type": "int16", "def": 0} 116 | SH_def["SweepTaperlengthStart"] = {"pos": 3242, "type": "int16", "def": 0} 117 | SH_def["SweepTaperLengthEnd"] = {"pos": 3244, "type": "int16", "def": 0} 118 | SH_def["TaperType"] = {"pos": 3246, "type": "int16", "def": 0} 119 | SH_def["CorrelatedDataTraces"] = {"pos": 3248, "type": "int16", "def": 0} 120 | SH_def["BinaryGain"] = {"pos": 3250, "type": "int16", "def": 0} 121 | SH_def["AmplitudeRecoveryMethod"] = {"pos": 3252, "type": "int16", "def": 0} 122 | SH_def["MeasurementSystem"] = {"pos": 3254, "type": "int16", "def": 0} 123 | SH_def["ImpulseSignalPolarity"] = {"pos": 3256, "type": "int16", "def": 0} 124 | SH_def["VibratoryPolarityCode"] = {"pos": 3258, "type": "int16", "def": 0} 125 | SH_def["Unassigned1"] = {"pos": 3260, "type": "int16", "n": 120, "def": 0} 126 | SH_def["SegyFormatRevisionNumber"] = {"pos": 3500, "type": "uint16", "def": 100} 127 | SH_def["FixedLengthTraceFlag"] = {"pos": 3502, "type": "uint16", "def": 0} 128 | SH_def["NumberOfExtTextualHeaders"] = {"pos": 3504, "type": "uint16", "def": 0} 129 | SH_def["Unassigned2"] = {"pos": 3506, "type": "int16", "n": 47, "def": 0} 130 | 131 | ############## 132 | # %% Initialize SEGY TRACE HEADER SPECIFICATION 133 | STH_def = {"TraceSequenceLine": {"pos": 0, "type": "int32"}} 134 | STH_def["TraceSequenceFile"] = {"pos": 4, "type": "int32"} 135 | STH_def["FieldRecord"] = {"pos": 8, "type": "int32"} 136 | STH_def["TraceNumber"] = {"pos": 12, "type": "int32"} 137 | STH_def["EnergySourcePoint"] = {"pos": 16, "type": "int32"} 138 | STH_def["cdp"] = {"pos": 20, "type": "int32"} 139 | STH_def["cdpTrace"] = {"pos": 24, "type": "int32"} 140 | STH_def["TraceIdenitifactionCode"] = {"pos": 28, "type": "uint16"} # 'int16'); % 28 141 | STH_def["TraceIdenitifactionCode"]["descr"] = {0: { 142 | 1: "Seismic data", 143 | 2: "Dead", 144 | 3: "Dummy", 145 | 4: "Time Break", 146 | 5: "Uphole", 147 | 6: "Sweep", 148 | 7: "Timing", 149 | 8: "Water Break"}} 150 | STH_def["TraceIdenitifactionCode"]["descr"][1] = { 151 | -1: "Other", 152 | 0: "Unknown", 153 | 1: "Seismic data", 154 | 2: "Dead", 155 | 3: "Dummy", 156 | 4: "Time break", 157 | 5: "Uphole", 158 | 6: "Sweep", 159 | 7: "Timing", 160 | 8: "Waterbreak", 161 | 9: "Near-field gun signature", 162 | 10: "Far-field gun signature", 163 | 11: "Seismic pressure sensor", 164 | 12: "Multicomponent seismic sensor - Vertical component", 165 | 13: "Multicomponent seismic sensor - Cross-line component", 166 | 14: "Multicomponent seismic sensor - In-line component", 167 | 15: "Rotated multicomponent seismic sensor - Vertical component", 168 | 16: "Rotated multicomponent seismic sensor - Transverse component", 169 | 17: "Rotated multicomponent seismic sensor - Radial component", 170 | 18: "Vibrator reaction mass", 171 | 19: "Vibrator baseplate", 172 | 20: "Vibrator estimated ground force", 173 | 21: "Vibrator reference", 174 | 22: "Time-velocity pairs"} 175 | STH_def["NSummedTraces"] = {"pos": 30, "type": "int16"} # 'int16'); % 30 176 | STH_def["NStackedTraces"] = {"pos": 32, "type": "int16"} # 'int16'); % 32 177 | STH_def["DataUse"] = {"pos": 34, "type": "int16"} # 'int16'); % 34 178 | STH_def["DataUse"]["descr"] = {0: { 179 | 1: "Production", 180 | 2: "Test"}} 181 | STH_def["DataUse"]["descr"][1] = STH_def["DataUse"]["descr"][0] 182 | STH_def["offset"] = {"pos": 36, "type": "int32"} # 'int32'); %36 183 | STH_def["ReceiverGroupElevation"] = {"pos": 40, "type": "int32"} # 'int32'); %40 184 | STH_def["SourceSurfaceElevation"] = {"pos": 44, "type": "int32"} # 'int32'); %44 185 | STH_def["SourceDepth"] = {"pos": 48, "type": "int32"} # 'int32'); %48 186 | STH_def["ReceiverDatumElevation"] = {"pos": 52, "type": "int32"} # 'int32'); %52 187 | STH_def["SourceDatumElevation"] = {"pos": 56, "type": "int32"} # 'int32'); %56 188 | STH_def["SourceWaterDepth"] = {"pos": 60, "type": "int32"} # 'int32'); %60 189 | STH_def["GroupWaterDepth"] = {"pos": 64, "type": "int32"} # 'int32'); %64 190 | STH_def["ElevationScalar"] = {"pos": 68, "type": "int16"} # 'int16'); %68 191 | STH_def["SourceGroupScalar"] = {"pos": 70, "type": "int16"} # 'int16'); %70 192 | STH_def["SourceX"] = {"pos": 72, "type": "int32"} # 'int32'); %72 193 | STH_def["SourceY"] = {"pos": 76, "type": "int32"} # 'int32'); %76 194 | STH_def["GroupX"] = {"pos": 80, "type": "int32"} # 'int32'); %80 195 | STH_def["GroupY"] = {"pos": 84, "type": "int32"} # 'int32'); %84 196 | STH_def["CoordinateUnits"] = {"pos": 88, "type": "int16"} # 'int16'); %88 197 | STH_def["CoordinateUnits"]["descr"] = {1: { 198 | 1: "Length (meters or feet)", 199 | 2: "Seconds of arc"}} 200 | STH_def["CoordinateUnits"]["descr"][1] = { 201 | 1: "Length (meters or feet)", 202 | 2: "Seconds of arc", 203 | 3: "Decimal degrees", 204 | 4: "Degrees, minutes, seconds (DMS)"} 205 | STH_def["WeatheringVelocity"] = {"pos": 90, "type": "int16"} # 'int16'); %90 206 | STH_def["SubWeatheringVelocity"] = {"pos": 92, "type": "int16"} # 'int16'); %92 207 | STH_def["SourceUpholeTime"] = {"pos": 94, "type": "int16"} # 'int16'); %94 208 | STH_def["GroupUpholeTime"] = {"pos": 96, "type": "int16"} # 'int16'); %96 209 | STH_def["SourceStaticCorrection"] = {"pos": 98, "type": "int16"} # 'int16'); %98 210 | STH_def["GroupStaticCorrection"] = {"pos": 100, "type": "int16"} # 'int16'); %100 211 | STH_def["TotalStaticApplied"] = {"pos": 102, "type": "int16"} # 'int16'); %102 212 | STH_def["LagTimeA"] = {"pos": 104, "type": "int16"} # 'int16'); %104 213 | STH_def["LagTimeB"] = {"pos": 106, "type": "int16"} # 'int16'); %106 214 | STH_def["DelayRecordingTime"] = {"pos": 108, "type": "int16"} # 'int16'); %108 215 | STH_def["MuteTimeStart"] = {"pos": 110, "type": "int16"} # 'int16'); %110 216 | STH_def["MuteTimeEND"] = {"pos": 112, "type": "int16"} # 'int16'); %112 217 | STH_def["ns"] = {"pos": 114, "type": "uint16"} # 'uint16'); %114 218 | STH_def["dt"] = {"pos": 116, "type": "uint16"} # 'uint16'); %116 219 | STH_def["GainType"] = {"pos": 119, "type": "int16"} # 'int16'); %118 220 | STH_def["GainType"]["descr"] = {0: { 221 | 1: "Fixes", 222 | 2: "Binary", 223 | 3: "Floating point"}} 224 | STH_def["GainType"]["descr"][1] = STH_def["GainType"]["descr"][0] 225 | STH_def["InstrumentGainConstant"] = {"pos": 120, "type": "int16"} # 'int16'); %120 226 | STH_def["InstrumentInitialGain"] = {"pos": 122, "type": "int16"} # 'int16'); %%122 227 | STH_def["Correlated"] = {"pos": 124, "type": "int16"} # 'int16'); %124 228 | STH_def["Correlated"]["descr"] = {0: { 229 | 1: "No", 230 | 2: "Yes"}} 231 | STH_def["Correlated"]["descr"][1] = STH_def["Correlated"]["descr"][0] 232 | 233 | STH_def["SweepFrequenceStart"] = {"pos": 126, "type": "int16"} # 'int16'); %126 234 | STH_def["SweepFrequenceEnd"] = {"pos": 128, "type": "int16"} # 'int16'); %128 235 | STH_def["SweepLength"] = {"pos": 130, "type": "int16"} # 'int16'); %130 236 | STH_def["SweepType"] = {"pos": 132, "type": "int16"} # 'int16'); %132 237 | STH_def["SweepType"]["descr"] = {0: { 238 | 1: "linear", 239 | 2: "parabolic", 240 | 3: "exponential", 241 | 4: "other"}} 242 | STH_def["SweepType"]["descr"][1] = STH_def["SweepType"]["descr"][0] 243 | 244 | STH_def["SweepTraceTaperLengthStart"] = {"pos": 134, "type": "int16"} # 'int16'); %134 245 | STH_def["SweepTraceTaperLengthEnd"] = {"pos": 136, "type": "int16"} # 'int16'); %136 246 | STH_def["TaperType"] = {"pos": 138, "type": "int16"} # 'int16'); %138 247 | STH_def["TaperType"]["descr"] = {0: { 248 | 1: "linear", 249 | 2: "cos2c", 250 | 3: "other"}} 251 | STH_def["TaperType"]["descr"][1] = STH_def["TaperType"]["descr"][0] 252 | 253 | STH_def["AliasFilterFrequency"] = {"pos": 140, "type": "int16"} # 'int16'); %140 254 | STH_def["AliasFilterSlope"] = {"pos": 142, "type": "int16"} # 'int16'); %142 255 | STH_def["NotchFilterFrequency"] = {"pos": 144, "type": "int16"} # 'int16'); %144 256 | STH_def["NotchFilterSlope"] = {"pos": 146, "type": "int16"} # 'int16'); %146 257 | STH_def["LowCutFrequency"] = {"pos": 148, "type": "int16"} # 'int16'); %148 258 | STH_def["HighCutFrequency"] = {"pos": 150, "type": "int16"} # 'int16'); %150 259 | STH_def["LowCutSlope"] = {"pos": 152, "type": "int16"} # 'int16'); %152 260 | STH_def["HighCutSlope"] = {"pos": 154, "type": "int16"} # 'int16'); %154 261 | STH_def["YearDataRecorded"] = {"pos": 156, "type": "int16"} # 'int16'); %156 262 | STH_def["DayOfYear"] = {"pos": 158, "type": "int16"} # 'int16'); %158 263 | STH_def["HourOfDay"] = {"pos": 160, "type": "int16"} # 'int16'); %160 264 | STH_def["MinuteOfHour"] = {"pos": 162, "type": "int16"} # 'int16'); %162 265 | STH_def["SecondOfMinute"] = {"pos": 164, "type": "int16"} # 'int16'); %164 266 | STH_def["TimeBaseCode"] = {"pos": 166, "type": "int16"} # 'int16'); %166 267 | STH_def["TimeBaseCode"]["descr"] = {0: { 268 | 1: "Local", 269 | 2: "GMT", 270 | 3: "Other"}} 271 | STH_def["TimeBaseCode"]["descr"][1] = { 272 | 1: "Local", 273 | 2: "GMT", 274 | 3: "Other", 275 | 4: "UTC"} 276 | STH_def["TraceWeightningFactor"] = {"pos": 168, "type": "int16"} # 'int16'); %170 277 | STH_def["GeophoneGroupNumberRoll1"] = {"pos": 170, "type": "int16"} # 'int16'); %172 278 | STH_def["GeophoneGroupNumberFirstTraceOrigField"] = {"pos": 172, "type": "int16"} # 'int16'); %174 279 | STH_def["GeophoneGroupNumberLastTraceOrigField"] = {"pos": 174, "type": "int16"} # 'int16'); %176 280 | STH_def["GapSize"] = {"pos": 176, "type": "int16"} # 'int16'); %178 281 | STH_def["OverTravel"] = {"pos": 178, "type": "int16"} # 'int16'); %178 282 | STH_def["OverTravel"]["descr"] = {0: { 283 | 1: "down (or behind)", 284 | 2: "up (or ahead)", 285 | 3: "other"}} 286 | STH_def["OverTravel"]["descr"][1] = STH_def["OverTravel"]["descr"][0] 287 | 288 | STH_def["cdpX"] = {"pos": 180, "type": "int32"} # 'int32'); %180 289 | STH_def["cdpY"] = {"pos": 184, "type": "int32"} # 'int32'); %184 290 | STH_def["Inline3D"] = {"pos": 188, "type": "int32"} # 'int32'); %188 291 | STH_def["Crossline3D"] = {"pos": 192, "type": "int32"} # 'int32'); %192 292 | STH_def["ShotPoint"] = {"pos": 192, "type": "int32"} # 'int32'); %196 293 | STH_def["ShotPointScalar"] = {"pos": 200, "type": "int16"} # 'int16'); %200 294 | STH_def["TraceValueMeasurementUnit"] = {"pos": 202, "type": "int16"} # 'int16'); %202 295 | STH_def["TraceValueMeasurementUnit"]["descr"] = {1: { 296 | -1: "Other", 297 | 0: "Unknown (should be described in Data Sample Measurement Units Stanza) ", 298 | 1: "Pascal (Pa)", 299 | 2: "Volts (V)", 300 | 3: "Millivolts (v)", 301 | 4: "Amperes (A)", 302 | 5: "Meters (m)", 303 | 6: "Meters Per Second (m/s)", 304 | 7: "Meters Per Second squared (m/&s2)Other", 305 | 8: "Newton (N)", 306 | 9: "Watt (W)"}} 307 | STH_def["TransductionConstantMantissa"] = {"pos": 204, "type": "int32"} # 'int32'); %204 308 | STH_def["TransductionConstantPower"] = {"pos": 208, "type": "int16"} # 'int16'); %208 309 | STH_def["TransductionUnit"] = {"pos": 210, "type": "int16"} # 'int16'); %210 310 | STH_def["TransductionUnit"]["descr"] = STH_def["TraceValueMeasurementUnit"]["descr"] 311 | STH_def["TraceIdentifier"] = {"pos": 212, "type": "int16"} # 'int16'); %212 312 | STH_def["ScalarTraceHeader"] = {"pos": 214, "type": "int16"} # 'int16'); %214 313 | STH_def["SourceType"] = {"pos": 216, "type": "int16"} # 'int16'); %216 314 | STH_def["SourceType"]["descr"] = {1: { 315 | -1: "Other (should be described in Source Type/Orientation stanza)", 316 | 0: "Unknown", 317 | 1: "Vibratory - Vertical orientation", 318 | 2: "Vibratory - Cross-line orientation", 319 | 3: "Vibratory - In-line orientation", 320 | 4: "Impulsive - Vertical orientation", 321 | 5: "Impulsive - Cross-line orientation", 322 | 6: "Impulsive - In-line orientation", 323 | 7: "Distributed Impulsive - Vertical orientation", 324 | 8: "Distributed Impulsive - Cross-line orientation", 325 | 9: "Distributed Impulsive - In-line orientation"}} 326 | 327 | STH_def["SourceEnergyDirectionMantissa"] = {"pos": 218, "type": "int32"} # 'int32'); %218 328 | STH_def["SourceEnergyDirectionExponent"] = {"pos": 222, "type": "int16"} # 'int16'); %222 329 | STH_def["SourceMeasurementMantissa"] = {"pos": 224, "type": "int32"} # 'int32'); %224 330 | STH_def["SourceMeasurementExponent"] = {"pos": 228, "type": "int16"} # 'int16'); %228 331 | STH_def["SourceMeasurementUnit"] = {"pos": 230, "type": "int16"} # 'int16'); %230 332 | STH_def["SourceMeasurementUnit"]["descr"] = {1: { 333 | -1: "Other (should be described in Source Measurement Unit stanza)", 334 | 0: "Unknown", 335 | 1: "Joule (J)", 336 | 2: "Kilowatt (kW)", 337 | 3: "Pascal (Pa)", 338 | 4: "Bar (Bar)", 339 | 4: "Bar-meter (Bar-m)", 340 | 5: "Newton (N)", 341 | 6: "Kilograms (kg)"}} 342 | STH_def["UnassignedInt1"] = {"pos": 232, "type": "int32"} # 'int32'); %232 343 | STH_def["UnassignedInt2"] = {"pos": 236, "type": "int32"} # 'int32'); %236 344 | 345 | 346 | ############## 347 | # %% FUNCTIONS 348 | 349 | def image(Data, SH={}, maxval=-1): 350 | """ 351 | image(Data,SH,maxval) 352 | Image segy Data 353 | """ 354 | import matplotlib.pylab as plt 355 | 356 | if (maxval<=0): 357 | Dmax = np.max(Data) 358 | maxval = -1*maxval*Dmax 359 | 360 | if 'time' in SH: 361 | t = SH['time'] 362 | ntraces = SH['ntraces'] 363 | ns = SH['ns'] 364 | else: 365 | ns = Data.shape[0] 366 | t = np.arange(ns) 367 | ntraces = Data.shape[1] 368 | x = np.arange(ntraces)+1 369 | 370 | print(maxval) 371 | plt.pcolor(x, t, Data, vmin=-1*maxval, vmax=maxval) 372 | plt.colorbar() 373 | plt.axis('normal') 374 | plt.xlabel('Trace number') 375 | if 'time' in SH: 376 | plt.ylabel('Time (ms)') 377 | else: 378 | plt.ylabel('Sample number') 379 | if 'filename' in SH: 380 | plt.title(SH['filename']) 381 | plt.gca().invert_yaxis() 382 | 383 | #plt.grid(True) 384 | plt.show() 385 | 386 | 387 | # %% 388 | def wiggle(Data, SH={}, maxval=-1, skipt=1, lwidth=.1): 389 | """ 390 | wiggle(Data,SH) 391 | """ 392 | import matplotlib.pylab as plt 393 | import numpy as np 394 | 395 | if 'time' in SH: 396 | t = SH['time'] 397 | ntraces = SH['ntraces'] 398 | ns = SH['ns'] 399 | else: 400 | ns=Data.shape[0] 401 | t=np.arange(ns) 402 | ntraces = Data.shape[1] 403 | 404 | 405 | if (maxval<=0): 406 | Dmax = np.max(Data) 407 | maxval = -1*maxval*Dmax 408 | 409 | for i in range(0, ntraces, skipt): 410 | trace = Data[:, i] 411 | trace[0] = 0 412 | trace[ns - 1] = 0 413 | plt.plot(i + trace / maxval, t, color='black', linewidth=lwidth) 414 | for a in range(len(trace)): 415 | if (trace[a] < 0): 416 | trace[a] = 0; 417 | # pylab.fill(i+Data[:,i]/maxval,t,color='k',facecolor='g') 418 | plt.fill(i + Data[:, i] / maxval, t, 'k', linewidth=0) 419 | 420 | plt.grid(True) 421 | plt.gca().invert_yaxis() 422 | 423 | plt.xlabel('Trace number') 424 | if 'time' in SH: 425 | plt.ylabel('Time (ms)') 426 | else: 427 | plt.ylabel('Sample number') 428 | if 'filename' in SH: 429 | plt.title(SH['filename']) 430 | plt.axes().set_xlim(-1, ntraces) 431 | plt.show() 432 | 433 | 434 | # %% 435 | def getDefaultSegyHeader(ntraces=100, ns=100): 436 | """ 437 | SH=getDefaultSegyHeader() 438 | """ 439 | # INITIALIZE DICTIONARY 440 | SH = {"Job": {"pos": 3200, "type": "int32", "def": 0}} 441 | 442 | for key in SH_def.keys(): 443 | 444 | tmpkey = SH_def[key] 445 | if (tmpkey.has_key('def')): 446 | val = tmpkey['def'] 447 | else: 448 | val = 0 449 | SH[key] = val 450 | 451 | SH["ntraces"] = ntraces; 452 | SH["ns"] = ns; 453 | 454 | return SH 455 | 456 | 457 | # %% 458 | def getDefaultSegyTraceHeaders(ntraces=100, ns=100, dt=1000): 459 | """ 460 | SH=getDefaultSegyTraceHeader() 461 | """ 462 | # INITIALIZE DICTIONARY 463 | STH = {"TraceSequenceLine": {"pos": 0, "type": "int32"}} 464 | 465 | for key in STH_def.keys(): 466 | 467 | tmpkey = STH_def[key] 468 | if (tmpkey.has_key('def')): 469 | val = tmpkey['def'] 470 | else: 471 | val = 0 472 | STH[key] = np.zeros(ntraces) 473 | 474 | for a in range(ntraces): 475 | STH["TraceSequenceLine"][a] = a + 1 476 | STH["TraceSequenceFile"][a] = a + 1 477 | STH["FieldRecord"][a] = 1000 478 | STH["TraceNumber"][a] = a + 1 479 | STH["ns"][a] = ns 480 | STH["dt"][a] = dt 481 | return STH 482 | 483 | 484 | # %% 485 | def getSegyTraceHeader(SH, THN='cdp', data='none', endian='>'): # modified by A Squelch 486 | """ 487 | getSegyTraceHeader(SH,TraceHeaderName) 488 | """ 489 | 490 | bps = getBytePerSample(SH) 491 | 492 | if (data == 'none'): 493 | data = open(SH["filename"], 'rb').read() 494 | 495 | # MAKE SOME LOOKUP TABLE THAT HOLDS THE LOCATION OF HEADERS 496 | # THpos=TraceHeaderPos[THN] 497 | THpos = STH_def[THN]["pos"] 498 | THformat = STH_def[THN]["type"] 499 | ntraces = SH["ntraces"] 500 | thv = np.zeros(ntraces) 501 | for itrace in range(1, ntraces + 1, 1): 502 | i = itrace 503 | 504 | pos = THpos + 3600 + (SH["ns"] * bps + 240) * (itrace - 1); 505 | 506 | txt = "getSegyTraceHeader : Reading trace header " + THN + " " + str(itrace) + " of " + str( 507 | ntraces) + " " + str(pos) 508 | 509 | printverbose(txt, 20); 510 | thv[itrace - 1], index = getValue(data, pos, THformat, endian, 1) 511 | txt = "getSegyTraceHeader : " + THN + "=" + str(thv[itrace - 1]) 512 | printverbose(txt, 30); 513 | 514 | return thv 515 | 516 | 517 | # %% 518 | def getLastSegyTraceHeader(SH, THN='cdp', data='none', endian='>'): # added by A Squelch 519 | """ 520 | getLastSegyTraceHeader(SH,TraceHeaderName) 521 | """ 522 | 523 | bps = getBytePerSample(SH) 524 | 525 | if (data == 'none'): 526 | data = open(SH["filename"]).read() 527 | 528 | # SET PARAMETERS THAT DEFINE THE LOCATION OF THE LAST HEADER 529 | # AND THE TRACE NUMBER KEY FIELD 530 | THpos = STH_def[THN]["pos"] 531 | THformat = STH_def[THN]["type"] 532 | ntraces = SH["ntraces"] 533 | 534 | pos = THpos + 3600 + (SH["ns"] * bps + 240) * (ntraces - 1); 535 | 536 | txt = "getLastSegyTraceHeader : Reading last trace header " + THN + " " + str(pos) 537 | 538 | printverbose(txt, 20); 539 | thv, index = getValue(data, pos, THformat, endian, 1) 540 | txt = "getLastSegyTraceHeader : " + THN + "=" + str(thv) 541 | printverbose(txt, 30); 542 | 543 | return thv 544 | 545 | 546 | # %% 547 | def getAllSegyTraceHeaders(SH, data='none'): 548 | SegyTraceHeaders = {'filename': SH["filename"]} 549 | 550 | printverbose('getAllSegyTraceHeaders : trying to get all segy trace headers', 2) 551 | 552 | if (data == 'none'): 553 | data = open(SH["filename"], 'rb').read() 554 | 555 | for key in STH_def.keys(): 556 | sth = getSegyTraceHeader(SH, key, data) 557 | SegyTraceHeaders[key] = sth 558 | txt = "getAllSegyTraceHeaders : " + key 559 | printverbose(txt, 10) 560 | 561 | return SegyTraceHeaders 562 | 563 | 564 | # %% 565 | def readSegy(filename, endian='>'): # modified by A Squelch 566 | """ 567 | Data,SegyHeader,SegyTraceHeaders=getSegyHeader(filename) 568 | """ 569 | 570 | printverbose("readSegy : Trying to read " + filename, 0) 571 | 572 | data = open(filename, 'rb').read() 573 | 574 | filesize = len(data) 575 | 576 | SH = getSegyHeader(filename, endian) # modified by A Squelch 577 | 578 | bps = getBytePerSample(SH) 579 | 580 | ntraces = (filesize - 3600) / (SH['ns'] * bps + 240) 581 | # ntraces = 100 582 | 583 | printverbose("readSegy : Length of data : " + str(filesize), 2) 584 | 585 | SH["ntraces"] = np.int(ntraces); 586 | 587 | # ndummy_samples=240/bps # modified by A Squelch 588 | # printverbose("readSegy : ndummy_samples="+str(ndummy_samples),6) # modified by A Squelch 589 | printverbose("readSegy : ntraces=" + str(ntraces) + " nsamples=" + str(SH['ns']), 2) 590 | 591 | # GET TRACE 592 | index = 3600; 593 | nd = int((filesize - 3600) / bps) 594 | 595 | printverbose("filesize=%d" % filesize) 596 | printverbose("bps=%5d" % bps) 597 | printverbose("nd=%5d" % nd) 598 | 599 | # modified by A Squelch 600 | # this portion replaced by call to new function: readSegyData 601 | Data, SH, SegyTraceHeaders = readSegyData(data, SH, nd, bps, index, endian) 602 | 603 | printverbose("readSegy : Read segy data", 2) # modified by A Squelch 604 | 605 | return Data, SH, SegyTraceHeaders 606 | 607 | 608 | # %% 609 | def readSegyData(data, SH, nd, bps, index, endian='>'): # added by A Squelch 610 | """ 611 | Data,SegyHeader,SegyTraceHeaders=readSegyData(data,SH,nd,bps,index) 612 | 613 | This function separated out from readSegy so that it can also be 614 | called from other external functions - by A Squelch. 615 | """ 616 | 617 | # Calulate number of dummy samples needed to account for Trace Headers 618 | ndummy_samples = int(240 / bps) 619 | printverbose("readSegyData : ndummy_samples=" + str(ndummy_samples), 6) 620 | 621 | # READ ALL SEGY TRACE HEADRES 622 | STH = getAllSegyTraceHeaders(SH, data) 623 | 624 | printverbose("readSegyData : Reading segy data", 1) 625 | 626 | # READ ALL DATA EXCEPT FOR SEGY HEADER 627 | # Data = np.zeros((SH['ns'],ntraces)) 628 | 629 | revision = SH["SegyFormatRevisionNumber"] 630 | if (revision == 100): 631 | revision = 1 632 | if (revision == 256): # added by A Squelch 633 | revision = 1 634 | 635 | dsf = SH["DataSampleFormat"] 636 | 637 | try: # block added by A Squelch 638 | DataDescr = SH_def["DataSampleFormat"]["descr"][revision][dsf] 639 | except KeyError: 640 | print("") 641 | print(" An error has ocurred interpreting a SEGY binary header key") 642 | print(" Please check the Endian setting for this file: ", SH["filename"]) 643 | sys.exit() 644 | 645 | printverbose("readSegyData : SEG-Y revision = " + str(revision), 1) 646 | printverbose("readSegyData : DataSampleFormat=" + str(dsf) + "(" + DataDescr + ")", 1) 647 | 648 | if (SH["DataSampleFormat"] == 1): 649 | printverbose("readSegyData : Assuming DSF=1, IBM FLOATS", 2) 650 | Data1 = getValue(data, index, 'ibm', endian, nd) 651 | elif (SH["DataSampleFormat"] == 2): 652 | printverbose("readSegyData : Assuming DSF=" + str(SH["DataSampleFormat"]) + ", 32bit INT", 2) 653 | Data1 = getValue(data, index, 'l', endian, nd) 654 | elif (SH["DataSampleFormat"] == 3): 655 | printverbose("readSegyData : Assuming DSF=" + str(SH["DataSampleFormat"]) + ", 16bit INT", 2) 656 | Data1 = getValue(data, index, 'h', endian, nd) 657 | elif (SH["DataSampleFormat"] == 5): 658 | printverbose("readSegyData : Assuming DSF=" + str(SH["DataSampleFormat"]) + ", IEEE", 2) 659 | Data1 = getValue(data, index, 'float', endian, nd) 660 | elif (SH["DataSampleFormat"] == 8): 661 | printverbose("readSegyData : Assuming DSF=" + str(SH["DataSampleFormat"]) + ", 8bit CHAR", 2) 662 | Data1 = getValue(data, index, 'B', endian, nd) 663 | else: 664 | printverbose("readSegyData : DSF=" + str(SH["DataSampleFormat"]) + ", NOT SUPORTED", 2) 665 | 666 | Data = Data1[0] 667 | 668 | printverbose("readSegyData : - reshaping", 2) 669 | printverbose(" ns=" + str(SH['ns']),-2) 670 | Data = np.reshape(np.array(Data), (SH['ntraces'], SH['ns'] + ndummy_samples)) 671 | printverbose("readSegyData : - stripping header dummy data", 2) 672 | Data = Data[:, ndummy_samples:(SH['ns'] + ndummy_samples)] 673 | printverbose("readSegyData : - transposing", 2) 674 | Data = np.transpose(Data) 675 | 676 | # SOMEONE NEEDS TO IMPLEMENT A NICER WAY DO DEAL WITH DSF=8 677 | if (SH["DataSampleFormat"] == 8): 678 | for i in np.arange(SH['ntraces']): 679 | for j in np.arange(SH['ns']): 680 | if Data[i][j] > 128: 681 | Data[i][j] = Data[i][j] - 256 682 | 683 | printverbose("readSegyData : Finished reading segy data", 1) 684 | 685 | return Data, SH, STH 686 | 687 | 688 | # %% 689 | def getSegyTrace(SH, itrace, endian='>'): # modified by A Squelch 690 | """ 691 | SegyTraceHeader,SegyTraceData=getSegyTrace(SegyHeader,itrace) 692 | itrace : trace number to read 693 | THIS DEF IS NOT UPDATED. NOT READY TO USE 694 | """ 695 | data = open(SH["filename"], 'rb').read() 696 | 697 | bps = getBytePerSample(SH) 698 | 699 | # GET TRACE HEADER 700 | index = 3200 + (itrace - 1) * (240 + SH['ns'] * bps) 701 | SegyTraceHeader = []; 702 | # print index 703 | 704 | # GET TRACE 705 | index = 3200 + (itrace - 1) * (240 + SH['ns'] * bps) + 240 706 | SegyTraceData = getValue(data, index, 'float', endian, SH['ns']) 707 | return SegyTraceHeader, SegyTraceData 708 | 709 | 710 | # %% 711 | def getSegyHeader(filename, endian='>'): # modified by A Squelch 712 | """ 713 | SegyHeader=getSegyHeader(filename) 714 | """ 715 | 716 | data = open(filename, 'rb').read() 717 | 718 | SegyHeader = {'filename': filename} 719 | 720 | j = 0; 721 | for key in SH_def.keys(): 722 | j = j + 1; 723 | pos = SH_def[key]["pos"] 724 | format = SH_def[key]["type"] 725 | 726 | txt = "i=%3d, pos=%5d, format=%2s, key=%s" % (j, pos, format, key); 727 | printverbose(txt, 10) 728 | 729 | SegyHeader[key], index = getValue(data, pos, format, endian); 730 | 731 | txt = "SegyHeader[%s] = %f" % (key, SegyHeader[key]) 732 | printverbose(txt, 2) 733 | 734 | # SET NUMBER OF BYTES PER DATA SAMPLE 735 | bps = getBytePerSample(SegyHeader) 736 | 737 | filesize = len(data) 738 | ntraces = (filesize - 3600) / (SegyHeader['ns'] * bps + 240) 739 | SegyHeader["ntraces"] = ntraces 740 | SegyHeader["time"]=np.arange(SegyHeader['ns']) * SegyHeader['dt'] / 1e+6 741 | 742 | 743 | printverbose('getSegyHeader : succesfully read ' + filename, 1) 744 | 745 | return SegyHeader 746 | 747 | 748 | # %% 749 | def writeSegy(filename, Data, dt=1000, STHin={}, SHin={}): 750 | """ 751 | writeSegy(filename,Data,dt) 752 | 753 | Write SEGY 754 | 755 | See also readSegy 756 | 757 | (c) 2005, Thomas Mejer Hansen 758 | 759 | MAKE OPTIONAL INPUT FOR ALL SEGYHTRACEHEADER VALUES 760 | 761 | """ 762 | 763 | printverbose("writeSegy : Trying to write " + filename, 0) 764 | 765 | N = Data.shape 766 | ns = N[0] 767 | ntraces = N[1] 768 | print(ntraces) 769 | print(ns) 770 | 771 | SH = getDefaultSegyHeader(ntraces, ns); 772 | STH = getDefaultSegyTraceHeaders(ntraces, ns, dt) 773 | 774 | # ADD STHin, if exists... 775 | for key in STHin.keys(): 776 | print(key) 777 | for a in range(ntraces): 778 | STH[key] = STHin[key][a] 779 | 780 | # ADD SHin, if exists... 781 | for key in SHin.keys(): 782 | print(key) 783 | SH[key] = SHin[key] 784 | 785 | writeSegyStructure(filename, Data, SH, STH) 786 | 787 | 788 | # %% 789 | def writeSegyStructure(filename, Data, SH, STH, endian='>'): # modified by A Squelch 790 | """ 791 | writeSegyStructure(filename,Data,SegyHeader,SegyTraceHeaders) 792 | 793 | Write SEGY file using SegyPy data structures 794 | 795 | See also readSegy 796 | 797 | (c) 2005, Thomas Mejer Hansen 798 | 799 | """ 800 | 801 | printverbose("writeSegyStructure : Trying to write " + filename, 0) 802 | 803 | f = open(filename, 'wb') 804 | 805 | # VERBOSE INF 806 | revision = SH["SegyFormatRevisionNumber"] 807 | dsf = SH["DataSampleFormat"] 808 | if (revision == 100): 809 | revision = 1 810 | if (revision == 256): # added by A Squelch 811 | revision = 1 812 | 813 | try: # block added by A Squelch 814 | DataDescr = SH_def["DataSampleFormat"]["descr"][revision][dsf] 815 | except KeyError: 816 | print("") 817 | print(" An error has ocurred interpreting a SEGY binary header key") 818 | print(" Please check the Endian setting for this file: ", SH["filename"]) 819 | sys.exit() 820 | 821 | printverbose("writeSegyStructure : SEG-Y revision = " + str(revision), 1) 822 | printverbose("writeSegyStructure : DataSampleFormat=" + str(dsf) + "(" + DataDescr + ")", 1) 823 | 824 | # WRITE SEGY HEADER 825 | 826 | for key in SH_def.keys(): 827 | pos = SH_def[key]["pos"] 828 | format = SH_def[key]["type"] 829 | value = SH[key] 830 | 831 | # SegyHeader[key],index = putValue(value,f,pos,format,endian); 832 | putValue(value, f, pos, format, endian); 833 | 834 | txt = str(pos) + " " + str(format) + " Reading " + key + "=" + str(value) 835 | # +"="+str(SegyHeader[key]) 836 | # printverbose(txt,-1) 837 | 838 | # SEGY TRACES 839 | 840 | ctype = SH_def['DataSampleFormat']['datatype'][revision][dsf] 841 | bps = SH_def['DataSampleFormat']['bps'][revision][dsf] 842 | 843 | sizeT = 240 + SH['ns'] * bps; 844 | 845 | for itrace in range(SH['ntraces']): 846 | index = 3600 + itrace * sizeT 847 | printverbose('Writing Trace #' + str(itrace + 1) + '/' + str(SH['ntraces']), 10) 848 | # WRITE SEGY TRACE HEADER 849 | for key in STH_def.keys(): 850 | pos = index + STH_def[key]["pos"] 851 | format = STH_def[key]["type"] 852 | value = STH[key][itrace] 853 | txt = str(pos) + " " + str(format) + " Writing " + key + "=" + str(value) 854 | printverbose(txt, 40) 855 | putValue(value, f, pos, format, endian); 856 | 857 | # Write Data 858 | cformat = endian + ctype 859 | for s in range(SH['ns']): 860 | strVal = struct.pack(cformat, Data[s, itrace]) 861 | f.seek(index + 240 + s * struct.calcsize(cformat)) 862 | f.write(strVal); 863 | 864 | f.close 865 | 866 | # return segybuffer 867 | 868 | 869 | # %% 870 | def putValue(value, fileid, index, ctype='l', endian='>', number=1): 871 | """ 872 | putValue(data,index,ctype,endian,number) 873 | """ 874 | if (ctype == 'l') | (ctype == 'long') | (ctype == 'int32'): 875 | size = l_long 876 | ctype = 'l' 877 | elif (ctype == 'L') | (ctype == 'ulong') | (ctype == 'uint32'): 878 | size = l_ulong 879 | ctype = 'L' 880 | elif (ctype == 'h') | (ctype == 'short') | (ctype == 'int16'): 881 | size = l_short 882 | ctype = 'h' 883 | elif (ctype == 'H') | (ctype == 'ushort') | (ctype == 'uint16'): 884 | size = l_ushort 885 | ctype = 'H' 886 | elif (ctype == 'c') | (ctype == 'char'): 887 | size = l_char 888 | ctype = 'c' 889 | elif (ctype == 'B') | (ctype == 'uchar'): 890 | size = l_uchar 891 | ctype = 'B' 892 | elif (ctype == 'f') | (ctype == 'float'): 893 | size = l_float 894 | ctype = 'f' 895 | elif (ctype == 'ibm'): 896 | size = l_float 897 | else: 898 | printverbose('Bad Ctype : ' + ctype, -1) 899 | 900 | cformat = endian + ctype * number 901 | 902 | printverbose('putValue : cformat : ' + cformat + ' ctype=' + ctype, 40) 903 | 904 | strVal = struct.pack(cformat, value) 905 | fileid.seek(index) 906 | fileid.write(strVal); 907 | 908 | return 1 909 | 910 | 911 | # %% 912 | def getValue(data, index, ctype='l', endian='>', number=1): 913 | """ 914 | getValue(data,index,ctype,endian,number) 915 | """ 916 | if (ctype == 'l') | (ctype == 'long') | (ctype == 'int32'): 917 | size = l_long 918 | ctype = 'l' 919 | elif (ctype == 'L') | (ctype == 'ulong') | (ctype == 'uint32'): 920 | size = l_ulong 921 | ctype = 'L' 922 | elif (ctype == 'h') | (ctype == 'short') | (ctype == 'int16'): 923 | size = l_short 924 | ctype = 'h' 925 | elif (ctype == 'H') | (ctype == 'ushort') | (ctype == 'uint16'): 926 | size = l_ushort 927 | ctype = 'H' 928 | elif (ctype == 'c') | (ctype == 'char'): 929 | size = l_char 930 | ctype = 'c' 931 | elif (ctype == 'B') | (ctype == 'uchar'): 932 | size = l_uchar 933 | ctype = 'B' 934 | elif (ctype == 'f') | (ctype == 'float'): 935 | size = l_float 936 | ctype = 'f' 937 | elif (ctype == 'ibm'): 938 | size = l_float 939 | ctype = 'ibm' 940 | else: 941 | printverbose('Bad Ctype : ' + ctype, -1) 942 | 943 | index_end = index + size * number 944 | 945 | printverbose("index=%d, number=%d, size=%d, ctype=%s" % (index, number, size, ctype), 8); 946 | printverbose("index, index_end = " + str(index) + "," + str(index_end), 9) 947 | 948 | if (ctype == 'ibm'): 949 | # ASSUME IBM FLOAT DATA 950 | Value = list(range(int(number))) 951 | for i in np.arange(number): 952 | index_ibm_start = i * 4 + index 953 | index_ibm_end = index_ibm_start + 4; 954 | ibm_val = ibm2ieee2(data[index_ibm_start:index_ibm_end]) 955 | Value[i] = ibm_val; 956 | # this resturn an array as opposed to a tuple 957 | else: 958 | # ALL OTHER TYPES OF DATA 959 | cformat = 'f' * number 960 | cformat = endian + ctype * number 961 | 962 | printverbose("getValue : cformat : '" + cformat + "'", 11) 963 | 964 | Value = struct.unpack(cformat, data[index:index_end]) 965 | 966 | if (ctype == 'B'): 967 | printverbose('getValue : Ineficient use of 1byte Integer...', -1) 968 | 969 | vtxt = 'getValue : ' + 'start=' + str(index) + ' size=' + str(size) + ' number=' + str( 970 | number) + ' Value=' + str(Value) + ' cformat=' + str(cformat) 971 | printverbose(vtxt, 20) 972 | 973 | if number == 1: 974 | return Value[0], index_end 975 | else: 976 | return Value, index_end 977 | 978 | 979 | # %% 980 | def print_version(): 981 | print('SegyPY version is ', version) 982 | 983 | 984 | # %% 985 | def printverbose(txt, level=1): 986 | if level <= verbose: 987 | print('SegyPY' + version + ': ', txt) 988 | 989 | 990 | # %% 991 | ############## 992 | # MISC FUNCTIONS 993 | def ibm2Ieee(ibm_float): 994 | """ 995 | ibm2Ieee(ibm_float) 996 | Used by permission 997 | (C) Secchi Angelo 998 | with thanks to Howard Lightstone and Anton Vredegoor. 999 | """ 1000 | """ 1001 | I = struct.unpack('>I',ibm_float)[0] 1002 | sign = [1,-1][bool(i & 0x100000000L)] 1003 | characteristic = ((i >> 24) & 0x7f) - 64 1004 | fraction = (i & 0xffffff)/float(0x1000000L) 1005 | return sign*16**characteristic*fraction 1006 | """ 1007 | 1008 | 1009 | def ibm2ieee2(ibm_float): 1010 | """ 1011 | ibm2ieee2(ibm_float) 1012 | Used by permission 1013 | (C) Secchi Angelo 1014 | with thanks to Howard Lightstone and Anton Vredegoor. 1015 | """ 1016 | dividend = float(16 ** 6) 1017 | 1018 | if ibm_float == 0: 1019 | return 0.0 1020 | istic, a, b, c = struct.unpack('>BBBB', ibm_float) 1021 | if istic >= 128: 1022 | sign = -1.0 1023 | istic = istic - 128 1024 | else: 1025 | sign = 1.0 1026 | mant = float(a << 16) + float(b << 8) + float(c) 1027 | return sign * 16 ** (istic - 64) * (mant / dividend) 1028 | 1029 | 1030 | def getBytePerSample(SH): 1031 | revision = SH["SegyFormatRevisionNumber"] 1032 | if (revision == 100): 1033 | revision = 1 1034 | if (revision == 256): # added by A Squelch 1035 | revision = 1 1036 | 1037 | dsf = SH["DataSampleFormat"] 1038 | 1039 | try: # block added by A Squelch 1040 | bps = SH_def["DataSampleFormat"]["bps"][revision][dsf] 1041 | except KeyError: 1042 | print("") 1043 | print(" An error has ocurred interpreting a SEGY binary header key") 1044 | print(" Please check the Endian setting for this file: ", SH["filename"]) 1045 | sys.exit() 1046 | 1047 | printverbose("getBytePerSample : bps=" + str(bps), 21); 1048 | 1049 | return bps 1050 | 1051 | 1052 | ############## 1053 | # segy class 1054 | class SegyTraceheaderClass: 1055 | def __init__(self): 1056 | self.cdp = 0 1057 | 1058 | 1059 | class SegyHeaderClass: 1060 | def __str__(self): 1061 | return "SegyHeaderClass " 1062 | 1063 | def __init__(self): 1064 | self.filename = 0 1065 | self.Trace = version 1066 | 1067 | def cdp(self): 1068 | return "Getting CDP trace header" 1069 | 1070 | def InlineX(self): 1071 | return "Getting CDP trace header" 1072 | 1073 | 1074 | class SegyClass: 1075 | STH_def = STH_def 1076 | SH_def = SH_def 1077 | STH = SegyTraceheaderClass() 1078 | SH = SegyHeaderClass() 1079 | 1080 | def __init__(self): 1081 | self.THOMAS = 'Thomas' 1082 | -------------------------------------------------------------------------------- /build/lib/PyOSGPUP/signalpy.py: -------------------------------------------------------------------------------- 1 | 2 | import numpy as np 3 | from numpy.fft.fftpack import fft,ifft 4 | 5 | def hilbert(mag): 6 | """Compute the modified 1D discrete Hilbert transform 7 | 8 | Parameters 9 | ---------- 10 | mag : ndarray 11 | The magnitude spectrum. Should be 1D with an even length, and 12 | preferably a fast length for FFT/IFFT. 13 | """ 14 | # Adapted based on code by Niranjan Damera-Venkata, 15 | # Brian L. Evans and Shawn R. McCaslin (see refs for `minimum_phase`) 16 | sig = np.zeros(len(mag)) 17 | # Leave Nyquist and DC at 0, knowing np.abs(fftfreq(N)[midpt]) == 0.5 18 | midpt = len(mag) // 2 19 | sig[1:midpt] = 1 20 | sig[midpt+1:] = -1 21 | # eventually if we want to support complex filters, we will need a 22 | # np.abs() on the mag inside the log, and should remove the .real 23 | recon = ifft(mag * np.exp(fft(sig * ifft(np.log(mag))))).real 24 | return recon 25 | 26 | -------------------------------------------------------------------------------- /build/lib/PyOSGPUP/synthe_seismo.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | import matplotlib.pyplot as plt 3 | import PyOSGPUP.wavelet as wavelet 4 | 5 | 6 | def getPlotLog(d, log, dmax=200): 7 | d = np.array(d, dtype=float) 8 | log = np.array(log, dtype=float) 9 | 10 | dplot = np.kron(d, np.ones(2)) 11 | logplot = np.kron(log, np.ones(2)) 12 | 13 | # dplot = dplot[1:] 14 | dplot = np.append(dplot[1:], dmax) 15 | 16 | return dplot, logplot 17 | 18 | 19 | def getImpedance(rholog, vlog): 20 | """ 21 | Acoustic Impedance is the product of density and velocity 22 | $$ 23 | Z = \\rho v 24 | $$ 25 | """ 26 | rholog, vlog = np.array(rholog, dtype=float), np.array(vlog, dtype=float), 27 | return rholog * vlog 28 | 29 | 30 | def getReflectivity(d, rho, v, usingT=True): 31 | """ 32 | The reflection coefficient of an interface is $$ R_i = \\frac{Z_{i+1} - Z_{i}}{Z_{i+1}+Z_{i}} $$ The reflectivity 33 | can also include the effect of transmission through above layers, in which case the reflectivity is given by $$ 34 | \\text{reflectivity} = R_i \\pi_{j = 1}^{i-1}(1-R_j^2) $$ 35 | """ 36 | Z = getImpedance(rho, v) # acoustic impedance 37 | dZ = (Z[1:] - Z[:-1]) 38 | sZ = (Z[:-1] + Z[1:]) 39 | R = dZ / sZ # reflection coefficients 40 | 41 | nlayer = len(v) # number of layers 42 | 43 | rseries = R 44 | 45 | if usingT: 46 | for i in range(nlayer - 1): 47 | rseries[i + 1:] = rseries[i + 1:] * (1. - R[i] ** 2) 48 | 49 | return rseries, R 50 | 51 | 52 | def getTimeDepth(d,v,dmax=200): 53 | """ 54 | The time depth conversion is computed by determining the two-way travel time for a reflection from a given depth. 55 | """ 56 | 57 | d = np.sort(d) 58 | d = np.append(d,dmax) 59 | 60 | twttop = 2.*np.diff(d)/v # 2-way travel time within each layer 61 | twttop = np.append(0.,twttop) 62 | twttop = np.cumsum(twttop) # 2-way travel time from surface to top of each layer 63 | 64 | return d, twttop 65 | 66 | 67 | def getLogs(d, rho, v, usingT=True): 68 | """ 69 | Function to make plotting convenient 70 | """ 71 | dpth, rholog = getPlotLog(d, rho) 72 | _, vlog = getPlotLog(d, v) 73 | zlog = getImpedance(rholog, vlog) 74 | rseries, _ = getReflectivity(d, rho, v, usingT) 75 | return dpth, rholog, vlog, zlog, rseries 76 | 77 | 78 | def plotLogFormat(log, dpth, xlim, col='blue'): 79 | """ 80 | Nice formatting for plotting logs as a function of depth 81 | """ 82 | ax = plt.plot(log, dpth, linewidth=2, color=col) 83 | plt.xlim(xlim) 84 | plt.ylim((dpth.min(), dpth.max())) 85 | plt.grid() 86 | plt.gca().invert_yaxis() 87 | plt.setp(plt.xticks()[1], rotation='90', fontsize=9) 88 | plt.setp(plt.yticks()[1], fontsize=9) 89 | 90 | return ax 91 | 92 | 93 | def plotLogs(d, rho, v, usingT=True): 94 | """ 95 | Plotting wrapper to plot density, velocity, acoustic impedance and reflectivity as a function of depth. 96 | """ 97 | d = np.sort(d) 98 | 99 | dpth, rholog, vlog, zlog, rseries = getLogs(d, rho, v, usingT) 100 | nd = len(dpth) 101 | 102 | xlimrho = (1.95, 5.05) 103 | xlimv = (0.25, 4.05) 104 | xlimz = (xlimrho[0] * xlimv[0], xlimrho[1] * xlimv[1]) 105 | 106 | # Plot Density 107 | plt.figure(1) 108 | 109 | plt.subplot(141) 110 | plotLogFormat(rholog * 10 ** -3, dpth, xlimrho, 'blue') 111 | plt.title('$\\rho$') 112 | plt.xlabel('Density \n $\\times 10^3$ (kg /m$^3$)', fontsize=9) 113 | plt.ylabel('Depth (m)', fontsize=9) 114 | 115 | plt.subplot(142) 116 | plotLogFormat(vlog * 10 ** -3, dpth, xlimv, 'red') 117 | plt.title('$v$') 118 | plt.xlabel('Velocity \n $\\times 10^3$ (m/s)', fontsize=9) 119 | plt.setp(plt.yticks()[1], visible=False) 120 | 121 | plt.subplot(143) 122 | plotLogFormat(zlog * 10. ** -6., dpth, xlimz, 'green') 123 | plt.gca().set_title('$Z = \\rho v$') 124 | plt.gca().set_xlabel('Impedance \n $\\times 10^{6}$ (kg m$^{-2}$ s$^{-1}$)', fontsize=9) 125 | plt.setp(plt.yticks()[1], visible=False) 126 | 127 | plt.subplot(144) 128 | plt.hlines(d[1:], np.zeros(nd - 1), rseries, linewidth=2) 129 | plt.plot(np.zeros(nd), dpth, linewidth=2, color='black') 130 | plt.title('Reflectivity') 131 | plt.xlim((-1., 1.)) 132 | plt.gca().set_xlabel('Reflectivity') 133 | plt.grid() 134 | plt.gca().invert_yaxis() 135 | plt.setp(plt.xticks()[1], rotation='90', fontsize=9) 136 | plt.setp(plt.yticks()[1], visible=False) 137 | 138 | plt.tight_layout() 139 | plt.show() 140 | 141 | 142 | def plotLogsInteract(d2, d3, rho1, rho2, rho3, v1, v2, v3, usingT=False): 143 | """ 144 | interactive wrapper of plotLogs 145 | """ 146 | d = np.array((0., d2, d3), dtype=float) 147 | rho = np.array((rho1, rho2, rho3), dtype=float) 148 | v = np.array((v1, v2, v3), dtype=float) 149 | plotLogs(d, rho, v, usingT) 150 | 151 | 152 | def plotTimeDepth(d,v): 153 | """ 154 | Wrapper to plot time-depth conversion based on the provided velocity model 155 | """ 156 | 157 | dpth,t = getTimeDepth(d,v) 158 | plt.figure() 159 | plt.plot(dpth,t,linewidth=2) 160 | plt.title('Depth-Time') 161 | plt.grid() 162 | plt.gca().set_xlabel('Depth (m)',fontsize=9) 163 | plt.gca().set_ylabel('Two Way Time (s)',fontsize=9) 164 | 165 | plt.tight_layout() 166 | plt.show() 167 | 168 | 169 | def syntheticSeismogram(d, rho, v, wavf, wavA=1., usingT=True, wavtyp = 'RICKER', dt=0.0001, dmax=200): 170 | """ 171 | function syntheticSeismogram(d, rho, v, wavtyp, wavf, usingT) 172 | syntheicSeismogram generates a synthetic seismogram for 173 | a simple 1-D layered model. 174 | Inputs: 175 | d : depth to the top of each layer (m) 176 | rho : density of each layer (kg/m^3) 177 | v : velocity of each layer (m/s) 178 | The last layer is assumed to be a half-space 179 | wavf : wavelet frequency 180 | wavA : wavelet amplitude 181 | usintT : using Transmission coefficients? 182 | wavtyp : type of Wavelet 183 | The wavelet options are: 184 | Ricker: takes one frequency 185 | Gaussian: still in progress 186 | Ormsby: takes 4 frequencies 187 | Klauder: takes 2 frequencies 188 | usingT : use transmission coefficients? 189 | Lindsey Heagy 190 | lheagy@eos.ubc.ca 191 | Created: November 30, 2013 192 | Modified: October 3, 2014 193 | """ 194 | 195 | v, rho, d = np.array(v, dtype=float), np.array(rho, dtype=float), np.array(d, dtype=float) 196 | usingT = np.array(usingT, dtype=bool) 197 | 198 | _, t = getTimeDepth(d,v,dmax) 199 | rseries,R = getReflectivity(d,rho,v) 200 | 201 | # time for reflectivity series 202 | tref = t[1:-1] 203 | 204 | # create time vector 205 | t = np.arange(t.min(),t.max(),dt) 206 | 207 | # make wavelet 208 | twav = np.arange(-2.0/np.min(wavf), 2.0/np.min(wavf), dt) 209 | 210 | # Get source wavelet 211 | wav = {'RICKER':wavelet.getRicker, 'ORMSBY':wavelet.getOrmsby, 'KLAUDER':wavelet.getKlauder}[wavtyp](wavf,twav) 212 | wav = wavA*wav 213 | 214 | rseriesconv = np.zeros(len(t)) 215 | for i in range(len(tref)): 216 | index = np.abs(t - tref[i]).argmin() 217 | rseriesconv[index] = rseries[i] 218 | 219 | # Do the convolution 220 | seis = np.convolve(wav,rseriesconv) 221 | tseis = np.min(twav)+dt*np.arange(len(seis)) 222 | index = np.logical_and(tseis >= 0, tseis <= np.max(t)) 223 | tseis = tseis[index] 224 | seis = seis[index] 225 | 226 | return tseis, seis, twav, wav, tref, rseries 227 | 228 | 229 | def plotSeismogram(d, rho, v, wavf, wavA=1., noise = 0., usingT=True, wavtyp='RICKER'): 230 | """ 231 | Plotting function to show physical property logs (in depth) and seismogram (in time). 232 | """ 233 | 234 | dpth, rholog, vlog, zlog, rseries = getLogs(d, rho, v, usingT) 235 | tseis, seis, twav, wav, tref, rseriesconv = syntheticSeismogram(d, rho, v, wavf, wavA, usingT,wavtyp) 236 | 237 | noise = noise*np.max(np.abs(seis))*np.random.randn(seis.size) 238 | filt = np.arange(1.,21.) 239 | filtr = filt[::-1] 240 | filt = np.append(filt,filtr[1:])*1./21. 241 | noise = np.convolve(noise,filt) 242 | noise = noise[0:seis.size] 243 | 244 | xlimrho = (1.95,5.05) 245 | xlimv = (0.25,4.05) 246 | xlimz = (xlimrho[0]*xlimv[0], xlimrho[1]*xlimv[1]) 247 | 248 | seis = seis + noise 249 | 250 | plt.figure() 251 | 252 | plt.subplot(131) 253 | plotLogFormat(rholog*10**-3,dpth,xlimrho,'blue') 254 | plt.title('$\\rho$') 255 | plt.xlabel('Density \n $\\times 10^3$ (kg /m$^3$)',fontsize=9) 256 | plt.ylabel('Depth (m)',fontsize=9) 257 | 258 | plt.subplot(132) 259 | plotLogFormat(vlog*10**-3,dpth,xlimv,'red') 260 | plt.title('$v$') 261 | plt.xlabel('Velocity \n $\\times 10^3$ (m/s)',fontsize=9) 262 | plt.ylabel('Depth (m)',fontsize=9) 263 | 264 | plt.subplot(133) 265 | plt.plot(seis,tseis,color='black',linewidth=1) 266 | plt.title('Seismogram') 267 | plt.grid() 268 | plt.ylim((tseis.min(),tseis.max())) 269 | plt.gca().invert_yaxis() 270 | plt.xlim((-0.5,0.5)) 271 | plt.setp(plt.xticks()[1],rotation='90',fontsize=9) 272 | plt.setp(plt.yticks()[1],fontsize=9) 273 | plt.gca().set_xlabel('Amplitude',fontsize=9) 274 | plt.gca().set_ylabel('Time (s)',fontsize=9) 275 | 276 | plt.tight_layout() 277 | plt.show() -------------------------------------------------------------------------------- /build/lib/PyOSGPUP/tuning_wedge_acces.py: -------------------------------------------------------------------------------- 1 | import numpy as np 2 | from matplotlib import gridspec 3 | import matplotlib.pyplot as plt 4 | from PyOSGPUP.signalpy import hilbert 5 | 6 | 7 | def plot_vawig(axhdl, data, t, excursion, highlight=None): 8 | [ntrc, nsamp] = data.shape 9 | 10 | t = np.hstack([0, t, t.max()]) 11 | 12 | for i in range(0, ntrc): 13 | tbuf = excursion * data[i] / np.max(np.abs(data)) + i 14 | 15 | tbuf = np.hstack([i, tbuf, i]) 16 | 17 | if i == highlight: 18 | lw = 2 19 | else: 20 | lw = 0.5 21 | 22 | axhdl.plot(tbuf, t, color='black', linewidth=lw) 23 | 24 | plt.fill_betweenx(t, tbuf, i, where=tbuf > i, facecolor=[0.6, 0.6, 1.0], linewidth=0) 25 | plt.fill_betweenx(t, tbuf, i, where=tbuf < i, facecolor=[1.0, 0.7, 0.7], linewidth=0) 26 | 27 | axhdl.set_xlim((-excursion, ntrc + excursion)) 28 | axhdl.xaxis.tick_top() 29 | axhdl.xaxis.set_label_position('top') 30 | axhdl.invert_yaxis() 31 | 32 | 33 | def ricker(cfreq, phase, dt, wvlt_length): 34 | ''' 35 | Calculate a ricker wavelet 36 | 37 | Usage: 38 | ------ 39 | t, wvlt = wvlt_ricker(cfreq, phase, dt, wvlt_length) 40 | 41 | cfreq: central frequency of wavelet in Hz 42 | phase: wavelet phase in degrees 43 | dt: sample rate in seconds 44 | wvlt_length: length of wavelet in seconds 45 | ''' 46 | 47 | nsamp = int(wvlt_length / dt + 1) 48 | t_max = wvlt_length * 0.5 49 | t_min = -t_max 50 | 51 | t = np.arange(t_min, t_max, dt) 52 | 53 | t = np.linspace(-wvlt_length / 2, (wvlt_length - dt) / 2, wvlt_length / dt) 54 | wvlt = (1.0 - 2.0 * (np.pi ** 2) * (cfreq ** 2) * (t ** 2)) * np.exp(-(np.pi ** 2) * (cfreq ** 2) * (t ** 2)) 55 | 56 | if phase != 0: 57 | phase = phase * np.pi / 180.0 58 | wvlth = hilbert(wvlt) 59 | wvlth = np.imag(wvlth) 60 | wvlt = np.cos(phase) * wvlt - np.sin(phase) * wvlth 61 | 62 | return t, wvlt 63 | 64 | 65 | def wvlt_bpass(f1, f2, f3, f4, phase, dt, wvlt_length): 66 | ''' 67 | Calculate a trapezoidal bandpass wavelet 68 | 69 | Usage: 70 | ------ 71 | t, wvlt = wvlt_ricker(f1, f2, f3, f4, phase, dt, wvlt_length) 72 | 73 | f1: Low truncation frequency of wavelet in Hz 74 | f2: Low cut frequency of wavelet in Hz 75 | f3: High cut frequency of wavelet in Hz 76 | f4: High truncation frequency of wavelet in Hz 77 | phase: wavelet phase in degrees 78 | dt: sample rate in seconds 79 | wvlt_length: length of wavelet in seconds 80 | ''' 81 | 82 | from numpy.fft import fft, ifft, fftfreq, fftshift, ifftshift 83 | 84 | nsamp = int(wvlt_length / dt + 1) 85 | 86 | freq = fftfreq(nsamp, dt) 87 | freq = fftshift(freq) 88 | aspec = freq * 0.0 89 | pspec = freq * 0.0 90 | 91 | # Calculate slope and y-int for low frequency ramp 92 | M1 = 1 / (f2 - f1) 93 | b1 = -M1 * f1 94 | 95 | # Calculate slop and y-int for high frequency ramp 96 | M2 = -1 / (f4 - f3) 97 | b2 = -M2 * f4 98 | 99 | # Build initial frequency and filter arrays 100 | freq = fftfreq(nsamp, dt) 101 | freq = fftshift(freq) 102 | filt = np.zeros(nsamp) 103 | 104 | # Build LF ramp 105 | idx = np.nonzero((np.abs(freq) >= f1) & (np.abs(freq) < f2)) 106 | filt[idx] = M1 * np.abs(freq)[idx] + b1 107 | 108 | # Build central filter flat 109 | idx = np.nonzero((np.abs(freq) >= f2) & (np.abs(freq) <= f3)) 110 | filt[idx] = 1.0 111 | 112 | # Build HF ramp 113 | idx = np.nonzero((np.abs(freq) > f3) & (np.abs(freq) <= f4)) 114 | filt[idx] = M2 * np.abs(freq)[idx] + b2 115 | 116 | # Unshift the frequencies and convert filter to fourier coefficients 117 | filt2 = ifftshift(filt) 118 | Af = filt2 * np.exp(np.zeros(filt2.shape) * 1j) 119 | 120 | # Convert filter to time-domain wavelet 121 | wvlt = fftshift(ifft(Af)) 122 | wvlt = np.real(wvlt) 123 | wvlt = wvlt / np.max(np.abs(wvlt)) # normalize wavelet by peak amplitude 124 | 125 | # Generate array of wavelet times 126 | t = np.linspace(-wvlt_length * 0.5, wvlt_length * 0.5, nsamp) 127 | 128 | # Apply phase rotation if desired 129 | if phase != 0: 130 | phase = phase * np.pi / 180.0 131 | wvlth = hilbert(wvlt) 132 | wvlth = np.imag(wvlth) 133 | wvlt = np.cos(phase) * wvlt - np.sin(phase) * wvlth 134 | 135 | return t, wvlt 136 | 137 | 138 | def calc_rc(vp_mod, rho_mod): 139 | ''' 140 | rc_int = calc_rc(vp_mod, rho_mod) 141 | ''' 142 | 143 | nlayers = len(vp_mod) 144 | nint = nlayers - 1 145 | 146 | rc_int = [] 147 | for i in range(0, nint): 148 | buf1 = vp_mod[i + 1] * rho_mod[i + 1] - vp_mod[i] * rho_mod[i] 149 | buf2 = vp_mod[i + 1] * rho_mod[i + 1] + vp_mod[i] * rho_mod[i] 150 | buf3 = buf1 / buf2 151 | rc_int.append(buf3) 152 | 153 | return rc_int 154 | 155 | def calc_times(z_int, vp_mod): 156 | ''' 157 | t_int = calc_times(z_int, vp_mod) 158 | ''' 159 | 160 | nlayers = len(vp_mod) 161 | nint = nlayers - 1 162 | 163 | t_int = [] 164 | for i in range(0, nint): 165 | if i == 0: 166 | tbuf = z_int[i] / vp_mod[i] 167 | t_int.append(tbuf) 168 | else: 169 | zdiff = z_int[i] - z_int[i - 1] 170 | tbuf = 2 * zdiff / vp_mod[i] + t_int[i - 1] 171 | t_int.append(tbuf) 172 | 173 | return t_int 174 | 175 | def digitize_model(rc_int, t_int, t): 176 | ''' 177 | rc = digitize_model(rc, t_int, t) 178 | 179 | rc = reflection coefficients corresponding to interface times 180 | t_int = interface times 181 | t = regularly sampled time series defining model sampling 182 | ''' 183 | 184 | import numpy as np 185 | 186 | nlayers = len(rc_int) 187 | nint = nlayers - 1 188 | nsamp = len(t) 189 | 190 | rc = list(np.zeros(nsamp, dtype='float')) 191 | lyr = 0 192 | 193 | for i in range(0, nsamp): 194 | 195 | if t[i] >= t_int[lyr]: 196 | rc[i] = rc_int[lyr] 197 | lyr = lyr + 1 198 | 199 | if lyr > nint: 200 | break 201 | 202 | return rc 203 | 204 | 205 | def wedge_tuning(mod,bound_mod,wave_parm,freq,trace_parm,plot_parm): 206 | ########################################################### 207 | # 208 | # DEFINE MODELING PARAMETERS HERE 209 | # 210 | 211 | # 3-Layer Model Parameters [Layer1, Layer2, Layer 3] 212 | vp_mod = mod[0] # P-wave velocity (m/s) 213 | vs_mod = mod[1] # S-wave velocity (m/s) 214 | rho_mod = mod[2] # Density (g/cc) 215 | 216 | dz_min = bound_mod[0] # Minimum thickness of Layer 2 (m) 217 | dz_max = bound_mod[1] # Maximum thickness of Layer 2 (m) 218 | dz_step = bound_mod[2] # Thickness step from trace-to-trace (normally 1.0 m) 219 | 220 | # Wavelet Parameters 221 | wvlt_type = wave_parm[0] # Valid values: 'ricker' or 'bandpass' 222 | wvlt_length = wave_parm[1] # Wavelet length in seconds 223 | wvlt_phase = wave_parm[2] # Wavelet phase in degrees 224 | wvlt_scalar = wave_parm[3] # Multiplier to scale wavelet amplitude (default = 1.0) 225 | wvlt_cfreq = wave_parm[4] # Ricker wavelet central frequency 226 | f1 = freq[0] # Bandpass wavelet low truncation frequency 227 | f2 = freq[1] # Bandpass wavelet low cut frequency 228 | f3 = freq[2] # Bandpass wavelet high cut frequency 229 | f4 = freq[3] # Bandpass wavelet high truncation frequency 230 | 231 | # Trace Parameters 232 | tmin = trace_parm[0] 233 | tmax = trace_parm[1] 234 | dt = trace_parm[2] # changing this from 0.0001 can affect the display quality 235 | 236 | # Plot Parameters 237 | min_plot_time = plot_parm[0] 238 | max_plot_time = plot_parm[1] 239 | excursion = plot_parm[2] 240 | 241 | ########################################################### 242 | # 243 | # DEFINE MODELING PARAMETERS HERE 244 | # 245 | 246 | # Some handy constants 247 | nlayers = len(vp_mod) 248 | nint = nlayers - 1 249 | nmodel = int((dz_max - dz_min) / dz_step + 1) 250 | 251 | 252 | # Generate wavelet 253 | if wvlt_type == 'ricker': 254 | wvlt_t, wvlt_amp = ricker(wvlt_cfreq, wvlt_phase, dt, wvlt_length) 255 | 256 | elif wvlt_type == 'bandpass': 257 | wvlt_t, wvlt_amp = wvlt_bpass(f1, f2, f3, f4, wvlt_phase, dt, wvlt_length) 258 | 259 | # Apply amplitude scale factor to wavelet (to match seismic amplitude values) 260 | wvlt_amp = wvlt_scalar * wvlt_amp 261 | 262 | # Calculate reflectivities from model parameters 263 | rc_int = calc_rc(vp_mod, rho_mod) 264 | 265 | syn_zo = [] 266 | rc_zo = [] 267 | lyr_times = [] 268 | for model in range(0, nmodel): 269 | 270 | # Calculate interface depths 271 | z_int = [500.0] 272 | z_int.append(z_int[0] + dz_min + dz_step * model) 273 | 274 | # Calculate interface times 275 | t_int = calc_times(z_int, vp_mod) 276 | lyr_times.append(t_int) 277 | 278 | # Digitize 3-layer model 279 | nsamp = int((tmax - tmin) / dt) + 1 280 | t = [] 281 | for i in range(0, nsamp): 282 | t.append(i * dt) 283 | 284 | rc = digitize_model(rc_int, t_int, t) 285 | rc_zo.append(rc) 286 | 287 | # Convolve wavelet with reflectivities 288 | syn_buf = np.convolve(rc, wvlt_amp, mode='same') 289 | syn_buf = list(syn_buf) 290 | syn_zo.append(syn_buf) 291 | print("finished step %i" % (model)) 292 | 293 | syn_zo = np.array(syn_zo) 294 | t = np.array(t) 295 | lyr_times = np.array(lyr_times) 296 | lyr_indx = np.array(np.round(lyr_times / dt), dtype='int16') 297 | 298 | # Use the transpose because rows are traces; 299 | # columns are time samples. 300 | tuning_trace = np.argmax(np.abs(syn_zo.T)) % syn_zo.T.shape[1] 301 | tuning_thickness = tuning_trace * dz_step 302 | 303 | # Plotting Code 304 | [ntrc, nsamp] = syn_zo.shape 305 | 306 | fig = plt.figure(figsize=(12, 14)) 307 | fig.set_facecolor('white') 308 | 309 | gs = gridspec.GridSpec(3, 1, height_ratios=[1, 1, 1]) 310 | 311 | ax0 = fig.add_subplot(gs[0]) 312 | ax0.plot(lyr_times[:, 0], color='blue', lw=1.5) 313 | ax0.plot(lyr_times[:, 1], color='red', lw=1.5) 314 | ax0.set_ylim((min_plot_time, max_plot_time)) 315 | ax0.invert_yaxis() 316 | ax0.set_xlabel('Thickness (m)') 317 | ax0.set_ylabel('Time (s)') 318 | plt.text(2, 319 | min_plot_time + (lyr_times[0, 0] - min_plot_time) / 2., 320 | 'Layer 1', 321 | fontsize=16) 322 | plt.text(dz_max / dz_step - 2, 323 | lyr_times[-1, 0] + (lyr_times[-1, 1] - lyr_times[-1, 0]) / 2., 324 | 'Layer 2', 325 | fontsize=16, 326 | horizontalalignment='right') 327 | plt.text(2, 328 | lyr_times[0, 0] + (max_plot_time - lyr_times[0, 0]) / 2., 329 | 'Layer 3', 330 | fontsize=16) 331 | plt.gca().xaxis.tick_top() 332 | plt.gca().xaxis.set_label_position('top') 333 | ax0.set_xlim((-excursion, ntrc + excursion)) 334 | 335 | ax1 = fig.add_subplot(gs[1]) 336 | plot_vawig(ax1, syn_zo, t, excursion, highlight=tuning_trace) 337 | ax1.plot(lyr_times[:, 0], color='blue', lw=1.5) 338 | ax1.plot(lyr_times[:, 1], color='red', lw=1.5) 339 | ax1.set_ylim((min_plot_time, max_plot_time)) 340 | ax1.invert_yaxis() 341 | ax1.set_xlabel('Thickness (m)') 342 | ax1.set_ylabel('Time (s)') 343 | 344 | ax2 = fig.add_subplot(gs[2]) 345 | ax2.plot(syn_zo[:, lyr_indx[:, 0]], color='blue') 346 | ax2.set_xlim((-excursion, ntrc + excursion)) 347 | ax2.axvline(tuning_trace, color='k', lw=2) 348 | ax2.grid() 349 | ax2.set_title('Upper interface amplitude') 350 | ax2.set_xlabel('Thickness (m)') 351 | ax2.set_ylabel('Amplitude') 352 | plt.text(tuning_trace + 2, 353 | plt.ylim()[0] * 1.1, 354 | 'tuning thickness = {0} m'.format(str(tuning_thickness)), 355 | fontsize=16) 356 | 357 | plt.show() 358 | 359 | 360 | 361 | 362 | 363 | -------------------------------------------------------------------------------- /build/lib/PyOSGPUP/wavelet.py: -------------------------------------------------------------------------------- 1 | # Ref: https://gist.github.com/rowanc1/8338665 2 | import numpy as np 3 | pi = np.pi 4 | 5 | 6 | def getRicker(f, t): 7 | #assert len(f) == 1, 'Ricker wavelet needs 1 frequency as input' 8 | # f = f[0] 9 | pift = pi * f * t 10 | wav = (1 - 2 * pift ** 2) * np.exp(-pift ** 2) 11 | return wav 12 | 13 | 14 | def getOrmsby(f, t): 15 | assert len(f) == 4, 'Ormsby wavelet needs 4 frequencies as input' 16 | f = np.sort(f) # Ormsby wavelet frequencies must be in increasing order 17 | pif = pi * f 18 | den1 = pif[3] - pif[2] 19 | den2 = pif[1] - pif[0] 20 | term1 = (pif[3] * np.sinc(pif[3] * t)) ** 2 - (pif[2] * np.sinc(pif[2])) ** 2 21 | term2 = (pif[1] * np.sinc(pif[1] * t)) ** 2 - (pif[0] * np.sinc(pif[0])) ** 2 22 | 23 | wav = term1 / den1 - term2 / den2 24 | return wav 25 | 26 | 27 | def getKlauder(f, t, T=5.0): 28 | assert len(f) == 2, 'Klauder wavelet needs 2 frequencies as input' 29 | 30 | k = np.diff(f) / T 31 | f0 = np.sum(f) / 2.0 32 | wav = np.real(np.sin(pi * k * t * (T - t)) / (pi * k * t) * np.exp(2 * pi * 1j * f0 * t)) 33 | return wav 34 | -------------------------------------------------------------------------------- /build/lib/sample/__init__.py: -------------------------------------------------------------------------------- 1 | 2 | def main(): 3 | """Entry point for the application script""" 4 | print("Call your main application code here") 5 | -------------------------------------------------------------------------------- /build/lib/sample/package_data.dat: -------------------------------------------------------------------------------- 1 | some data -------------------------------------------------------------------------------- /dist/PyOSGPUP-1.0.3-py3-none-any.whl: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Metkom/PyOSGPUP/93b2e153b3dd4e1f644a704a0d7c62ca3bda8f26/dist/PyOSGPUP-1.0.3-py3-none-any.whl -------------------------------------------------------------------------------- /example/readsegy.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Metkom/PyOSGPUP/93b2e153b3dd4e1f644a704a0d7c62ca3bda8f26/example/readsegy.png -------------------------------------------------------------------------------- /example/seis1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Metkom/PyOSGPUP/93b2e153b3dd4e1f644a704a0d7c62ca3bda8f26/example/seis1.png -------------------------------------------------------------------------------- /example/seis2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Metkom/PyOSGPUP/93b2e153b3dd4e1f644a704a0d7c62ca3bda8f26/example/seis2.png -------------------------------------------------------------------------------- /example/seis3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Metkom/PyOSGPUP/93b2e153b3dd4e1f644a704a0d7c62ca3bda8f26/example/seis3.png -------------------------------------------------------------------------------- /example/wavelet.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Metkom/PyOSGPUP/93b2e153b3dd4e1f644a704a0d7c62ca3bda8f26/example/wavelet.png -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | numpy==1.19.2 2 | matplotlib -------------------------------------------------------------------------------- /setup.cfg: -------------------------------------------------------------------------------- 1 | [egg_info] 2 | tag_build = 3 | tag_date = 0 4 | 5 | -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | from __future__ import print_function 2 | """PyOSGPUP: Python, Open-source, Geophysical Eng. Univ. Pertamina 3 | 4 | A python packages for geophysical data processing modeling, and interpretation. 5 | """ 6 | 7 | from os import path 8 | from distutils.core import setup 9 | from setuptools import find_packages 10 | 11 | here = path.abspath(path.dirname(__file__)) 12 | # Get the long description from the README file 13 | # Get the long description from the README file 14 | with open(path.join(here, 'README.rst'), encoding='utf-8') as f: 15 | long_description = f.read() 16 | 17 | 18 | setup( 19 | name='PyOSGPUP', # Required 20 | version='1.0.3', # Required 21 | 22 | description='An open-source library for geophysical data processing, modeling, and interpretation based on Python.', # Required 23 | long_description=long_description, # Optional 24 | 25 | url='https://sites.google.com/site/metkomup/', # Optional 26 | author='Komputasi Geofisika - Universitas Pertamina', # Optional 27 | author_email='metkom.up@gmail.com', # Optional 28 | 29 | classifiers=[ # Optional 30 | 'Development Status :: 3 - Alpha', 31 | 32 | # Indicate who your project is intended for 33 | 'Intended Audience :: Developers', 34 | 'Topic :: Software Development :: Build Tools', 35 | 36 | # Pick your license as you wish 37 | 'License :: OSI Approved :: MIT License', 38 | 39 | 'Programming Language :: Python :: 3.4', 40 | 'Programming Language :: Python :: 3.5', 41 | 'Programming Language :: Python :: 3.6', 42 | ], 43 | 44 | keywords='geophysical data processing, modeling, and interpretation', # Optional 45 | packages=find_packages(exclude=['contrib', 'docs', 'tests']), # Required 46 | 47 | install_requires=['numpy','matplotlib'], # Optional 48 | 49 | # download_url="https://github.com/Metkom/PyOSGPUP", 50 | project_urls={ # Optional 51 | 'Bug Reports': 'https://github.com/Metkom/PyOSGPUP/issues', 52 | 'Say Thanks!': 'https://sites.google.com/site/metkomup/pyosgpup', 53 | 'Source': 'https://github.com/Metkom/PyOSGPUP', 54 | }, 55 | platforms=["Windows","Linux","Mac OS-X"] 56 | 57 | ) 58 | -------------------------------------------------------------------------------- /tox.ini: -------------------------------------------------------------------------------- 1 | # this file is *not* meant to cover or endorse the use of tox or pytest or 2 | # testing in general, 3 | # 4 | # It's meant to show the use of: 5 | # 6 | # - check-manifest 7 | # confirm items checked into vcs are in your sdist 8 | # - python setup.py check (using the readme_renderer extension) 9 | # confirms your long_description will render correctly on pypi 10 | # 11 | # and also to help confirm pull requests to this project. 12 | 13 | [tox] 14 | envlist = py{27,34,35,36} 15 | 16 | [testenv] 17 | basepython = 18 | py27: python2.7 19 | py34: python3.4 20 | py35: python3.5 21 | py36: python3.6 22 | deps = 23 | check-manifest 24 | readme_renderer 25 | flake8 26 | pytest 27 | commands = 28 | check-manifest --ignore tox.ini,tests* 29 | python setup.py check -m -r -s 30 | flake8 . 31 | py.test tests 32 | [flake8] 33 | exclude = .tox,*.egg,build,data 34 | select = E,W,F 35 | --------------------------------------------------------------------------------