2

I have the following sample data:

col1 2 0 1 1
col2 1 1 0 0
col3 1 1 1 0
col4 1 1 2 1
col5 1 1 1 1
col6 2 0 1 1
col7 1 1 2 2
col8 1 1 2 1

columns #4 and #5 are the color codes for columns #2 and #3. For example, I want '1' for green, 2 for white, and 0 for orange.

Here is how I tried to plot it:

set key off
unset border
unset xtics
unset ytics
set style data histograms
set style histogram rowstacked
set boxwidth 1 relative
set style fill solid 1.0 border -1
set yrange [0:2]
set lmargin 0
set rmargin 0
set tmargin 0
set bmargin 0.1
set terminal pngcairo truecolor size 100,65
set output "/export/test.png"
set palette model RGB defined ( 0 'orange', 1 'green', 2 'white')
plot 'test.data' u 2 linecolor rgb "orange",  '' u 3 linecolor rgb "green"

Here is what I got without being able to implement the color according to the actual data:

Sample Image

So how do I use the actual colors as specified in my data file?

[in case anybody wonders and in case the rational behind this encourages your efforts;-): I am trying to draw an HP blade c7000 chassis, using color coding to show empty chassis slots, slots with blades that are powered on and off. The actual values in column #2 and #3 indicate whether the blade is full-height (with value of 2) or half-height blades (with a value of 1). Where there is no blade, it still gets a value of 1, defaulting to half-height.]

## Update

With this, I was able to get what I need...Anybody has a shorter version?

plot 'test.data' u ($5==0?$2:sqrt(-1)) linecolor rgb "orange",\
    '' u ($5==1?$2:sqrt(-1)) linecolor rgb "green",\
    '' u ($5==2?$2:sqrt(-1)) linecolor rgb "white",\
    '' u ($4==0?$3:sqrt(-1)) linecolor rgb "orange",\
    '' u ($4==1?$3:sqrt(-1)) linecolor rgb "green",\
    '' u ($4==2?$3:sqrt(-1)) linecolor rgb "white"

new sample image

Further refinement

How do I add numbering to the blocks as the following image shows:

blocks with numbering

Updated Question:

I noticed that sometimes the color pallete gets the color wrong, unless all colors defined in the pallete are present in the data. For example, with the following data:

1  2 0 1 1
2  1 1 0 0
3  2 0 1 1
4  2 0 1 1
5  1 1 1 1
6  1 1 1 0
7  1 1 1 1
8  1 1 1 1

As you can see from col#4-5, I have only 'green' (1) and 'organge' (0). As I don't have any slot empty, I don't have 'white' color. I get this image:

enter image description here

This image obviously is incorrect, as white would indicate that I have an empty slot. I expected this image:

enter image description here

So how did the colors 'white' and 'green' get flipped? I noticed if I change any one of those color code to white, then the color pallete will work correctly.

zagpoint
  • 85
  • 1
  • 10

2 Answers2

2

I would use the boxxyerrorbars plotting style. Despite the name, this is what you should use, when you want to plot "different" boxes.

set key off
unset border
unset xtics
unset ytics
unset colorbox
set style fill solid 1.0 border -1

set palette model RGB defined ( 0 'orange', 1 'green', 2 'white')
set cbrange [0:2]
set style data boxxyerrorbars
plot 'test.data' u 0:(0.5*$2):(0.5):(0.5*$2):4 lc palette,\
    '' u 0:($2 + 0.5*$3):(0.5):(0.5*$3):5 lc palette

The boxxyerrorbars plotting style itself takes four columns, x, y, dx, and dy, and the lc palette uses the values in a fifth column to determine the color based on the current palette. To make the values in the palette absolute values I additionally set the cbrange to the same range which is covered by the palette.

The expression using 0:(0.5*$2):(0.5):(0.5*$2):4 means:

  • Use the zeroth column (the row number) as x-value (box center)
  • the value in the second column multiplied by 0.5 as y-value (box center)
  • the number 0.5 as dx (half of the box width)
  • the value in the second column multiplied by 0.5 as dy-value (half of the box height)

For the second plot part the y-value is the value in the second column plus half of the value in the third column.

enter image description here

This solution can also easily be written to allow increasing the number of stacked boxes:

set palette model RGB defined ( 0 'orange', 1 'green', 2 'white')
set cbrange [0:2]
set style data boxxyerrorbars

last_column = 3
plot for [i=2:last_column] 'test.data' \
    u 0:(0.5*column(i) + sum[c=2:(i-1)] column(c)):(0.5):(0.5*column(i)):(column(last_column + i - 1)) lc palette
Christoph
  • 47,569
  • 8
  • 87
  • 187
  • BTW, why '0th' column, instead of '1st' column, as the x value? I tried with '1' and it works just fine. – zagpoint Dec 09 '16 at 08:02
  • Because in the zeroth column you have strings like 'col1', at least according to your question. – Christoph Dec 09 '16 at 08:03
  • That is my confusion. If we start with index 0, we won't have a 5th column to work with. what does the last number in "u 0:($2 + 0.5*$3):(0.5):(0.5*$3):5" refer to? – zagpoint Dec 09 '16 at 08:09
  • Numbering of the physical columns in your file starts at `1`,`0` is a pseudo column which contains the row number, but that is not part of the data file. So, you have a data file with 5 columns starting at 1 and in your example file the column(1) contains the `col1`, `col2` etc strings. – Christoph Dec 09 '16 at 08:21
  • Any way to add a number on the color block? Top row: 1, 2, 3, 4, 5, 6, 7, 8; bottom row (unless subsumed by the top row in the case of full height blades): 9, 10, 11,12,13,14,15,16...In the example image, we'd have: 1,2,3,4,5,6,7,8,10,11,12,13,15,16...It is almost like we basically label the blocks with their col# (or col#+8 in the case of the lower row)... – zagpoint Dec 10 '16 at 01:16
  • Just noticed that unless I have all colors present in my data, the plot sometimes is off. Any idea why? – zagpoint Dec 29 '16 at 22:29
  • The values given in the palette are relative to the actual cbrange, not absolute values. So you must also use `set cbrange [0:2]` if not all values are present. Instead of using a palette you could also `plot ... lc var` in which case the value in the last `using` column gives a linetype. – Christoph Dec 29 '16 at 22:53
1

The colors are used to identify the corresponding parts in different stacks. Therefore they must follow the same order in all stacks which belong to the same histogram.

But Gnuplot has a newhistogram command after which the colors can be "reset". And there is the multiplot command which can be used to add new histograms in a loop.

Here is the part of the script which replaces the original plot command:

set style line 1 lt 1 lc rgb "white"
set style line 2 lt 1 lc rgb "green"
set style line 3 lt 1 lc rgb "orange"

stats 'test.data' u 2
n = STATS_records

set multiplot

do for [i=0:n-1] {
   plot "test.data" u (0) ,\
        newhistogram "" at i, "" every ::i::i u (style = $5 + 1, 0), \
                              "" every ::i::i u 2 ls style,          \
                              "" every ::i::i u (style = $4 + 1, 0), \
                              "" every ::i::i u 3 ls style
}

unset multiplot

And this is how it works:

  • set style ...: Define the styles (colors) which will be used.
  • stats ...: Find the number of rows. We are going to plot an independent histogram for each row.
  • set multiplot: We will plot again and again on the same area.
  • "test.data" u (0): Plot nothing, but reserve space for all histograms.
  • new histogram "" at i: Initialize a new histogram without a name with offset i on the x axis. We are going to plot a single stack at this offset.
  • "" every ::i::i: Plot row i.
  • u (style = $5 + 1, 0): Plot nothing, but read the color of the current row from file.
  • u 2 ls style: Plot column 2 of the current row with the previously read style.

I'm not sure whether this version is shorter than yours :)

enter image description here

maij
  • 4,094
  • 2
  • 12
  • 28
  • Thanks! Not necessarily shorter, but thanks for sharing the different ways of achieving the goal. I wish there is a way to simply say 'linecolor rgb $4 (or $5 for that matter)" – zagpoint Dec 07 '16 at 06:01