Swath profiles using grdtrack

Currently I am searching for a convenient approach to generate topographic swath profiles solely be applying GMT tools. In the past I computed swath profiles via home brewed codes and plotted the results with GMT. This was fine as long as the profile just followed a straight line.

However, now I need a profile consisting of several segements and before I start extending my buggy code, I’m just wondering if GMT offers a solution out of the box. I found a similar request but not a working solution at the forum. I’m just wondering if the deluxe solution of grdtrack already exists: https://flint.soest.hawaii.edu/t/grdtrack-vertical-profile-along-track/1547

  1. For my approach I would require: max, min, mean, 1 std (median, 25% and 75% Percentiles) of the cross profiles next to the distance, lat, lon of the original profile line. By reading the grdtrack manual I understand that I could first produce the cross profiles and compute the statistics in a second step. However, it would make me quite happy if I could avoid generating thousands of temporary files.

  2. I was thinking to compute min, max, mean, … values along a profile line within a circular sliding window of a given radius. By reading the grdtrack manual I found that -E in combination with +r might be a solution but I’m not sure how to use it and how to pass a long list of coordinates to -E.
    Currently, I just can think of a brute force method but computing spatial statistics (min, max,…) for the entire grid via grdfilter and using grdtrack to extract the desired values along the profile line. Anyhow, I’m quite sure that there are more elegant solutions for such a task.

Any hints are highly appreciated!

Thank you in advance
JΓΆrg

1 Like

Hi! I am also working on the similar thing with you recently, about Swath Profile. However, it is so sorry that I have not found the specialized commands to compute and plot swath profiles in GMT yet. I do not know whether you have found some solution. Anyway, now I have a indirect way to it. If it is still helpful for you, you can see the following. (I am so sorry my strategy is a little complex and long … :rofl:)

Okay, I choose to create swath profile based on the function stacking (-S option) of multiple cross-profiles (-C option) in GMT command grdtrack.

Next let me introduce my method to you. I recommend you glance through the output figure in the last part when you read my bash script. And I have written the necessary interpretation in this bash script, for clarity, as following. Also, the following blod font represents the variable using in the bash script or the important element in the method (shown in the figure).

Input files:

  1. relief_TibetanPlateau_forplot.nc, a example topography file.
  2. mychem.txt, a data file including data which are expected to project to the same swath profile, with the format of lon, lat, value:
    95 32 5000

#!/bin/bash

figure=β€œswath”
gmt begin ${figure}

##Topography Map
grdfile=β€œrelief_TibetanPlateau_forplot.nc”

intensfile=${figure}β€œ_topo.int”
gmt grdgradient ${grdfile} -G${intensfile} -A45/0
gmt grdimage ${grdfile} -JM20/10 -BWeSn+t"Map View" -Bpxa4f1 -Bpya2f1 -Csrtm -I${intensfile} --FORMAT_GEO_MAP=ddd

##Define swath profile
#Here you should select your desired survey line, with start point and end point or start point and azimuth clockwise from north and length of survey lines, as the central thick black line shown in the figure. However, (1). This line cannot accurately be the real survey line for swath profile, and the nearby thick red line will be the real survey line used to project topography and data. That may be because of the existence of grid spacing of DEM data and spherical earth. For example, I define a line with GMT, then I compute its orthogonal line. However, if I compute cross profile which is orthogonal to its orthogonal line using grdtrack, they can not be consistent with the original line. As you see, the thick red line can not consistent with the black line. (2) Whether you define survey line with start point and end point or start point, azimuth and length, both of selection need to compute the azimuth and length (using mapproject) because we will need those information to decide the position of midpoint using project.

orilon=92 #deg
orilat=34 #deg
endlon=99 #deg
endlat=30 #deg
#azimuth=120 #deg, clockwise from North!
#length=1000 #km
swathw=200 #km(-/+)

echo ${endlon} ${endlat} | gmt mapproject -Af${orilon}/${orilat} -G${orilon}/${orilat}+uk -je
azimuth=$( echo ${endlon} ${endlat} | gmt mapproject -Af${orilon}/${orilat} -G${orilon}/${orilat}+uk -je | awk β€˜{print $3}’ )
length=$( echo ${endlon} ${endlat} | gmt mapproject -Af${orilon}/${orilat} -G${orilon}/${orilat}+uk -je | awk β€˜{print $4}’ )

#If you define the desired survey line with azimuth and length rather than end point.
#endlon=$( gmt project -C${orilon}/${orilat} -A${azimuth} -G${length} -L0/${length} -Q | tail -1 | awk β€˜{print $1}’ )
#endlat=$( gmt project -C${orilon}/${orilat} -A${azimuth} -G${length} -L0/${length} -Q | tail -1 | awk β€˜{print $2}’ )
gmt plot -W2p,black << EOF
${orilon} ${orilat}
${endlon} ${endlat}
EOF

#We must need to find the position (cenlon,cenlat) of midpoint of the desired survey line, as the central blue circle in the figure.
cendist=$( echo β€œ${length}/2.0” | bc -l )
cenlon=$( gmt project -C${orilon}/${orilat} -A${azimuth} -G${cendist} -L0/${cendist} -Q | tail -1 | awk β€˜{print $1}’ )
cenlat=$( gmt project -C${orilon}/${orilat} -A${azimuth} -G${cendist} -L0/${cendist} -Q | tail -1 | awk β€˜{print $2}’ )
echo ${cenlon} ${cenlat} | gmt plot -Sc0.2 -Gblue

#We find one endpoint (cen1lon,cen1lat) of the orthogonal line, as the blue circle on the border in the figure.
cen1azimuth=$( echo β€œ${azimuth}-90” | bc -l )
cen1lon=$( gmt project -C${cenlon}/${cenlat} -A${cen1azimuth} -G${swathw} -L0/${swathw} -Q | tail -1 | awk β€˜{print $1}’ )
cen1lat=$( gmt project -C${cenlon}/${cenlat} -A${cen1azimuth} -G${swathw} -L0/${swathw} -Q | tail -1 | awk β€˜{print $2}’ )
echo ${cen1lon} ${cen1lat} | gmt plot -Sc0.2 -Gblue

#We find another endpoint (cen2lon,cen2lat) of the orthogonal line, as the blue circle on the other border in the figure.
cen2azimuth=$( echo β€œ${azimuth}+90” | bc -l )
cen2lon=$( gmt project -C${cenlon}/${cenlat} -A${cen2azimuth} -G${swathw} -L0/${swathw} -Q | tail -1 | awk β€˜{print $1}’ )
cen2lat=$( gmt project -C${cenlon}/${cenlat} -A${cen2azimuth} -G${swathw} -L0/${swathw} -Q | tail -1 | awk β€˜{print $2}’ )
echo ${cen2lon} ${cen2lat} | gmt plot -Sc0.2 -Gblue

##track and stack along the cross-profiles of CENTRAL NORMAL LINE
#Here we have find a new line which is formed by connecting the two blue endpoints, orthogonal to our desired survey line. Next we will determine many cross profiles (i.e. the thin lines in the figure) of the new line using -C option and -S option of grdtrack. Unfortunately, there is a so minor angle shift between cross profiles (the thin black line) and our desired survey line (the thick black line). Then the analysis for stacking cross profiles will produce average value, median value, lower value, upper value and others with -S option of grdtrack.

Clength=${length}β€œk”
Csample=β€œ1k” #km
Cspacing=β€œ100k” #km
stackfile=${figure}β€œ_stack.txt”
profilefile=${figure}β€œ_profile.txt”
gmt grdtrack -G${grdfile} -C${Clength}/${Csample}/${Cspacing}+v -Sa+s${stackfile} << EOF > ${profilefile}
${cen1lon} ${cen1lat}
${cen2lon} ${cen2lat}
EOF
awk -v leng=${length} β€˜{print $1+leng/2,$2,$3,$4,$5,$6,$7}’ ${stackfile} > swath.temp
mv swath.temp ${stackfile}
envfile=${figure}β€œ_env.txt”
gmt convert ${stackfile} -o0,5 > ${envfile}
gmt convert ${stackfile} -o0,6 -I -T >> ${envfile}

#Now we have known that the desired survey line (the thick black line) can not be used, and the cross profiles (the thin black line) will be plotted. Here I choose the median cross profile (the central thin black line) from the output file of grdtrack, named stack_profile.txt, which includes the sampling point data for each cross profile. Then the selected cross profile will be the true coordinate system used to plot. So we can find the information about the true line (the central thin black line), such as longitude (newlon) and latitude (newlat) of its midpoint (i.e. the central red circle in the figure) and azimuth (newazimuth). Also, the central cross profile is shown as the central red thick line in the figure, whose data is stored in the file stack_oneProfile.txt. Note: the newazimuth is counterclockwise from South!

onenum=$( grep β€œ>” ${profilefile} | wc -l | awk β€˜{print int($1/2)}’ )
oneProfile=${figure}β€œ_oneProfile.txt”
gmt convert -S"-L0-${onenum}" ${profilefile} > ${oneProfile}
newlon=$( grep β€œ-L0-${onenum}” ${profilefile} | awk β€˜{print $7}’ | awk -F"/" β€˜{print $1}’ )
newlat=$( grep β€œ-L0-${onenum}” ${profilefile} | awk β€˜{print $7}’ | awk -F"/" β€˜{print $2}’ )
newazimuth=$( grep β€œ-L0-${onenum}” ${profilefile} | awk β€˜{print $8}’ | awk -F’=’ β€˜{print $2}’)
#newazimuth is counterclockwise from South!
echo ${newlon} ${newlat} ${newazimuth}
echo ${newlon} ${newlat} | gmt plot -Sc0.1 -Gred

#Also, because we will project some data in the input file mychem.txt to the (swath) profile, here we calculate its two endpoints (i.e. the red circles on the endpoints of the red thick lines in the figure). The two endpoints new1 (new1lon,new1lat) and new2 (new2lon,new2lat) will be used in the following project.

half=$( echo β€œ${length}/2.0” | bc -l )
new1lon=$( gmt project -C${newlon}/${newlat} -A${newazimuth} -L0/${half} -G${half} -Q | tail -1 | awk β€˜{print $1}’)
new1lat=$( gmt project -C${newlon}/${newlat} -A${newazimuth} -L0/${half} -G${half} -Q | tail -1 | awk β€˜{print $2}’)
echo ${new1lon} ${new1lat} | gmt plot -Sc0.1 -Gred
echo ${new1lon} ${new1lat}

new2az=$( echo β€œ180+${newazimuth}” | bc -l )
new2lon=$( gmt project -C${newlon}/${newlat} -A${new2az} -L0/${half} -G${half} -Q | tail -1 | awk β€˜{print $1}’)
new2lat=$( gmt project -C${newlon}/${newlat} -A${new2az} -L0/${half} -G${half} -Q | tail -1 | awk β€˜{print $2}’)
echo ${new2lon} ${new2lat} | gmt plot -Sc0.1 -Gred
echo ${new2lon} ${new2lat}

gmt plot ${profilefile} -W0.5p,black
awk β€˜{print $1,$2}’ ${oneProfile} | gmt plot -W3p,red@50

##Plot Swath Profile
gmt basemap -JX10/5 -R0/${length}/0/8000 -BWSne+t"Swath Profile" -Bpxa100f10 -Bpya1000f100 -Y-8

lowpass=1 #low-pass filtering

gmt plot ${envfile} -Ggray90
awk β€˜{print $1,$2}’ ${stackfile} | gmt plot ${stackfile} -W0.1p,blue

stackUP=${figure}β€œ_stackUP.txt”
gmt grdtrack -G${grdfile} -C${Clength}/${Csample}/${Cspacing}+v -Su+s${stackUP} << EOF > /dev/null
${cen1lon} ${cen1lat}
${cen2lon} ${cen2lat}
EOF
awk -v leng=${length} β€˜{print $1+leng/2,$2,$3,$4,$5,$6,$7}’ ${stackUP} > swath.temp
mv swath.temp ${stackUP}
gmt filter1d -Fg${lowpass} ${stackUP} | gmt plot -W1p,gray70

stackLOW=${figure}β€œ_stackLOW.txt”
gmt grdtrack -G${grdfile} -C${Clength}/${Csample}/${Cspacing}+v -Sl+s${stackLOW} << EOF > /dev/null
${cen1lon} ${cen1lat}
${cen2lon} ${cen2lat}
EOF
awk -v leng=${length} β€˜{print $1+leng/2,$2,$3,$4,$5,$6,$7}’ ${stackLOW} > swath.temp
mv swath.temp ${stackLOW}
gmt filter1d -Fg${lowpass} ${stackLOW} | gmt plot -W1p,gray70

##The Real Track
#Here we project our data in mychem.txt to the true swath profile (the central thin black line or the red thick line), based on the two endpoint new1 (new1lon,new1lat) and new2 (new2lon,new2lat).

awk -v leng=${length} β€˜NR>1 {print $3+leng/2,$5}’ ${oneProfile} | gmt filter1d -Fg${lowpass} | gmt plot -W0.1p,red@30

gmt project -C${new1lon}/${new1lat} -E${new2lon}/${new2lat} -G0.1 -Q | gmt grdtrack -G${grdfile} | awk β€˜{print $3,$4}’ | gmt filter1d -Fg${lowpass} | gmt plot -W0.1p,black

inputchemistry=β€œmychem.txt”
Chemistry=${figure}β€œ_chemistry.txt”
gmt project ${inputchemistry} -C${new1lon}/${new1lat} -E${new2lon}/${new2lat} -Q > ${Chemistry}
awk β€˜{print $4,$3}’ ${Chemistry} | gmt plot -Sd0.2 -Ggreen

gmt end show

Output files in addition to the figure (.pdf) like in the last part:

  1. swath_chemistry.txt: the projected data along the true survey line.
  2. swath_env.txt: the envolve line which is generated from swath_stack.txt
  3. swath_oneProfile.txt: the cross profile as the final projecting profile.
  4. swath_profile.txt: all cross profiles as represented by the black thin lines in the figure.
  5. swath_stackLOW.txt: distance, lower value of stacking cross profiles (swath profile), and others.
  6. swath_stack.txt: distance, average value of stacking cross profiles (swath profile), and others.
  7. swath_stackUP.txt: distance, upper value of stacking cross profiles (swath profile), and others.
  8. swath_topo.int: the gradient file generate by grdgradient.

This script is a little long and complex. I still want to caution:

  1. There is a angle shift between the really used survey line (the central thin black line or the red thick line) and the desired survey lines (the black thick line).
  2. The bash script will echo some important information: (1) the longitude and latitude of end point (endlon,endlat), azimuth (azimuth) and length (length) of the desired survey line, if defining the desired survey line with start point and end point. (2) the longitude and latitude of midpoint (newlon,newlat), and azimuth (newazimuth) of true survey line counterclockwise from South. (3) the longitude and latitude (new1lon,new1lat) of one endpoint of the true survey line. (4) the longitude and latitude (new2lon,new2lat) of another endpoint of the true survey line.
  3. If you want to plot multiple connecting survey lines, you should use the endpoints of true survey lines (new1lon,new1lat and new2lon,new2lat) rather than the endpoints of your desired survey lines.

In addition, there is another good example about Stacking automatically generated cross-profiles in GMT doc.