Source code for libGP.libGP

"""
GP
library for field work
2023-06-30
Georg Kaufmann
"""

import numpy as np
import scipy
import matplotlib.pyplot as plt
import matplotlib.cm as cm
import matplotlib.colors
from matplotlib.ticker import LogFormatter 

#================================#
[docs]def readTopography(fileTopo,path='./',iskip=10,control=False,plot=False): """ Read topography data from geodyn5 file Parameters ---------- fileTopo : str Full name of input file (topography in geodyn5 format) path : str Path to input file, default: ./ iskip : int Read in only iskip line, default: 10 control : bool Control output, default: None plot : bool plot map, default: None Returns ------- easting : 1D numpy array List of easting coordinates [m] northing : 1D numpy array List of northing coordinates [m] elevation : 1D numpy array List of elevations [m] Notes ----- Raises ------ ValueError if path/fileTopo does not exist, aborts """ import numpy as np import os.path, sys # check, if path+fileTopo exists if (os.path.isfile(path+fileTopo)==False): print ('File ',path+fileTopo,' does not exist, aborted') sys.exit() else: # read all lines from geodyn5 elevation file f = open(path+fileTopo,'r') topolines = f.readlines() f.close() # create data fields (datetime, easting, northing, elevation) imeta=0; itopodata=0; i=0 datetime =[] easting = np.empty(0) northing = np.empty(0) elevation = np.empty(0) # go through lines, separate meta-data from data, fill fields, skip every iskip lines for line in topolines: # Get next line from file if (line[0] == '!'): imeta += 1 #print(line.split()) else: i += 1 if (i%iskip == 0): itopodata += 1 easting = np.append(easting,[float(line.split()[1])],axis=0) northing = np.append(northing,[float(line.split()[2])],axis=0) elevation = np.append(elevation,[float(line.split()[3])],axis=0) datetime.append(line.split()[0]) # control output if (control): print('File read: ',path+fileTopo) print('Number of topo lines: ',len(topolines)) print('Number of meta-data read: ',imeta) print('Number of topo data read: ',itopodata) print('min/max easting: ',easting.min(),easting.max()) print('min/max northing: ',northing.min(),northing.max()) print('min/max elevation: ',elevation.min(),elevation.max()) # plot topography if (plot): plt.figure(figsize=(10,10)) ax = plt.axes(aspect='equal') plt.title('Topography: '+fileTopo) # draw ticks and labels ax.set_xlim([easting.min(),easting.max()]) ax.set_ylim([northing.min(),northing.max()]) ax.set_xlabel('Easting [m]') ax.set_ylabel('Northing [m]') ax.ticklabel_format(useOffset=False) # topography as image vmin=elevation.min();vmax=elevation.max() bounds = np.linspace(vmin,vmax,20) cbar1=ax.tricontourf(easting,northing,elevation,cmap='terrain',vmin=vmin,vmax=vmax,levels=bounds) plt.colorbar(cbar1,label='Elevation [m]',shrink=0.6) # topo contours cbar2=ax.tricontour(easting,northing,elevation,levels=bounds,colors='black',linewidths=1,alpha=0.3) ax.clabel(cbar2,colors='black',inline=True,fmt='{:.0f}'.format) return easting,northing,elevation
#================================#
[docs]def readBouguerAnomaly(fileGrav,path='./',iskip=1,control=False,plot=False): """ Read Bouguer anomaly data from geodyn5 file Parameters ---------- fileGrav : str Full name of input file (in geodyn5 format) path : str Path to input file, default: ./ iskip : int Read in only iskip line, default: 10 control : bool Control output, default: None plot : bool plot map, default: None Returns ------- easting : 1D numpy array List of easting coordinates [m] northing : 1D numpy array List of northing coordinates [m] topo : 1D numpy array List of elevations [m] boug : 1D numpy array List of elevations [m] Notes ----- Raises ------ ValueError if path/fileGrav does not exist, aborts """ import numpy as np import os.path, sys # check, if path+fileTopo exists if (os.path.isfile(path+fileGrav)==False): print ('File ',path+fileGrav,' does not exist, aborted') sys.exit() else: # read all lines from geodyn5 elevation file f = open(path+fileGrav,'r') topolines = f.readlines() f.close() # create data fields (datetime, easting, northing, elevation) imeta=0; itopodata=0; i=0 datetime =[] easting = np.empty(0) northing = np.empty(0) topo = np.empty(0) boug = np.empty(0) # go through lines, separate meta-data from data, fill fields, skip every iskip lines for line in topolines: # Get next line from file if (line[0] == '!'): imeta += 1 #print(line.split()) else: i += 1 if (i%iskip == 0): itopodata += 1 easting = np.append(easting,[float(line.split()[1])],axis=0) northing = np.append(northing,[float(line.split()[2])],axis=0) topo = np.append(topo,[float(line.split()[3])],axis=0) boug = np.append(boug,[float(line.split()[5])],axis=0) datetime.append(line.split()[0]) # control output if (control): print('File read: ',path+fileGrav) print('Number of topo lines: ',len(topolines)) print('Number of meta-data read: ',imeta) print('Number of topo data read: ',itopodata) print('min/max easting: ',easting.min(),easting.max()) print('min/max northing: ',northing.min(),northing.max()) print('min/max elevation: ',topo.min(),topo.max()) print('min/max Bouguer anomaly: ',boug.min(),boug.max()) # plot Bouguer anomaly if (plot): plt.figure(figsize=(10,10)) ax = plt.axes(aspect='equal') plt.title('Bouguer anomaly: '+fileGrav) # draw ticks and labels ax.set_xlim([easting.min(),easting.max()]) ax.set_ylim([northing.min(),northing.max()]) ax.set_xlabel('Easting [m]') ax.set_ylabel('Northing [m]') ax.ticklabel_format(useOffset=False) # topography as image vmin=boug.min();vmax=boug.max() bounds = np.linspace(vmin,vmax,20) cbar1=ax.tricontourf(easting,northing,boug,cmap='seismic',vmin=vmin,vmax=vmax,levels=bounds) plt.colorbar(cbar1,label='Bouguer anomaly [mGal]',shrink=0.6) # topo contours cbar2=ax.tricontour(easting,northing,boug,levels=bounds,colors='black',linewidths=1,alpha=0.3) ax.clabel(cbar2,colors='black',inline=True,fmt='{:.0f}'.format) return easting,northing,topo,boug
#================================#
[docs]def readTotalField(fileMAG,path='./',iskip=1,control=False,plot=False): """ Read Total-field anomaly data from geodyn5 file Parameters ---------- fileMAG : str Full name of input file (in geodyn5 format) path : str Path to input file, default: ./ iskip : int Read in only iskip line, default: 10 control : bool Control output, default: None plot : bool plot map, default: None Returns ------- easting : 1D numpy array List of easting coordinates [m] northing : 1D numpy array List of northing coordinates [m] topo : 1D numpy array List of elevations [m] total : 1D numpy array List of total-field values [m] Notes ----- Raises ------ ValueError if path/fileMAG does not exist, aborts """ import numpy as np import os.path, sys # check, if path+fileMAG exists if (os.path.isfile(path+fileMAG)==False): print ('File ',path+fileMAG,' does not exist, aborted') sys.exit() else: # read all lines from geodyn5 elevation file f = open(path+fileMAG,'r') topolines = f.readlines() f.close() # create data fields (datetime, easting, northing, topo, total) imeta=0; itopodata=0; i=0 datetime =[] easting = np.empty(0) northing = np.empty(0) topo = np.empty(0) total = np.empty(0) # go through lines, separate meta-data from data, fill fields, skip every iskip lines for line in topolines: # Get next line from file if (line[0] == '!'): imeta += 1 #print(line.split()) else: i += 1 if (i%iskip == 0): itopodata += 1 easting = np.append(easting,[float(line.split()[1])],axis=0) northing = np.append(northing,[float(line.split()[2])],axis=0) topo = np.append(topo,[float(line.split()[3])],axis=0) total = np.append(total,[float(line.split()[5])],axis=0) datetime.append(line.split()[0]) # control output if (control): print('File read: ',path+fileMAG) print('Number of topo lines: ',len(topolines)) print('Number of meta-data read: ',imeta) print('Number of topo data read: ',itopodata) print('min/max easting: ',easting.min(),easting.max()) print('min/max northing: ',northing.min(),northing.max()) print('min/max elevation: ',topo.min(),topo.max()) print('min/max Total field: ',total.min(),total.max()) # plot Bouguer anomaly if (plot): plt.figure(figsize=(10,10)) ax = plt.axes(aspect='equal') plt.title('Total-field anomaly: '+fileMAG) # draw ticks and labels ax.set_xlim([easting.min(),easting.max()]) ax.set_ylim([northing.min(),northing.max()]) ax.set_xlabel('Easting [m]') ax.set_ylabel('Northing [m]') ax.ticklabel_format(useOffset=False) # topography as image vmin=total.min();vmax=total.max() bounds = np.linspace(vmin,vmax,20) cbar1=ax.tricontourf(easting,northing,total,cmap='seismic',vmin=vmin,vmax=vmax,levels=bounds) plt.colorbar(cbar1,label='Total-field anomaly [nT]',shrink=0.6) # topo contours cbar2=ax.tricontour(easting,northing,total,levels=bounds,colors='black',linewidths=1,alpha=0.3) ax.clabel(cbar2,colors='black',inline=True,fmt='{:.0f}'.format) return easting,northing,topo,total
#================================#
[docs]def readERTprofile(fileERT,path='./',control=False,plot=False): """ Read ERT data data from geodyn5 file Parameters ---------- fileERT : str Full name of input file (in geodyn5 format) path : str Path to input file, default: ./ control : bool Control output, default: None plot : bool plot map, default: None Returns ------- ert : 2D numpy array List of easting, northing, elevation, offset [m], rho [Ohmm], profile [m] points : 2D numpy array List of profile, offset [m] tri : object trianulation object Notes ----- Raises ------ ValueError if path/fileERT does not exist, aborts """ import numpy as np import os.path, sys # check, if path+fileMAG exists if (os.path.isfile(path+fileERT)==False): print ('File ',path+fileERT,' does not exist, aborted') sys.exit() else: # read all lines from geodyn5 file f = open(path+fileERT, 'r') ertlines = f.readlines() f.close() # create ert data fields (easting, northing, elev/boug) imeta=0; iertdata=0 datetime =[] ert = np.empty((0,6)) # go through lines, separate meta-data from data, fill fields for line in ertlines: # Get next line from file if (line[0] == '!'): imeta += 1 #print(line.split()) else: iertdata += 1 add = np.array([[float(line.split()[1]), float(line.split()[2]), float(line.split()[3]), float(line.split()[4]), float(line.split()[5]), float(line.split()[6])]]) ert = np.append(ert,add,axis=0) datetime.append(line.split()[0]) # control output if (control): print('Number of meta-data lines: ',imeta) print('Number of ert lines: ',iertdata) print('min/max elevation: ',ert[:,2].min(),ert[:,2].max()) print('min/max offset: ',ert[:,3].min(),ert[:,3].max()) print('min/max resistivity: ',ert[:,4].min(),ert[:,4].max()) print('min/max profile: ',ert[:,5].min(),ert[:,5].max()) # triangulation points points = np.zeros(ert.shape[0]*2).reshape(ert.shape[0],2) for i in range(ert.shape[0]): points[i][0] = ert[i,5] points[i][1] = ert[i,3] # Delaunay triangulation tri = scipy.spatial.Delaunay(points) # plot profile if (plot): fig,ax1 = plt.subplots(1,1,figsize=(12.0, 4.0)) ax1.set_xlabel('Profile distance [m]') ax1.set_ylabel('Elevation [m]') ax1.set_title('ERT profile: '+fileERT) ax1.set_xlim([ert[:,5].min(),ert[:,5].max()]) ax1.set_ylim([ert[:,2].min()+ert[:,3].min(),ert[:,2].max()]) sorted = np.argsort(ert[:,5]) ax1.plot(ert[sorted,5],ert[sorted,2],linewidth=4,color='black') contour1=plt.tricontour(points[:,0], points[:,1]+ert[:,2], tri.simplices,ert[:,4], levels=[10,20,50,100,200,500,1000,2000,3000,5000], colors='black',alpha=0.5,linewidths=1) ax1.clabel(contour1,colors='black',inline=True,fmt='{:.0f}'.format) im1 = plt.tripcolor(points[:,0], points[:,1]+ert[:,2], tri.simplices,ert[:,4], shading='gouraud', cmap = plt.get_cmap('rainbow'),norm=matplotlib.colors.LogNorm(vmin=ert[:,4].min(),vmax=ert[:,4].max())) formatter = LogFormatter(10, labelOnlyBase=False,minor_thresholds=(3,2)) cbar1=fig.colorbar(im1,ax=ax1,shrink=0.9,ticks=[10,20,50,100,200,500,1000,5000],format=formatter) cbar1.set_label('Specific resistivity [\u03A9'+'m]', rotation=90) return ert,points,tri
#================================#
[docs]def readGPRprofile(fileGPR,path='./',iskip=1,control=False,plot=False,reversed=False,scale=5e5,xoffset=0.): """ Read GPR data data from geodyn5 file Parameters ---------- fileGPR : str Full name of input file (in geodyn5 format) path : str Path to input file, default: ./ iskip : int Read in only iskip line, default: 1 control : bool Control output, default: None plot : bool plot map, default: None reversed : bool reverse xprofile direction, default: no scale : float scale reflection amplitude, default: 5e5 xoffset : float offset for profile, default: 0 m Returns ------- gpr : 2D numpy array List of easting, northing, elevation, offset [m], amplitude [-], profile [m] points : 2D numpy array List of profile, offset [m] tri : object trianulation object total : 1D numpy array List of total-field values [m] Notes ----- Raises ------ ValueError if path/fileGPR does not exist, aborts """ import numpy as np import os.path, sys # check, if path+fileMAG exists if (os.path.isfile(path+fileGPR)==False): print ('File ',path+fileGPR,' does not exist, aborted') sys.exit() else: # read all lines from geodyn5 file f = open(path+fileGPR, 'r') ertlines = f.readlines() f.close() # create ert data fields (easting, northing, elev/boug) imeta=0; igprdata=0; i=0 datetime =[] gpr = np.empty((0,6)) # go through lines, separate meta-data from data, fill fields for line in ertlines: # Get next line from file if (line[0] == '!'): imeta += 1 #print(line.split()) else: i += 1 if (i%iskip == 0): igprdata += 1 add = np.array([[float(line.split()[1]), float(line.split()[2]), float(line.split()[3]), float(line.split()[4]), float(line.split()[5]), float(line.split()[6])+xoffset]]) gpr = np.append(gpr,add,axis=0) datetime.append(line.split()[0]) # control output if (control): print('Number of meta-data lines: ',imeta) print('Number of gpr lines: ',igprdata) print('min/max elevation: ',gpr[:,2].min(),gpr[:,2].max()) print('min/max offset: ',gpr[:,3].min(),gpr[:,3].max()) print('min/max amplitude: ',gpr[:,4].min(),gpr[:,4].max()) print('min/max amplitude scaled: ',gpr[:,4].min()/scale,gpr[:,4].max()/scale) print('min/max profile: ',gpr[:,5].min(),gpr[:,5].max()) # triangulation points points = np.zeros(gpr.shape[0]*2).reshape(gpr.shape[0],2) for i in range(gpr.shape[0]): points[i][0] = gpr[i,5] points[i][1] = gpr[i,3] # Delaunay triangulation tri = scipy.spatial.Delaunay(points) # plot profile if (plot): fig,ax1 = plt.subplots(1,1,figsize=(12.0, 4.0)) ax1.set_xlabel('Profile distance [m]') ax1.set_ylabel('Elevation [m]') ax1.set_title('GPR profile: '+fileGPR) if (reversed): ax1.set_xlim([gpr[:,5].max(),gpr[:,5].min()]) else: ax1.set_xlim([gpr[:,5].min(),gpr[:,5].max()]) ax1.set_ylim([gpr[:,2].min()+gpr[:,3].min(),gpr[:,2].max()]) sorted = np.argsort(gpr[:,5]) ax1.plot(gpr[sorted,5],gpr[sorted,2],linewidth=4,color='black') #contour1=plt.tricontour(points[:,0], points[:,1]+gpr[:,2], tri.simplices,gpr[:,4], # levels=[10,20,50,100,200,500,1000,2000], # colors='black',alpha=0.5,linewidths=1) #ax1.clabel(contour1,colors='black',inline=True,fmt='{:.0f}'.format) im1 = plt.tripcolor(points[:,0], points[:,1]+gpr[:,2], tri.simplices,gpr[:,4]/scale, shading='gouraud', cmap = plt.get_cmap('seismic'),vmin=-10,vmax=10) cbar1=fig.colorbar(im1,ax=ax1,shrink=0.9,ticks=[-10,10]) cbar1.set_label('Reflectivity [-]', rotation=90) return gpr,points,tri
#================================#
[docs]def createERTCoordElevation(nameERT,nElectrodes,sElectrodes,GPSPoints,easting,northing,elevation,path='./',control=False,plot=False): """ Read GPS coordinates taken along ERT profile, create coordinates for every electrode position and interpolate elevation for electrode from topo data Parameters ---------- nameERT : str name of ERT profile nElectrodes : int number of electrodes along profile sElectrodes : int electrode spacing [m] GPSPoints : 2D float array List of GPS points easting,northing) along profile easting : 1D float array List of easting coordinates [m] (from readTopography.py) northing : 1D float array List of northing coordinates [m] (from readTopography.py) elevation : 1D float array List of elevations [m] (from readTopography.py) control : bool Control output, default: None plot : bool plot simple map, default: None Returns ------- elecPoints : 2D float array List of coordinates, elevations, and distances for profile electrodes [m] elecPoints[:,0] - easting [m] elecPoints[:,1] - northing [m] elecPoints[:,2] - elevation [m] elecPoints[:,3] - distance [m] Notes ----- Sample parameter values for 25 electrodes, 3m spacing, and two GPS points: nElectrodes = 25 sElectrodes = 3 GPSPoints = np.array([ [605503.44,5714171.93], [605450.70,5714227.35] ]) """ import numpy as np import scipy.interpolate import os.path, sys print('nameERT: ',nameERT) print('nElectrodes: ',nElectrodes) print('sElectrodes: ',sElectrodes) lProfile = (nElectrodes-1)*sElectrodes print('Profile length: ',lProfile,' m') # calculate linear distance between GPS points GPSDistance = np.zeros(GPSPoints.shape[0]) print('GPS points: ',GPSPoints.shape[0]) GPSDistance = np.zeros(GPSPoints.shape[0]) for i in range(1,GPSDistance.shape[0]): GPSDistance[i] = GPSDistance[i-1] + np.sqrt((GPSPoints[i-1][0]-GPSPoints[i][0])**2 + (GPSPoints[i-1][1]-GPSPoints[i][1])**2) print('GPSDistance: ',GPSDistance[-1]) # if last GPSPoints point results in shorter GPSDistance < lProfile # then extrapolate last GPSPoints if (lProfile > GPSDistance[-1]): dx = GPSPoints[-1,0] - GPSPoints[-2,0] dy = GPSPoints[-1,1] - GPSPoints[-2,1] radius = np.sqrt(dx**2 + dy**2) alpha = np.arctan2(dy,dx) radius += (lProfile-GPSDistance[-1]) GPSPoints[-1,0] = GPSPoints[-2,0] + radius * np.cos(alpha) GPSPoints[-1,1] = GPSPoints[-2,1] + radius * np.sin(alpha) print('extrapolate last point') print(GPSPoints) for i in range(1,GPSDistance.shape[0]): GPSDistance[i] = GPSDistance[i-1] + np.sqrt((GPSPoints[i-1][0]-GPSPoints[i][0])**2 + (GPSPoints[i-1][1]-GPSPoints[i][1])**2) print('GPSDistance: ',GPSDistance[-1]) #sys.exit('') # calculate electrode distance and positions elecPoints = np.zeros([nElectrodes,4]) for i in range(nElectrodes): elecPoints[i,3] = GPSDistance[0] + i*sElectrodes elecPoints[i,0] = np.interp(elecPoints[i,3], GPSDistance,GPSPoints[:,0]) elecPoints[i,1] = np.interp(elecPoints[i,3], GPSDistance,GPSPoints[:,1]) # calculate electrode elevations from interpolation elecPoints[:,2] = scipy.interpolate.griddata(np.c_[easting,northing], elevation, (elecPoints[:,0], elecPoints[:,1]), method='linear') if (control): for i in range(nElectrodes): print("%4i %12.8f %12.8f %8.2f %8.2f" % (i,elecPoints[i,0],elecPoints[i,1],elecPoints[i,2],elecPoints[i,3])) # save coordinates, distance, elevation to profile file f = open(path+nameERT+'.profile','w') for i in range(nElectrodes): print("%12.8f %12.8f %8.2f %8.2f" % (elecPoints[i,0],elecPoints[i,1],elecPoints[i,3],elecPoints[i,2]),file=f) f.close() print('nameERT: ',nameERT) print('File written: ',path+nameERT+'.profile') # plot profile if (plot): fig,axs = plt.subplots(1,2,figsize=(10,5),constrained_layout=True) # plot map view for profile axs[0].set_title('ERT profile: '+nameERT) axs[0].set_aspect('equal') axs[0].set_xlim([elecPoints[:,0].min()-100,elecPoints[:,0].max()+100]) axs[0].set_ylim([elecPoints[:,1].min()-100,elecPoints[:,1].max()+100]) axs[0].set_xlabel('Easting [m]') axs[0].set_ylabel('Northing [m]') axs[0].tricontourf(easting,northing,elevation) axs[0].plot(elecPoints[:,0],elecPoints[:,1],lw=2,marker='o',markersize=3,color='blue') axs[0].plot(GPSPoints[:,0],GPSPoints[:,1],lw=0,marker='x',markersize=7,color='red') # plot elevation of profile axs[1].set_xlim([0,lProfile]) axs[1].set_ylim([elecPoints[:,2].min(),elecPoints[:,2].max()]) axs[1].set_xlabel('Profile [m]') axs[1].set_ylabel('Elevation [m]') axs[1].plot(elecPoints[:,3],elecPoints[:,2],lw=2,marker='o',markersize=3,color='blue') return elecPoints
#================================#
[docs]def createGPRCoordElevation(nameGPR,lProfile,sProfile,GPSPoints,easting,northing,elevation,traceInc=0,path='./',control=False,plot=False): """ Read GPS coordinates taken along GPR profile, create coordinates for every nth trace icrement and interpolate elevation for traces from topo data Parameters ---------- nameGPR : str name of GPR profile lProfile : float length of GPR profile [m] sProfile : float spacing distance for profile [m] GPSPoints : 2D float array List of GPS points easting,northing) along profile easting : 1D float array List of easting coordinates [m] (from readTopography.py) northing : 1D float array List of northing coordinates [m] (from readTopography.py) elevation : 1D float array List of elevations [m] (from readTopography.py) traceInc : float trace increment (from GPS recording) control : bool Control output, default: None plot : bool plot simple map, default: None Returns ------- gprPoints : 2D float array List of coordinates, elevations, and distances for profile electrodes [m] gprPoints[:,0] - easting [m] gprPoints[:,1] - northing [m] gprPoints[:,2] - elevation [m] gprPoints[:,3] - distance [m] Notes ----- Sample parameter values for 100m long GPR profile, sample every 1m, trace increment 0.01, and two GPS points: lProfile = 100. sProfile = 1. traceInc = 0.01 GPSPoints = np.array([ [605503.44,5714171.93], [605450.70,5714227.35] ]) """ import numpy as np import scipy.interpolate import os.path, sys if (traceInc==0): print('Trace increment not set') sys.exit() nTraces = int(lProfile/sProfile) print('nameGPR: ',nameGPR) print('lProfile: ',lProfile) print('sProfile: ',sProfile) print('nTraces: ',nTraces) print('traceInc: ',traceInc) # calculate linear distance between GPS points print('GPS points: ',GPSPoints.shape[0]) GPSDistance = np.zeros(GPSPoints.shape[0]) for i in range(1,GPSDistance.shape[0]): GPSDistance[i] = GPSDistance[i-1] + np.sqrt((GPSPoints[i-1][0]-GPSPoints[i][0])**2 + (GPSPoints[i-1][1]-GPSPoints[i][1])**2) print('GPSDistance: ',GPSDistance[-1]) # if last GPSPoints point results in shorter GPSDistance < lProfile # then extrapolate last GPSPoints if (lProfile > GPSDistance[-1]): dx = GPSPoints[-1,0] - GPSPoints[-2,0] dy = GPSPoints[-1,1] - GPSPoints[-2,1] radius = np.sqrt(dx**2 + dy**2) alpha = np.arctan2(dy,dx) radius += (lProfile-GPSDistance[-1]) GPSPoints[-1,0] = GPSPoints[-2,0] + radius * np.cos(alpha) GPSPoints[-1,1] = GPSPoints[-2,1] + radius * np.sin(alpha) print('extrapolate last point') print(GPSPoints) for i in range(1,GPSDistance.shape[0]): GPSDistance[i] = GPSDistance[i-1] + np.sqrt((GPSPoints[i-1][0]-GPSPoints[i][0])**2 + (GPSPoints[i-1][1]-GPSPoints[i][1])**2) print('GPSDistance: ',GPSDistance[-1]) #sys.exit('') # calculate electrode distance and positions gprPoints = np.zeros([nTraces,4]) for i in range(nTraces): gprPoints[i,3] = GPSDistance[0] + i*sProfile gprPoints[i,0] = np.interp(gprPoints[i,3], GPSDistance,GPSPoints[:,0]) gprPoints[i,1] = np.interp(gprPoints[i,3], GPSDistance,GPSPoints[:,1]) # calculate electrode elevations from interpolation gprPoints[:,2] = scipy.interpolate.griddata(np.c_[easting,northing], elevation, (gprPoints[:,0], gprPoints[:,1]), method='linear') if (control): for i in range(nTraces): print("%4i %12.8f %12.8f %8.2f %8.2f" % (i,gprPoints[i,0],gprPoints[i,1],gprPoints[i,2],gprPoints[i,3])) # save coordinates, distance, elevation to profile file f = open(path+nameGPR+'.utm','w') for i in range(nTraces): print("%10i %12.8f %12.8f %8.2f" % (1+int(gprPoints[i,3]/traceInc),gprPoints[i,1],gprPoints[i,0],gprPoints[i,2]),file=f) f.close() print('nameGPR: ',nameGPR) print('File written: ',path+nameGPR+'.utm') # plot profile if (plot): fig,axs = plt.subplots(1,2,figsize=(10,5),constrained_layout=True) # plot map view for profile axs[0].set_title('GPR profile: '+nameGPR) axs[0].set_aspect('equal') axs[0].set_xlim([gprPoints[:,0].min()-100,gprPoints[:,0].max()+100]) axs[0].set_ylim([gprPoints[:,1].min()-100,gprPoints[:,1].max()+100]) axs[0].set_xlabel('Easting [m]') axs[0].set_ylabel('Northing [m]') axs[0].tricontourf(easting,northing,elevation) axs[0].plot(gprPoints[:,0],gprPoints[:,1],lw=2,marker='o',markersize=3,color='blue') axs[0].plot(GPSPoints[:,0],GPSPoints[:,1],lw=0,marker='x',markersize=7,color='red') # plot elevation of profile axs[1].set_xlim([0,lProfile]) axs[1].set_ylim([gprPoints[:,2].min(),gprPoints[:,2].max()]) axs[1].set_xlabel('Profile [m]') axs[1].set_ylabel('Elevation [m]') axs[1].plot(gprPoints[:,3],gprPoints[:,2],lw=2,marker='o',markersize=3,color='blue') return gprPoints
#================================#
[docs]def createGravityCoordElevation(fileGrav,path='./',irepeat=1,control=False,plot=False): """ Read coordinates of gravity stations along with leveling data Parameters ---------- fileGrav : str Full name of input file (gravity coord file) path : str Path to input file, default: ./ irepeat : int Repeat cooordinate irepeat times, default: 1 control : bool Control output, default: None plot : bool plot map, default: None Returns ------- easting : 1D numpy array List of easting coordinates [m] northing : 1D numpy array List of northing coordinates [m] elevation : 1D numpy array List of elevations [m] Notes ----- sample input file. INFO lines not needed BASE line needed, holds reference elevation DATA line(s) needed, holds point coordinates, for target point ('to') and back- and forward view from leveling ~~~~~~~~~~~~~~~ INFO Base point with absolute coordinates BASE G01 none 51.155896000564098 10.03715998493135 300 INFO Points levelled DATA G01 Z01 51.155896000564098 10.03715998493135 13.2 4.5 DATA Z01 G02 51.155896000564098 10.03715998493135 30.6 24.4 ~~~~~~~~~~~~~~~ Raises ------ ValueError if path+fileGrav does not exist, aborts """ import numpy as np import os.path, sys # check, if path+fileGrav exists if (os.path.isfile(path+fileGrav)==False): print ('File ',path+fileGrav,' does not exist, aborted') sys.exit() else: # read file content into object file_grav = open(path+fileGrav,'r') # convert object into a list containing all lines lines = file_grav.readlines() file_grav.close() print('File read: ',path+fileGrav) lon = np.empty(0) lat = np.empty(0) topo = np.empty(0) # go through the list line by line ibase = 0; idata=0 coords = dict(dict()); add = dict(); for line in lines: if (line[0:4] == 'BASE'): ibase += 1 splitted = line.split() add = dict(); add['from'] = splitted[1] add['to'] = splitted[2] add['lat'] = splitted[3] add['lon'] = splitted[4] add['elev'] = splitted[5] coords[splitted[1]] = add elif (line[0:4] == 'DATA'): idata += 1 splitted = line.split() add = dict(); add['from'] = splitted[1] add['to'] = splitted[2] add['lat'] = splitted[3] add['lon'] = splitted[4] add['elev'] = -99999 add['backward'] = splitted[5] add['forward'] = splitted[6] coords[splitted[2]] = add print('BASE lines: ',ibase) print('Data lines: ',idata) # calculate elevation difference form leveling data and save coordinates to file if (ibase == 0): print ('No base point defined, aborted') else: outfile = path+fileGrav.split('.')[0]+'.xyz' f = open(outfile, 'w') icoord = 0 for key in coords: if (icoord == 0): if (control): print("%10s %14.10f %14.10f %8.2f %5s" % (coords[key]['from'],float(coords[key]['lon']),float(coords[key]['lat']),float(coords[key]['elev']),'fixed')) else: if coords[key]['from'] in coords: diff = float(coords[key]['backward']) - float(coords[key]['forward']) elev = float(coords[coords[key]['from']]['elev']) + 0.1*diff coords[key]['elev'] = elev lon = np.append(lon,[float(coords[key]['lon'])],axis=0) lat = np.append(lat,[float(coords[key]['lat'])],axis=0) topo = np.append(topo,[float(coords[key]['elev'])],axis=0) if (control): print("%10s %14.10f %14.10f %8.2f" % (coords[key]['to'],float(coords[key]['lon']),float(coords[key]['lat']),float(coords[key]['elev']))) for i in range(irepeat): print("%14.10f %14.10f %8.2f" % (float(coords[key]['lon']),float(coords[key]['lat']),float(coords[key]['elev'])),file=f) else: print('Wrong network connection!'+coords[key]['from']+coords[key]['to']);break icoord += 1 print('File written: ',outfile) # plot topography if (plot): plt.figure(figsize=(10,10)) ax = plt.axes(aspect='equal') plt.title('Leveling: '+fileGrav) # draw ticks and labels ax.set_xlim([lon.min(),lon.max()]) ax.set_ylim([lat.min(),lat.max()]) ax.set_xlabel('Longitude [$^{\circ}$]') ax.set_ylabel('Latitude [$^{\circ}$]') ax.ticklabel_format(useOffset=False) # topography as image vmin=topo.min();vmax=topo.max() bounds = np.linspace(vmin,vmax,20) cbar1=ax.tricontourf(lon,lat,topo,cmap='terrain',vmin=vmin,vmax=vmax,levels=bounds) plt.colorbar(cbar1,label='Elevation [m]',shrink=0.6) # topo contours cbar2=ax.tricontour(lon,lat,topo,levels=bounds,colors='black',linewidths=1,alpha=0.3) ax.clabel(cbar2,colors='black',inline=True,fmt='{:.0f}'.format) # gravity stations ax.plot(lon,lat,lw=0,marker='o',markersize=4,color='red',alpha=0.4) return
#================================#
[docs]def addERTCoordElevation(fileERT,elecPoints,path='./',control=False): """ Add profile length and elevation along ERT profile to Res2DInv file Parameters ---------- fileERT : str file name of ERT profile in Res2DInv format elecPoints : 2D float array List of coordinates, elevations, and distances for profile electrodes [m] elecPoints[:,0] - easting [m] elecPoints[:,1] - northing [m] elecPoints[:,2] - elevation [m] elecPoints[:,3] - distance [m] path : str Path to input file, default: ./ control : bool Control output, default: None Returns ------- -none- Notes ----- Read the ERT file in Res2DInv format and replaces last section with elevation data """ import numpy as np import os.path, sys # check, if path+fileERT exists if (os.path.isfile(path+fileERT)==False): print ('File ',path+fileERT,' does not exist, aborted') sys.exit() else: # read file content into lines object f = open(path+fileERT, 'r') # convert object into a list containing all lines lines = f.readlines() f.close() print('File read: ',path+fileERT) # get 6 header lines, extract electrode spacing, type of ERT profile, number of measurements sElectrodes = float(lines[1]) typeERT = int(lines[2]) nMeasurements = int(lines[3]) if (control): print('Electode spacing: ',sElectrodes) print('type of ERT measurments: ',typeERT) print('Number of measurements: ',nMeasurements) # save measurements to array ERTData = np.zeros([nMeasurements,4]) for i in range(nMeasurements): ERTData[i,0] = lines[6+i].replace(',','').split()[0] ERTData[i,1] = lines[6+i].replace(',','').split()[1] ERTData[i,2] = lines[6+i].replace(',','').split()[2] ERTData[i,3] = lines[6+i].replace(',','').split()[3] if (control): print(ERTData) # check if topography is already present itopo = int(lines[nMeasurements+6]) if (itopo != 0): print('Topography data already present in '+path+fileERT) #sys.exit() else: # replace last section with elevation data f = open(path+fileERT.split('.')[0]+'_mod.dat', 'w') for i in range(nMeasurements+6): print(lines[i].replace(',',''),end="",file=f) print(2,file=f) print(elecPoints.shape[0],file=f) for i in range(elecPoints.shape[0]): print(elecPoints[i,3],elecPoints[i,2],file=f) print(0,file=f) print('File written: ',path+fileERT.split('.')[0]+'_mod.dat') return
#================================#