{
 "cells": [
  {
   "attachments": {},
   "cell_type": "markdown",
   "id": "9965e19a-97cf-45c0-941e-699602ec60fe",
   "metadata": {},
   "source": [
    "This tutorial demonstrates how to __read a SEG-Y data set using a customized trace header definition table__. The test data is a small SEG-Y file containing three traces with special trace headers such as a shot point line number, a receiver point line number, or a floating datum elevation.\n",
    "\n",
    "Let's start by importing some packages (including the __seisio__ package itself) and setting up the logging config."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "id": "2852c71c-ae09-4fa4-b1a0-9683cbeeda13",
   "metadata": {},
   "outputs": [],
   "source": [
    "import logging\n",
    "import numpy as np\n",
    "import sys\n",
    "sys.path.insert(1, '../')\n",
    "import seisio\n",
    "\n",
    "logging.basicConfig(level=logging.INFO, format='%(levelname)s: %(message)s', force=True)\n",
    "log = logging.getLogger(\"main\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "422834cb-996c-4474-b4f0-8ba8fb815089",
   "metadata": {},
   "source": [
    "We would like to read the file called \"three_traces.sgy\" located in the data directory. In order to do so, we use a customized trace header definition table. We can get a trace header definition template using the *segy_thdef_template()* function of the __seisio__ package, we just have to provide the path and name under which the file should be stored."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "id": "2cd4359e-1ab3-4a72-aa93-34a8ec5584d4",
   "metadata": {},
   "outputs": [],
   "source": [
    "seisio.segy_thdef_template(\"./custom_segy_thdef.json\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "d46e530c-9e6a-497b-81e3-0a3e90384adb",
   "metadata": {},
   "source": [
    "Now we could edit this file to customize it for the SEG-Y file at hand. A pre-edited version is available under the name *three_traces_thdef.json* in the data directory. Here, the standard headers that involve the string \"cdp\" were renamed \"cmp\", and there are some special definitions in byte locations 197 onwards. Please note that we could also read, for instance, floating-point values (32-bit or 64-bit, symbol \"f\" or \"d\", respectively) or other types of entries not usually present in the SEG-Y standard. Before trying to apply the trace header definition file, we can check whether it is valid (or whether we have, for instance, made a mistake in the JSON file):"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "id": "40278514-317f-4837-8894-ea5a1d4143dc",
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "INFO: Trace header definition file data/three_traces_thdef.json is valid. Size: 240 bytes.\n"
     ]
    }
   ],
   "source": [
    "thdef_json = \"data/three_traces_thdef.json\"\n",
    "thdef_is_valid = seisio.check_thdef_validity(thdef_json)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "f20bd14d-8248-438b-aa1e-02dd0bb4c740",
   "metadata": {},
   "source": [
    "Let's create the reader object using our special trace header definition table:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "id": "9e1c85b2-2720-4f45-8652-13e51fb9ec84",
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "INFO: Input file: data/three_traces.sgy\n",
      "INFO: SEG-Y textual file header encoding looks to be 'EBCDIC' (best guess).\n",
      "INFO: Input file endianess looks to be '>' (best guess).\n",
      "INFO: SEG-Y revision: original SEG-Y conforming to 1975 standard.\n",
      "INFO: Data sample format: 4-byte IBM floating-point.\n",
      "WARNING: SEG-Y fixed-trace-length flag is not set in binary header.\n",
      "WARNING: As SEG-Y major revision is 0, assuming fixed-length traces.\n",
      "INFO: Number of additional textual header records: 0.\n",
      "INFO: Number of trailer stanza records: 0.\n",
      "INFO: SEG-Y trace header extension 1 is not present.\n",
      "INFO: Number of user-defined trace headers: 0\n",
      "INFO: Byte offset of first trace relative to start of file: 3600 bytes.\n",
      "INFO: Number of samples per data trace: 1334.\n",
      "INFO: Sampling interval: 3000 (unit as per SEG-Y standard).\n",
      "INFO: Number of data traces in file: 3.\n",
      "INFO: Delay (on first trace): 0 (unit as per SEG-Y standard).\n"
     ]
    }
   ],
   "source": [
    "infile = \"data/three_traces.sgy\"\n",
    "sio = seisio.input(infile, thdef=thdef_json)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "9e47912c-2b61-4015-b4be-373b035102c5",
   "metadata": {},
   "source": [
    "If you get an error about titles already being used when creating the custom data type for Numpy, please ensure that the description fields in the trace header definition file (json) contain unique entries. Now let's read the trace headers from disk and determine some trace header statistics:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "id": "c1ed162c",
   "metadata": {
    "scrolled": true
   },
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "INFO: Calculating trace header statistics.\n",
      "INFO: Reading all 3 trace headers from disk...\n",
      "INFO: Reading all headers took 0.000 seconds.\n",
      "INFO: Summary of trace header statistics (zeros excluded):\n",
      "+---------+------------------+------------------+------------------+---------+------------------+------------------+\n",
      "|         |              min |              max |             mean |     std |              25% |              75% |\n",
      "|---------+------------------+------------------+------------------+---------+------------------+------------------|\n",
      "| fldr    | 200001           | 200001           | 200001           |   0     | 200001           | 200001           |\n",
      "| tracf   |      1           |      3           |      2           |   1     |      1.5         |      2.5         |\n",
      "| cmp     |      1.37501e+08 |      1.37501e+08 |      1.37501e+08 |   1     |      1.37501e+08 |      1.37501e+08 |\n",
      "| trid    |      1           |      1           |      1           |   0     |      1           |      1           |\n",
      "| offset  |   3811           |   3815           |   3813           |   2     |   3812           |   3814           |\n",
      "| gelev   |   8880           |   8900           |   8886.67        |  11.547 |   8880           |   8890           |\n",
      "| selev   |  16360           |  16360           |  16360           |   0     |  16360           |  16360           |\n",
      "| sdepth  |    770           |    770           |    770           |   0     |    770           |    770           |\n",
      "| scalel  |   -100           |   -100           |   -100           |   0     |   -100           |   -100           |\n",
      "| scalco  |   -100           |   -100           |   -100           |   0     |   -100           |   -100           |\n",
      "| sx      |      4.40675e+08 |      4.40675e+08 |      4.40675e+08 |   0     |      4.40675e+08 |      4.40675e+08 |\n",
      "| sy      |      5.77978e+08 |      5.77978e+08 |      5.77978e+08 |   0     |      5.77978e+08 |      5.77978e+08 |\n",
      "| gx      |      4.40519e+08 |      4.4052e+08  |      4.40519e+08 | 820     |      4.40519e+08 |      4.4052e+08  |\n",
      "| gy      |      5.77629e+08 |      5.7763e+08  |      5.7763e+08  | 575.007 |      5.77629e+08 |      5.7763e+08  |\n",
      "| sut     |     12           |     12           |     12           |   0     |     12           |     12           |\n",
      "| ns      |   1334           |   1334           |   1334           |   0     |   1334           |   1334           |\n",
      "| dt      |   3000           |   3000           |   3000           |   0     |   3000           |   3000           |\n",
      "| cmpx    |      4.40597e+08 |      4.40598e+08 |      4.40597e+08 | 409.5   |      4.40597e+08 |      4.40598e+08 |\n",
      "| cmpy    |      5.77803e+08 |      5.77804e+08 |      5.77804e+08 | 286.5   |      5.77803e+08 |      5.77804e+08 |\n",
      "| iline   |   1375           |   1375           |   1375           |   0     |   1375           |   1375           |\n",
      "| xline   |   1071           |   1073           |   1072           |   1     |   1071.5         |   1072.5         |\n",
      "| fldatel |  10676           |  10718           |  10697           |  21     |  10686.5         |  10707.5         |\n",
      "| binel   |    102           |    102           |    102           |   0     |    102           |    102           |\n",
      "| spline  |   5101           |   5101           |   5101           |   0     |   5101           |   5101           |\n",
      "| sp      |   1475           |   1475           |   1475           |   0     |   1475           |   1475           |\n",
      "| rpline  |   1101           |   1101           |   1101           |   0     |   1101           |   1101           |\n",
      "| rp      |   5171           |   5173           |   5172           |   1     |   5171.5         |   5172.5         |\n",
      "| rpidx   |      1           |      1           |      1           |   0     |      1           |      1           |\n",
      "| spiid   |  30762           |  30762           |  30762           |   0     |  30762           |  30762           |\n",
      "| rpiid   |    106           |    128           |    117           |  11     |    111.5         |    122.5         |\n",
      "| spidx   |      1           |      1           |      1           |   0     |      1           |      1           |\n",
      "+---------+------------------+------------------+------------------+---------+------------------+------------------+\n"
     ]
    }
   ],
   "source": [
    "thstat = sio.log_thstat()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "cc90b3f0-485b-42e1-b687-2053dd8caaed",
   "metadata": {},
   "source": [
    "As can clearly be seen, there are no trace headers with the string \"cdp...\", all those headers are called \"cmp...\" as expected, and we have a few custom headers called \"fldatel\", \"binel\", \"spline\", \"sp\", \"rpline\", \"rp\", \"rpidx\", \"spiid\", \"rpiid\" and \"spidx\". Those were defined in the customized JSON trace header definition table. Please note that the customized header definition is not allowed to have gaps and/or overlaps in byte positions. We can also check and log the trace header definition setup itself:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "id": "62f758f3-faa9-4479-8fa3-38d36be992aa",
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "INFO: Trace header definition:\n",
      "+-------------+--------+--------+------------------------------------------------------------------+\n",
      "|             |   byte | type   | description                                                      |\n",
      "|-------------+--------+--------+------------------------------------------------------------------|\n",
      "| tracl       |      0 | i      | Trace sequence number within line                                |\n",
      "| tracr       |      4 | i      | Trace sequence number within file                                |\n",
      "| fldr        |      8 | i      | Original field record number                                     |\n",
      "| tracf       |     12 | i      | Trace number within original field record                        |\n",
      "| ep          |     16 | i      | Energy source point number                                       |\n",
      "| cmp         |     20 | i      | Ensemble number                                                  |\n",
      "| cmpt        |     24 | i      | Trace number within ensemble                                     |\n",
      "| trid        |     28 | h      | Trace identification code                                        |\n",
      "| nvs         |     30 | h      | Number of vertically summed traces                               |\n",
      "| nhs         |     32 | h      | Number of horizontally summed traces                             |\n",
      "| duse        |     34 | h      | Data use                                                         |\n",
      "| offset      |     36 | i      | Distance from center of source point to center of receiver group |\n",
      "| gelev       |     40 | i      | Receiver group elevation from sea level                          |\n",
      "| selev       |     44 | i      | Surface elevation at source                                      |\n",
      "| sdepth      |     48 | i      | Source depth below surface                                       |\n",
      "| gdel        |     52 | i      | Datum elevation at receiver group                                |\n",
      "| sdel        |     56 | i      | Datum elevation at source                                        |\n",
      "| swdep       |     60 | i      | Water depth at source                                            |\n",
      "| gwdep       |     64 | i      | Water depth at receiver group                                    |\n",
      "| scalel      |     68 | h      | Scalar to be applied to elevations and depths                    |\n",
      "| scalco      |     70 | h      | Scalar to be applied to coordinates                              |\n",
      "| sx          |     72 | i      | Source coodinate x                                               |\n",
      "| sy          |     76 | i      | Source coordinate y                                              |\n",
      "| gx          |     80 | i      | Group coordinate x                                               |\n",
      "| gy          |     84 | i      | Group coordinate y                                               |\n",
      "| counit      |     88 | h      | Coordinate units                                                 |\n",
      "| wevel       |     90 | h      | Weathering velocity                                              |\n",
      "| swevel      |     92 | h      | Subewathering velocity                                           |\n",
      "| sut         |     94 | h      | Uphole time at source (ms)                                       |\n",
      "| gut         |     96 | h      | Uphole time at receiver group                                    |\n",
      "| sstat       |     98 | h      | Source static correction                                         |\n",
      "| gstat       |    100 | h      | Group static correction                                          |\n",
      "| tstat       |    102 | h      | Total static applied                                             |\n",
      "| laga        |    104 | h      | Lag time A                                                       |\n",
      "| lagb        |    106 | h      | Lag time B                                                       |\n",
      "| delrt       |    108 | h      | Delay recording time                                             |\n",
      "| muts        |    110 | h      | Mute time start                                                  |\n",
      "| mute        |    112 | h      | Mute time end                                                    |\n",
      "| ns          |    114 | H      | Number of samples                                                |\n",
      "| dt          |    116 | H      | Sample interval                                                  |\n",
      "| gain        |    118 | h      | Gain type of field instrument code                               |\n",
      "| igc         |    120 | h      | Instrument gain constant                                         |\n",
      "| igi         |    122 | h      | Instrument initial gain                                          |\n",
      "| corr        |    124 | h      | Correlated                                                       |\n",
      "| sfs         |    126 | h      | Sweep frequency start                                            |\n",
      "| sfe         |    128 | h      | Sweep frequency end                                              |\n",
      "| slen        |    130 | h      | Sweep length                                                     |\n",
      "| styp        |    132 | h      | Sweep type code                                                  |\n",
      "| stas        |    134 | h      | Sweep trace length at start                                      |\n",
      "| stae        |    136 | h      | Sweep trace length at end                                        |\n",
      "| tatyp       |    138 | h      | Taper type                                                       |\n",
      "| afilf       |    140 | h      | Alias filter frequency                                           |\n",
      "| afils       |    142 | h      | Alias filter slope                                               |\n",
      "| nofilf      |    144 | h      | Notch filter frequency                                           |\n",
      "| nofils      |    146 | h      | Notch filter slope                                               |\n",
      "| lcf         |    148 | h      | Low-cut frequency                                                |\n",
      "| hcf         |    150 | h      | High-cut frequency                                               |\n",
      "| lcs         |    152 | h      | Low-cut slope                                                    |\n",
      "| hcs         |    154 | h      | High-cut slope                                                   |\n",
      "| year        |    156 | h      | Year data recorded                                               |\n",
      "| day         |    158 | h      | Day of year                                                      |\n",
      "| hour        |    160 | h      | Hour of day                                                      |\n",
      "| minute      |    162 | h      | Minute of hour                                                   |\n",
      "| sec         |    164 | h      | Second of minute                                                 |\n",
      "| timbas      |    166 | h      | Time basis code                                                  |\n",
      "| trwf        |    168 | h      | Trace weighting factor                                           |\n",
      "| grnors      |    170 | h      | Geophone group number of roll switch                             |\n",
      "| grnofr      |    172 | h      | Geophone group number of trace one within original field record  |\n",
      "| grnlof      |    174 | h      | Geophone group number of last trace within original field record |\n",
      "| gaps        |    176 | h      | Gap size                                                         |\n",
      "| otrav       |    178 | h      | Overtravel taper code                                            |\n",
      "| cmpx        |    180 | i      | X-coordinate of ensemble                                         |\n",
      "| cmpy        |    184 | i      | Y-coordinate of ensemble                                         |\n",
      "| iline       |    188 | i      | Inline number                                                    |\n",
      "| xline       |    192 | i      | Crossline number                                                 |\n",
      "| fldatel     |    196 | i      | Floating datum elevation                                         |\n",
      "| binel       |    200 | i      | Bin center elevation                                             |\n",
      "| unassigned1 |    204 | h      | Unassigned_1                                                     |\n",
      "| spline      |    206 | i      | Shot point line                                                  |\n",
      "| sp          |    210 | i      | Shot point                                                       |\n",
      "| timscal     |    214 | h      | Scalar to be applied to times in bytes 95-114                    |\n",
      "| rpline      |    216 | i      | Receiver point line                                              |\n",
      "| rp          |    220 | i      | Receiver point                                                   |\n",
      "| rpidx       |    224 | h      | Receiver point index                                             |\n",
      "| spiid       |    226 | i      | Shot point internal ID                                           |\n",
      "| rpiid       |    230 | i      | Receiver point internal ID                                       |\n",
      "| unassigned2 |    234 | i      | Unassigned_2                                                     |\n",
      "| spidx       |    238 | h      | Shot point index                                                 |\n",
      "+-------------+--------+--------+------------------------------------------------------------------+\n"
     ]
    }
   ],
   "source": [
    "sio.log_thdef()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "edc7cab2-020f-4065-ab6b-4c506ced3064",
   "metadata": {},
   "source": [
    "The custom trace headers can be accessed as usual once the data have been read in:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "id": "a0ef999c-064d-4049-8dbf-607deba23f31",
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "INFO: Reading entire file (3 traces) from disk...\n",
      "INFO: Reading all traces took 0.000 seconds.\n",
      "INFO: Converting IBM floats to IEEE floats.\n",
      "INFO: Floating datum elevations in meters: [106.76 106.97 107.18]\n"
     ]
    }
   ],
   "source": [
    "dataset = sio.read_dataset()\n",
    "fldatel = dataset[\"fldatel\"]\n",
    "scalco = dataset[\"scalco\"]\n",
    "float_dat = fldatel/np.abs(scalco)\n",
    "log.info(\"Floating datum elevations in meters: %s\", float_dat)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "36ded65f-2893-4a26-be9d-9344dcbb2ab6",
   "metadata": {},
   "source": [
    "If you write the data back to disk in SEG-Y format, you have to use the same customized trace header definition table on output, otherwise the custom trace headers get lost. Or, alternatively, you have to remap the headers from their customized names to trace header names and types available in the standard SEG-Y trace header definition table."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "610f5de2-8c25-4a04-b434-4d5f1eb96b9f",
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "jupytext": {
   "cell_metadata_filter": "-all",
   "executable": "/usr/bin/env python3",
   "main_language": "python",
   "notebook_metadata_filter": "-all"
  },
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.9.19"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
