Source code for ADFWI.survey.receiver

from typing import List
import numpy as np
from ADFWI.utils import list2numpy,numpy2list

[docs]class Receiver(object): """Seismic Receiver class for handling receiver locations and seismic data. Parameters ------------- nt (int) : Number of time samples in the receiver data. dt (float) : Time interval between the samples in the receiver data. Notes: ------------- 1. The seismic data is assumed to start at time 0 (i.e., t = 0). 2. The receiver locations are added using the `add_receiver` method. 3. The receiver locations are assumed to be the same for all shots (i.e., the receiver positions are not shot-dependent). This assumption is based on the efficiency of handling regular data (with shape: `nshot, nrec, nt`) on GPUs. However, for models where the receiver locations vary by shot (e.g., streamer data), this may not be flexible. In such cases, offset masking can be applied to regular data to simulate shot-dependent receiver locations. """ def __init__(self,nt:int,dt:float) -> None: self.nt = nt self.dt = dt self.loc_x = [] self.loc_z = [] self.locs = [] self.type = [] self.num = 0 def __repr__(self): """Print the receiver information """ try: rcv_x = np.array(self.loc_x) rcv_z = np.array(self.loc_z) xmin = rcv_x.min() xmax = rcv_x.max() zmin = rcv_z.min() zmax = rcv_z.max() info = f"Seismic Receiver:\n" info += ( f" Receiver data : {self.nt} samples at {self.dt * 1000:.2f} ms\n" ) info += f" Receiver number : {self.num}\n" info += f" Receiver types : {self.get_type(unique = True)}\n" info += f" Receiver x range: {xmin} - {xmax} (grids)\n" info += f" Receiver z range: {zmin} - {zmax} (grids)\n" except: info = f"Seismic Receiver:\n" info += f" empty\n" return info
[docs] def add_receivers(self, rcv_x: np.array,rcv_z:np.array, rcv_type: str) -> None: """add multiple receiver with same type """ if rcv_x.shape != rcv_z.shape: raise ValueError( "Receiver Error: Inconsistant number of receiver in X and Z directions" ) if rcv_type.lower() not in ["pr", "vx", "vz"]: raise ValueError("Receiver type must be either pr, vx, vz") rcv_n = len(rcv_x) # add the receiver self.loc_x.extend(numpy2list(rcv_x.reshape(-1))) self.loc_z.extend(numpy2list(rcv_z.reshape(-1))) self.type.extend([rcv_type]*rcv_n) self.num += rcv_n
[docs] def add_receiver(self, rcv_x:int,rcv_z:int, rcv_type: str) -> None: """Append single receiver """ if rcv_type.lower() not in ["pr", "vx", "vz"]: raise ValueError("Receiver type must be either pr, vx, vz") # add the receiver self.loc_x.append(rcv_x) self.loc_z.append(rcv_z) self.type.append(rcv_type) self.num += 1
[docs] def get_loc(self): """Return the source location """ rcv_x = list2numpy(self.loc_x).reshape(-1,1) rcv_z = list2numpy(self.loc_z).reshape(-1,1) rcv_loc = np.hstack((rcv_x,rcv_z)) self.loc = rcv_loc.copy() return rcv_loc
[docs] def get_type(self, unique=False) -> List[str]: """Return the source type """ type = list2numpy(self.type) if unique: type = list2numpy(list(set(self.type))) return type