Getting color value from CPT + z-value

Hi GMT team,

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.

Cheers - Kyle

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?

Would you be interested in a Julia based solution? The line https://github.com/GenericMappingTools/GMT.jl/blob/master/src/choropleth_utils.jl#L42 does just that.

Hi Joaquim, thanks for the quick reply.

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
          }
        '
}

Good that you found a way, because:

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.

Probably simpler to use makecpt and sample1d. E.g

gmt makecpt -Cgeo -Fr | tr ‘/’ ‘\t’ | gmt sample1d -i0:3 -T-4000/-3000/100

interpolates r g b just for the interval -4000/-3000 in steps of 100, while

gmt makecpt -Cgeo -Fr | tr ‘/’ ‘\t’ | gmt sample1d -i0:3 -T5,

returns the color for z = 5.

Waking up an old post.

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):

gmt makecpt -T-6/6/0.5 -Cpolar -Fr -N | tr '/' '\t' | gmt sample1d -i0:3 -T-1.24, -o1-3 | tr '\t' '/'

Here’s the output: 202.3/202.3/255

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.

1 Like