3

I want to plot a single contour with variable line colour. I have defined the colour at each (x,y) point explicitly in a data file as follows

  -0.4000  -0.4000   7.6807  253    0    0
  -0.3933  -0.4000   7.6907  253    10   0
  -0.3867  -0.4000   7.7009  153    25   45
  -0.3800  -0.4000   7.7112   33    25   90
  -0.3733  -0.4000   7.7215  200   130   40
  -0.3667  -0.4000   7.7320   23    11  100
   .
   .
   .

Above, the first three columns correspond to the x, y and z values, and the last three columns are the respective values for red, green and blue colours, each varying between [0:255].

Using the following code, I can get the right colour projection for the surface, but the line colour of the contour is wrong and does not vary at all.

set pm3d at s
set contour base
set cntrparam levels discrete 7.245
rgb(r,g,b) = int(r)*65536 + int(g)*256 + int(b)
splot 'data' u 1:2:3:(rgb($4,$5,$6)) w pm3d lw 2 lc rgb variable 

Does anyone know how to fix this issue? Any help is much appreciated.

Update: In case it helps, here is the output I get from the above script and the related data file. As you can see, the isocontour does not follow the colour pattern projected onto the surface.

enter image description here

Saeed
  • 33
  • 5
  • Can you share the output image too ? – newstudent Jul 22 '22 at 06:47
  • @Saeed, so, is the color only related to the x- and y-values but unrelated to the z-value? As newstudent wrote, adding your current output graph to the question definitely would help. – theozh Jul 22 '22 at 19:31
  • Thanks, @newstudent I have added the output image, I hope it helps. – Saeed Jul 23 '22 at 12:29
  • @theozh: thank you for your comment. Yes, the colour only depends on x and y values and is entirely unrelated to the z-value. I have added the output image of my script. I hope it helps clarify what the issue is and what I want to achieve. – Saeed Jul 23 '22 at 12:30
  • @Saeed, thanks can you also share your original data to reproduce the fig? – newstudent Jul 24 '22 at 15:03
  • 1
    @newstudent, thanks. I added a link in the description, allowing you to access the data file. – Saeed Jul 26 '22 at 13:07
  • @Saeed thanks for adding the data. It _never(!)_ hurts adding data. Sometimes, I spend more time for generating (illustrative and realistic) test data than for the actual script. Now, I can easily reproduce your graph and see that you must be using gnuplot 5.2.6 or earlier. I will think about a solution. – theozh Jul 26 '22 at 13:48
  • @Saeed From you data and graph I see that there are various shades of R, G, and B. But maybe to simplify, would be 3 colors (red, green, blue) enough? Are the colors maybe regular in 60 degree sectors? Otherwise, I guess you would have to interpolate the colors for the contour line from your data. – theozh Jul 26 '22 at 14:28

2 Answers2

1

This would be my suggestion on the simplfied assumption that there are only 3 colors (red, green, blue) depending only on x and y and constant colors within 60 degree sectors. Let me know if this assumption is not correct.

Script: (tested with gnuplot 5.0.0 and 5.4.1)

### variable color contour line
reset session

FILE = "SO73015796.dat"

set contour
set cntrparam levels discrete 7.245
rgb(r,g,b) = int(r)*65536 + int(g)*256 + int(b)

set table $Contour
    splot FILE u 1:2:3
unset table

set xyplane relative 0
unset contour
unset colorbox

set angle degrees 
myColor(x,y) = (a=atan2(y,x), abs(sin(a))<sin(30) ? 0x00ff00 : \
                abs(sin(a-60))<sin(30) ? 0xff0000 : 0x0000ff)
set key noautotitle

splot FILE u 1:2:3:(rgb($4,$5,$6)) w pm3d lc rgb var, \
      $Contour u 1:2:(6.5):(myColor($1,$2)) index 1 w l lw 2 lc rgb var
### end of script

Result:

enter image description here

Addition:

The following is a solution which doesn't make simplified assumptions, but takes the color from the original data. Well, a bit slow and inefficient. Maybe somebody has ideas to speed this up (maybe with specialized external tools).

  • plot the contour lines into a new datablock
  • find the closest point (in x,y) from 3D data and take its color (in principle, you could also interpolate the color between closest points)

In the example below you have 2 contour lines and about 700 contour points and about 15000 3D-points in your file. Hence, you need to read the 3D-file about 700 times from disk. Therefore, I thought it might be faster if you first load the file 1:1 into a datablock into memory, but I am not sure if it is really faster. On my old laptop the creation of the graph takes about 1-2 minutes.

Script: (works for gnuplot>=5.2.0)

### variable color contour line
reset session

FILE = "SO73015796.dat"

FileToDatablock(f,d) = GPVAL_SYSNAME[1:7] eq "Windows" ? \
                       sprintf('< echo   %s ^<^<EOD  & type "%s"',d,f) : \
                       sprintf('< echo "\%s   <<EOD" & cat  "%s"',d,f)     # Linux/MacOS

load FileToDatablock(FILE,'$Data')

set contour
set cntrparam levels discrete 7.25, 7.35
rgb(r,g,b) = int(r)*0x10000 + int(g)*0x100 + int(b)

# plot grid and contour data into datablock
set table $Temp
    splot $Data u 1:2:3     
unset table
unset contour

# get only contour lines into a new datablock
stats $Temp u 0 nooutput   # get number of blocks
N = STATS_blocks
set table $CONTOURS
    splot $Temp u 1:2:3 index 1:N-1   # all blocks except first (index 0-based) into datablock
unset table

# loop all contour points and take the color from closest 3D point
Dist(x0,y0,x1,y1) = sqrt((x1-x0)**2 + (y1-y0)**2)   # distance between to points
set print $ColoredContours
    do for [i=1:|$CONTOURS|] {
        if (strlen($CONTOURS[i])==0 || $CONTOURS[i][1:1] eq '#') {
            print $CONTOURS[i]
        }
        else {
            x0 = real(word($CONTOURS[i],1))
            y0 = real(word($CONTOURS[i],2))
            dmin = NaN
            stats $Data u (d=Dist(x0,y0,$1,$2),d<dmin || dmin!=dmin ? \
                (dmin=d, color=rgb($4,$5,$6)) : 0) nooutput
            print sprintf("%g %g 0x%06x", x0, y0, color)
        }
    }
set print

set xyplane relative 0
unset colorbox
set grid x,y
set key noautotitle
set zrange [zMin=6.0:]

splot $Data u 1:2:3:(rgb($4,$5,$6)) index 0 w pm3d lc rgb var, \
      $ColoredContours u 1:2:(zMin):3 w l lc rgb var
### end of script

Result:

enter image description here

theozh
  • 22,244
  • 5
  • 28
  • 72
  • Many thanks, @theozh. This is a really nice workaround. However, It's not still what I am looking for. The colours are in general not symmetrically distributed and there is no guarantee they have such a simple RGB alternation. Actually, even here you can probably notice a change in the shading around the bottom of the surface, making everything look darker. I'm wondering if there is any way to define myColor function based on the RGB columns in my data file. – Saeed Jul 27 '22 at 10:19
  • @Saeed Ok, so this was a simplification which apparently is not sufficient. That's fine. So, how is the color determined depending on x and y? If there is a function you can use this for the color. However, I assume that the color might be an output e.g. of a lengthy calculation or simulation? I guess it will be difficult to find ("reverse engineer") a function matching thousands of datapoints. I would say you need to take the points on the contour and interpolate the color from the 3D data. This might get lengthy with about 200 contour points and about 15'000 3D points. I will think about it. – theozh Jul 27 '22 at 10:33
  • This data is the output of a simulation through which everything, including the projection parameter (i.e. RGB colours), is determined self-consistently. So there is no way to find a simple, functional form for this. Anyway, thanks again for your time and help. – Saeed Jul 28 '22 at 12:03
  • 1
    @Saeed see modified answer with second solution. I guess that's what you were looking for. But still room for improvements. – theozh Jul 29 '22 at 10:49
  • this is fantastic and exactly what I've been trying to produce. Thanks so much @theozh for taking the time to help me out. I really appreciate it. On a side note, to speed up the whole process, I think it's possible to use the fact that both the x and y points are equally spaced. So knowing the corresponding x and y spacings, one can quickly find the closest colour to any (x,y) point on the contour from the main data block. – Saeed Jul 31 '22 at 16:27
  • @Saeed yes, if you have a range from -0.4 to +0.4 and 121 equidistant samples in both x and y this will give a grid of 0.00661. However, you still will have to read the file (or datablock) about 700 times., but nevertheless, this might speed up the process since you don't have to do about 15'000 calculations each time. So, answer acceptable, question answered? Do you maybe need help implementing this in gnuplot? – theozh Aug 02 '22 at 12:26
  • I think I know how to implement this in your script. Thanks again for your time and help. – Saeed Aug 03 '22 at 14:54
  • @Saeed If this answer was helpful and solved your problem, please select the check mark at the top left of the answer indicating that the question is answered. – theozh Aug 17 '22 at 15:31
0

In order to get contour with variable linecolors you need to include the palette command in the splot.

set pm3d at s
set palette rgbformulae 33,13,10
set contour
set cntrparam levels 50
set zrange [:8]
#rgb(r,g,b) = int(r)*65536 + int(g)*256 + int(b)
splot 'data' u 1:2:3 w l ls 7 palette notitle 

Contour with variable linecolors

However, based on the output it looks like your data doesn't vary much at the center to have variable linecolors. You can also play around with set contrparam levels to change the intensity of the contours.

newstudent
  • 402
  • 6
  • 19
  • Nice, but I guess it is more complex. The OP doesn't want a palette color, instead the color from the dataset, where the color does not depend on z but only on x and y. – theozh Jul 26 '22 at 14:08
  • Thanks, @newstudent, but this is not what I want. You have basically used a default z-value-dependent palette for shading both the surface and contours. As I've explained above, my colours are predefined and only dependent on x and y values. – Saeed Jul 27 '22 at 10:25
  • @Saeed, Okay, but based on your question, Its still unclear how the colors are dependent on x and y ? is there a specific relation ? – newstudent Jul 27 '22 at 11:13
  • @newstudent there is no functional form to describe this dependence, but it's there and you can see it in the data file. – Saeed Jul 28 '22 at 12:08