I need a simple way to determine the R/G/B values for a list of Z-values and a given CPT. These R/G/B values are used to replicate the exact colors of the GMT plot in a different software package. Ideally, I would be able to input a data table and CPT and get the colors directly via stdout. I haven’t found a way to do this with GMT - but I can see the RGB data in output .ps files (like from psxy -Sc), so I could imagine writing a script to extract that somehow. I could also try to write my own interpolator, but I’m worried about the complexities of Z-values which are times, etc. Please stop me from trying that by pointing me in a better direction! And thanks as always for any help.
So… if I understand correctly, you have a CPT, and want to know for a given value, what color it corresponds to.
Why not just using ˋgrep` to find the line desired?
I’m hoping to call GMT directly from the command line.
Here’s a slightly silly bash function that calls GMT psxy and then uses gawk to parse out the RGB values from the PS code. It hijacks symbol size as a way to preserve record numbers, so that the output can be merged back to the input table if any lines are skipped for some reason. It seems to work for my current needs, including for datetime (ISO8601) Z-values, and I’m happy that GMT is doing all the interpolation of the CPT file just like when I make the actual plots with psxy. I’m putting the code here in case anyone else needs this specific functionality and is also wedded to the command line.
Of course, a pure GMT solution would be much better, but I don’t know of any way to get at the GMT_get_rgb_from_z API function from the command line.
Cheers
Kyle
# get_rgb_from_z_and_cpt()
# Prints RGB values for specified Z-values, given a CPT file
# Inputs: Data table, CPT file
# Output: line_number red green blue
# line_number is the equivalent line in the input data table
# Argument 1: path to input data table
# Argument 2: field delimiter for data table (" " for whitespace delimited)
# Argument 3: field number for z value (first column=1)
# Argument 4: path to CPT file
function get_rgb_from_z_and_cpt() {
[[ ! -s "${1}" || ! -s "${4}" ]] && return
gawk -F"${2}" '
($'${3}'!="") {
# FNR/600 in inches turns out to be FNR in PS code units
print 0, 0, $'${3}', FNR/600
}' "${1}" | gmt psxy -N -Rg -JX5i -Sc -C"${4}" -O -K --PROJ_LENGTH_UNIT=i | gawk '
# Load a new color. This always happens before any circles are plotted.
($(NF)=="FS") {
# Get rid of the leading brace
gsub("{","")
if ($(NF-1) == "A}") {
# Setting a gray value
red=$1*255
green=red
blue=red
} else if ($(NF-1) == "C}") {
# Setting a non-gray value
red=$1*255
green=$2*255
blue=$3*255
} else {
# We do not handle other color modes like CMYK in this function
print "Error: Color assignment type not understood:", $(NF-1) > "/dev/stderr"
exit 1
}
}
# Print an event with the current color. This always happens after a color
# has been loaded.
($(NF)=="Sc") {
print $1, red, green, blue
}
'
}
You cant access the library functions of compiled code unless you link to them or use a tool that offers a FFI and an example of it was what I showed with that Julia function.
In August 2024, I found that I needed to extend Pål’s nifty suggestion in order to make it work correctly. I used something like this (to sample from a color bar with min= -6, to max +6, at the value -1.24):
The -N in makecpt omits the background, foreground and NaN color fields. The tr is the translate characters function, to convert from slashed fields to tab fields, then back again.