3

Here's an interesting problem:

I have a 2D "matrix" of double-precision, binary data I'd like to plot using Gnuplot. This is easily done as follows:

plot "foo.dat" binary array=384x384 format='%double' with image

The trick is that certain "regions" of the data have a special value, say 1234567890.0. I want those elements to be fully transparent, and all other matrix entires to be fully opaque. Is there a way to set the transparency channel based on the data itself?

I have looked through the relevant parts of the Gnuplot documentation (link), and I think I need to use the with rgbalpha style, but I'm not sure how that applies or how to map the transparency correctly.

I have also looked at these examples (link), but I'm not sure how I could apply it.

I wonder if this could be done in a one-liner (as above), or if it would need a couple lines (as when plotting contours on top of a binary matrix).

Thanks in advance!

UPDATE

I thought I'd give some examples for posterity. In all examples, I use the following preamble:

set title "Basic Plot"   # Or as appropriate
set size square
set palette @MATLAB   # see <http://www.gnuplotting.org/matlab-colorbar-with-gnuplot/>
set cbrange [-100000:100000]    # This cbrange fits my data well enough
                                # I would LOVE an automated way to do this!
val = 1234567890.0      # For missing data

My basic command produces the following:

plot "foo.dat" binary array=384x384 format='%double' with image

Basic Plot

I also tried what @Christoph suggested: replace values equal to val with NaN:

plot "foo.dat" binary array=384x384 format='%double' \
    using ($1 == val ? NaN : $1) with image

Plot setting val to NaN

I tried using rgbalpha in order to truly control transparency, and it produces the following:

plot "foo.dat" binary array=384x384 format='%double' \
    using 1:1:1:($1 == val ? 0 : 255) with rgbalpha

Plot using rgbalpha

CONCLUSION

The first two methods produce similar results. The first is bad because it messes up the colormap with false maxima. The first and second fall short in that they don't actually achieve transparency ("undefined" values in Gnuplot aren't automatically given transparency). The last is great in that it actually controls transparency, but it is in grayscale and doesn't use the @MATLAB palette as I want it to.

If somebody can cause all entries equal to val to be transparent and get the colormap to work correctly, I'll accept their answer.

***Where to go next****

The Gnuplot Documentation mentions the set datafile missing command (link). This looks promising, but it only seems to work for column-based data -- not binary files.

I imagine the best way to answer my original question is by setting up a set of functions to imitate a given palette for each "column" of the rgbalpha method -- something like this:

red(z)   = <stuff>
green(z) = <stuff>
blue(z)  = <stuff> 
plot "foo.dat" binary array=384x384 format='%double' \
    using red($1):green($1):blue($1):($1 == val ? 0 : 255) with rgbalpha

Bonus points if those functions somehow reference the current palette, so the specifics of a palette aren't hard-coded into these three functions. :-)

jvriesem
  • 1,859
  • 3
  • 18
  • 40
  • The alpha channel goes from 0 to 255: 0 = fully transparent and 255 = fully opaque. When mapping your data into the transparency channel use the `using` option and an appropriate expression. For instance, in the example you link, `using 1:2:3:($3 == 1234567890 ? 0 : 255)` would set the transparency channel to 0 (transparent) if your data point equals 1234567890 and to 255 (opaque) if it doesn't. – Miguel Aug 15 '14 at 04:56
  • Since it's binary data, there aren't three data columns, so that won't work. I think that's the right idea, but not quite there? – jvriesem Aug 15 '14 at 19:38
  • I don't know, why my answer doesn't work for you. I gave a similar answer in [Replacing Colors in Gnuplot Heat Maps (pm3d map)](http://stackoverflow.com/a/22234147/2604213), were the NaN stuff also seemed not to work. I tested my script with the `png`, `pngcairo` and `wxt` terminals with gnuplot 4.6.5 both on Windows and Linux, and it always worked fine. – Christoph Aug 15 '14 at 20:42
  • Using the `rgbalpha` style should also work fine, but the coloring becomes much more involved since you must 1) define the color functions yourself (which I have somewhere), 2) do the scaling yourself (use `stats` and also here remove the undefined values) 3) Use multiplot in case you need to show the colorbox. That all can be done, but is quite lengthy. If you can provide an example data file, I can check if I can get the NaN stuff to work with this data file. – Christoph Aug 15 '14 at 20:55
  • @Christoph: your answer didn't have correct syntax for a binary array, at least as it was originally stated. Your `1:2:...` syntax would probably work for ascii files with data arranged in columns. That's why I edited it. If you mean, "why I'm not satisfied with the results", I am content with what you said. The output I get shows a dark blue outline where the NaNs are (picture #2, above), but I'd like that blue to be transparent instead. (Perhaps it does get rendered as transparency when writing to PNG? I'm using X11.) I've tried using `stats`, but could not get it to work with binary data. – jvriesem Aug 15 '14 at 21:02
  • @Christoph Here's a link to the file: http://www.lpl.arizona.edu/~vriesema/files/foo.dat. Note that in this case, I believe the dimensions are actually 512x512 rather than 384x384. – jvriesem Aug 15 '14 at 21:06
  • Sorry, yes I was referring to the blue color which should be transparent. Right now I could reproduce that with the `x11` terminal (Linux, 4.6.5). Can you try out the `wxt` terminal? – Christoph Aug 15 '14 at 21:07
  • @Christoph: the `wxt` terminal rendered it correctly! Thanks! (Funny how it's different for different terminals....) – jvriesem Aug 15 '14 at 21:14
  • Great. I'll edit my answer to show the script and the image I get with your data. – Christoph Aug 15 '14 at 21:15
  • Thanks again! (I also realized that I may not have sent you the exact same data file I used to make the above images. It should look similar, however.) – jvriesem Aug 15 '14 at 21:16

1 Answers1

3

You can achieve that by giving the respective pixel a value of 'NaN':

value = 123456789.0
plot "foo.dat" binary array=384x384 format='%double' \
     using ($1 == val ? NaN : $1) with image

Note, that this depends on the selected terminal. It works at least with wxt, pdfcairo, pngcairo and png, and does not work with x11 and postscript. I didn't test other terminals.

Here is a self-contained example. The background color is set to show that the pixel indeed is transparent and not white:

set xrange [0:1]
set yrange [0:1]
set isosamples 11
set samples 11
plot '++' using 1:2:($1 == 0.5 && $2 == 0.5 ? NaN : $1) with image

The result with 4.6.5 is:

enter image description here

Using your example data file, the following script works fine and gives a nice result:

set terminal pngcairo size 800,800
set output 'foo.png'
set size square

f(x)=1.5-4*abs(x)
set palette model RGB
set palette functions f(gray-0.75),f(gray-0.5),f(gray-0.25)

val = 1234567890.0

set autoscale xfix
set autoscale yfix
set cbrange [-10000:10000]
plot 'foo.dat' binary array=(512,512) format='%double' using ($1 == val ? NaN : $1) with image notitle

enter image description here

Christoph
  • 47,569
  • 8
  • 87
  • 187
  • This definitely got me on the right track -- replacing values with NaN tells Gnuplot the values are undefined, which it then ignores. It doesn't quite work as you wrote it: binary files don't have "columns" (or rather, Gnuplot treats it as a single column), so your `using 1:2:` should be `using `. – jvriesem Aug 15 '14 at 19:30
  • I edited your answer to fix the issue I described in my last comment, and am about to accept your answer. Thanks! – jvriesem Aug 15 '14 at 19:36
  • I'm not entirely sure what you did with the palette, but it looks great! (Also, it isn't actually doing "true" transparency, but this is *entirely* sufficient for my purposes. :-)) Thanks again -- so much! – jvriesem Aug 18 '14 at 19:23
  • 1
    I did nothing special with the palette. I got the function of the jet palette from [gnuplotting.org](http://www.gnuplotting.org/matlab-colorbar-with-gnuplot/comment-page-1/#comment-38037). To have real transparency, you must use `set terminal pngcairo nobackground`, see [this result](http://i.stack.imgur.com/Lumtn.png). – Christoph Aug 18 '14 at 19:35