The hinge in etopo1.cpt

Suppose we have a CPT master file foo.cpt

# HARD_HINGE
# RANGE = -10/20
-1 r/g/b -0.9 r/g/b
 :
0.9 r/g/b 1 r/g/b

Am I right in thinking that makecpt -Cfoo.cpt+h7 -T-20/20 will take the file z-values from -1 to 0, make an affine transformation of them to [-20, 7], then the file values from 0 to 1, and affine transform them to [7, 20]? This would seem to be the case from “world.cpt” for example. If I omit the -T then the RANGE in the file is used instead.

So I was expecting that gmt makecpt -Cetopo1+h-0.001 to give me something close to the original, a rather odd CPT with a natural hinge 1mm below sea-level, but it does not: The original:

-11000  10      0       121     -10500  26      0       137
-10500  26      0       137     -10000  38      0       152
:
-500    138     227     255     -0.001  188     230     255
-0.001  51      102     0       100     51      204     102
100     51      204     102     200     187     228     146

while gmt makecpt -Cetopo1+h-0.001 gives

-11000      10/0/121 -10500.5 26/0/137 L 
-10500.5    26/0/137 -10001   38/0/152 L 
:
-510.5   138/227/255 -0.001   188/230/255 L 
-0.001      51/102/0 91.600    51/204/102 L 
91.600    51/204/102  191.7   187/228/146 L 

I find, by bisection, that gmt makecpt -Cetopo1+h11.01001001 gives almost correct negative z-values as the original, but the positive ones are still strangely off

-11000        10/0/121   -10500           26/0/137 L 
-10500        26/0/137   -10000           38/0/152 L 
:
-1500         79/210/255 -999.99999999  94/223/255 L 
-999.9999999  94/223/25  -500          138/227/255 L 
-500          138/227/255 11.01001001  188/230/255 L 
11.01001001   51/102/0   102.492348903  51/204/102 L 
102.492348903 51/204/102 202.462678083  87/228/146 L 

All very strange, is etopo1.cpt broken in some way? Possibly my understanding of how hinges work is at fault.

I come to this using the cpt as a test fixture for cptutils, trying to get v5 cpt handling working, the file below is master etopo1 as generated by cptutils (from the original from cpt-city), but it differs from the version in 6.4 …

# autogenerated GMT palette "ETOPO1"
# cptutils 1.78, Wed Dec  6 23:21:04 2023
# RANGE = -11000/8500
# HARD_HINGE
-1.0000000000    10/0/121  -0.9545454504    26/0/137
-0.9545454504    26/0/137  -0.9090909008    38/0/152
-0.9090909008    38/0/152  -0.8636363512    27/3/166
-0.8636363512    27/3/166  -0.8181818017    16/6/180
-0.8181818017    16/6/180  -0.7727272521     5/9/193
-0.7727272521     5/9/193  -0.7272727025    0/14/203
-0.7272727025    0/14/203  -0.6818181529    0/22/210
-0.6818181529    0/22/210  -0.6363636033    0/30/216
-0.6363636033    0/30/216  -0.5909090537    0/39/223
-0.5909090537    0/39/223  -0.5454545041   12/68/231
-0.5454545041   12/68/231  -0.4999999545  26/102/240
-0.4999999545  26/102/240  -0.4545454050  19/117/244
-0.4545454050  19/117/244  -0.4090908554  14/133/249
-0.4090908554  14/133/249  -0.3636363058  21/158/252
-0.3636363058  21/158/252  -0.3181817562  30/178/255
-0.3181817562  30/178/255  -0.2727272066  43/186/255
-0.2727272066  43/186/255  -0.2272726570  55/193/255
-0.2272726570  55/193/255  -0.1818181074  65/200/255
-0.1818181074  65/200/255  -0.1363635579  79/210/255
-0.1363635579  79/210/255  -0.0909090083  94/223/255
-0.0909090083  94/223/255  -0.0454544587 138/227/255
-0.0454544587 138/227/255   0.0000000000 188/230/255
 0.0000000000    51/102/0   0.0117648221  51/204/102
 0.0117648221  51/204/102   0.0235295266 187/228/146
 0.0235295266 187/228/146   0.0588236401 255/220/185
 0.0588236401 255/220/185   0.1176471626 243/202/137
 0.1176471626 243/202/137   0.1764706851  230/184/88
 0.1764706851  230/184/88   0.2352942076  217/166/39
 0.2352942076  217/166/39   0.2941177301  168/154/31
 0.2941177301  168/154/31   0.3529412526  164/144/25
 0.3529412526  164/144/25   0.4117647751  162/134/19
 0.4117647751  162/134/19   0.4705882976  159/123/13
 0.4705882976  159/123/13   0.5294118201   156/113/7
 0.5294118201   156/113/7   0.5882353426   153/102/0
 0.5882353426   153/102/0   0.6470588651   162/89/89
 0.6470588651   162/89/89   0.7058823875 178/118/118
 0.7058823875 178/118/118   0.7647059100 183/147/147
 0.7647059100 183/147/147   0.8235294325 194/176/176
 0.8235294325 194/176/176   0.8823529550 204/204/204
 0.8823529550 204/204/204   0.9411764775 229/229/229
 0.9411764775 229/229/229   1.0000000000 255/255/255
B 10/0/121
F 255/255/255
N 128/128/128

Hi Jim-

Pretty sure that all hinges in CPT files are at 0 and cannot be some other value (-0.001 for example). We search for the break in the CPT between lower and upper at the CPT hinge and in the case of this odd etopo1 file there is no z = 0 break, only at -0.001. To allow that we would need to know what the hinge value is. Say it is 7. How would we know that? Probably by allowing an argument to the HARD_HINGE and SOFT_HINGE comments, e.g.,

HARD_HINGE = -0.001

Not sure if I see good reasons for spending time coding that up and changing the original etopo1 to such a file. I believe all the hinges in GMT CPTs are at 0.

Hi Paul,

Perhaps I should disambiguate between a “natural hinge” which is the value at which there is a discontinuity in the gradient, so 0 for most bath-topo scales at zero, and a GMT hinge, the value passed to -C<name>+h<hinge>.

The original ETOPO1 from cpt-city definitely has a natural hinge at -0.001, you can download it and confirm that

-500    138     227     255     -0.001  188     230     255
-0.001  51      102     0       100     51      204     102
100     51      204     102     200     187     228     146

but the etopo1.cpt distributed with GMT has this discontinuity at zero (the same colours either side as the original), so I assumed an affine transformation of the original z-values from [-11000, -0.001] to [-1, 0]. When I implement the same myself, I don’t get the same z-values as in the distributed etopo1.cpt. I spent a while trying to work out why, and find that makecpt -Cetopo1+h-0.001 does not reproduce the original cpt-city values, but performing the same makecpt on the output that my code creates (at the end of the parent post) does. I conclude that either the distributed etopo1.cpt is broken, or my understanding of the format is.

Please note, I’m not requesting a change to the format, for the hinge value to be included in the file itself. I get that the (natural) hinge in the makecpt output should be specified on the command line (I guess ideally one would use -T-11000/-0.001/7000, but that would be too radical a change. so -Cetopo1+h-0.001 -T-11000/7000 instead) when generating a particular static cpt from a master (dynamic) one. Surely the whole point of the +h<value> posfix for -C is to allow users to generate natural hinges at arbitrary <value> from a master cpt which has the hinge at zero,

I know Lester placed his “zero” and -0.001 m for reasons I do not think are good. People can use that CPT if they want to of course . What I will do is to check if +h is used that there is a CPT slice at z=0 and if not give a warning or error.

But if you moved the 0.001 in the original to 0.0 (which I will agree is a good idea), and then performed an affine transformation of [-11000, 0] to [-1, 0], then you would expect that makecpt -Cetopo1 would repoduce the original z-levels (including the hinge at zero fix). It does not.

> gmt makecpt -Cetopo1
-11000	10/0/121	-10500.4999546	26/0/137	L
-10500.4999546	26/0/137	-10000.9999092	38/0/152	L
-10000.9999092	38/0/152	-9501.49986377	27/3/166	L
:

Incidentally. if I take the original v4 cpt, manually edit the natural hinge from -0.001 to 0, run my code to update to v6 and normalise to [-1, 1], I get

# RANGE = -11000/8500
# HARD_HINGE
-1.0000000000    10/0/121  -0.9545454545    26/0/137
-0.9545454545    26/0/137  -0.9090909091    38/0/152
-0.9090909091    38/0/152  -0.8636363636    27/3/166
-0.8636363636    27/3/166  -0.8181818182    16/6/180
-0.8181818182    16/6/180  -0.7727272727     5/9/193
-0.7727272727     5/9/193  -0.7272727273    0/14/203
-0.7272727273    0/14/203  -0.6818181818    0/22/210
-0.6818181818    0/22/210  -0.6363636364    0/30/216
-0.6363636364    0/30/216  -0.5909090909    0/39/223
-0.5909090909    0/39/223  -0.5454545455   12/68/231
-0.5454545455   12/68/231  -0.5000000000  26/102/240
-0.5000000000  26/102/240  -0.4545454545  19/117/244
-0.4545454545  19/117/244  -0.4090909091  14/133/249
-0.4090909091  14/133/249  -0.3636363636  21/158/252
-0.3636363636  21/158/252  -0.3181818182  30/178/255
-0.3181818182  30/178/255  -0.2727272727  43/186/255
-0.2727272727  43/186/255  -0.2272727273  55/193/255
-0.2272727273  55/193/255  -0.1818181818  65/200/255
-0.1818181818  65/200/255  -0.1363636364  79/210/255
-0.1363636364  79/210/255  -0.0909090909  94/223/255
-0.0909090909  94/223/255  -0.0454545455 138/227/255
-0.0454545455 138/227/255   0.0000000000 188/230/255
 0.0000000000    51/102/0   0.0117647059  51/204/102
 0.0117647059  51/204/102   0.0235294118 187/228/146
 0.0235294118 187/228/146   0.0588235294 255/220/185
 0.0588235294 255/220/185   0.1176470588 243/202/137
 0.1176470588 243/202/137   0.1764705882  230/184/88
 0.1764705882  230/184/88   0.2352941176  217/166/39
 0.2352941176  217/166/39   0.2941176471  168/154/31
 0.2941176471  168/154/31   0.3529411765  164/144/25
 0.3529411765  164/144/25   0.4117647059  162/134/19
 0.4117647059  162/134/19   0.4705882353  159/123/13
 0.4705882353  159/123/13   0.5294117647   156/113/7
 0.5294117647   156/113/7   0.5882352941   153/102/0
 0.5882352941   153/102/0   0.6470588235   162/89/89
 0.6470588235   162/89/89   0.7058823529 178/118/118
 0.7058823529 178/118/118   0.7647058824 183/147/147
 0.7647058824 183/147/147   0.8235294118 194/176/176
 0.8235294118 194/176/176   0.8823529412 204/204/204
 0.8823529412 204/204/204   0.9411764706 229/229/229
 0.9411764706 229/229/229   1.0000000000 255/255/255
B 10/0/121
F 255/255/255
N 128/128/128

then run makecpt -CETOPO1-normalised.cpt against that, I seem to get the original back save for some 7th d.p. noise, presumably due to truncation.

$ gmt makecpt -CETOPO1-normalised.cpt
-11000	10/0/121	-10499.9999995	26/0/137	L
-10499.9999995	26/0/137	-10000.0000001	38/0/152	L
-10000.0000001	38/0/152	-9499.9999996	27/3/166	L
-9499.9999996	27/3/166	-9000.0000002	16/6/180	L
-9000.0000002	16/6/180	-8499.9999997	5/9/193	L
-8499.9999997	5/9/193	-8000.0000003	0/14/203	L
: