Process substitution in gmt

Hi all,

Does anyone have any good knowledge of process substitution? I’m trying to use it to generate and specify a CPT on the fly with grdimage:

$ echo <(gmt makecpt -Cjet -T-1000/0/100)
$ cat <(gmt makecpt -Cjet -T-1000/0/100)
-1000	0/0/178.2	-900	0/0/178.2	L	
-900	0/25.5/255	-800	0/25.5/255	L	
-800	0/127.5/255	-700	0/127.5/255	L	
-700	0/229.5/255	-600	0/229.5/255	L	
-600	76.5/255/178.5	-500	76.5/255/178.5	L	
-500	178.5/255/76.5	-400	178.5/255/76.5	L	
-400	255/229.5/0	-300	255/229.5/0	L	
-300	255/127.5/0	-200	255/127.5/0	L	
-200	255/25.5/0	-100	255/25.5/0	L	
-100	178.2/0/0	0	178.2/0/0	B	
B	black
F	white
N	127.5

But getting into trouble:

$ gmt grdimage @earth_relief_05m -JM15c -RNO -C<(gmt makecpt -Cjet -T-1000/0/100) -png
gmt [WARNING]: Modern mode oneliner syntax given but no file prefix provided - using gmtsession
grdimage [ERROR]: File /dev/fd/63.cpt was not found
grdimage [ERROR]: Cannot find file /dev/fd/63.cpt
grdimage [ERROR]: File /dev/fd/63.cpt not found
[Session gmt (0)]: Error returned from GMT API: GMT_FILE_NOT_FOUND (16)
grdimage [ERROR]: Failed to read CPT /dev/fd/63.

I do not understand why this does not work. And, if it is related to the system or gmt.

epiphany time!

grdimage [ERROR]: Cannot find file /dev/fd/63.cpt

GMT adds a .cpt extension to the filename that is expected to contain the cpt-stuff.

Hi Andreas; I was not aware of this feature in bash. I have mostly used $(). However, GMT does have some rules pertaining to filenames, such as CPT files ending in .cpt. I will actually be clarifying naming conventions in GMT since we also have the various interplays between filename modifiers (for bot grids and CPTs) that needs to be spelled out. Working on strengthening parsing of filenames right now.

You are welcome to open a feature request on GitHub to allow for files called /dev/fd/* to be considered differently and the team can discuss it.

Life is so much simpler without bash

julia> grdimage("@earth_relief_05m", J="M15c", R="NO", C=makecpt(C="jet", T="-1000/0/100"), show=1)

So a file containing a cpt, has to have the file extension .cpt?

From the grdcontour man page (

If contours is a string with suffix “.cpt” and can be opened as a file, it is assumed to be a CPT.[..]

If contours is a file but not a CPT[..]

Does gmt check if it is a cpt-file based on the filename, and the file extension? Or does it look at the contents of the file?

Wouldnt it be more robust to check the file contents and then decide whether a file contains a cpt or not? Filename should be completely irrelevant in my opinion.

E.g. You would never expect to find a cpt within my_poems.txt, but you’re in for a surprise.

$ gmt makecpt -Cjet > my_poems.txt

So we always know what we are reading. If you gave -Crandomname we still know it is an argument to -C which expects a CPT table. But, it is not always a file name. It can be a memory reference, a file, a list of colors, name of a master table (no .cpt extension), and probably some other things. And files may have filename modifiers such as +h, +u|U, +i. So there is quite a bit of complexity, and requiring CPT files to end in .cpt does not seem like much hardship until you mentioned the <() operator in bash.

Alright, thanks Paul. I’ll post a feature request about this.

Joaquim: Thanks for the tip. I kind of like bash, but nothing is better than learning something new.

About process substitution; I didnt learn about this until recently either. It’s a very handy method of not having to generate temporary files etc.

Andreas, for the reasons Paul mentioned and for the complexities it would introduce in the code with questionable success, I don’t think it’s a good idea to try to guess if a file is a .cpt

I also hate temporary files. That’s why I love one-liners … and the Julia wrapper.

I know in grdcontour we can either accept a CPT file or a contour list file, hence requiring .cpt extension to tell them apart was a simple fix. I agree in principle that it should not matter what the file is called, but here we would then actually have to inspect the contents to learn what it is, so more coding. But please open that issue.

Ok, I have created an issue,