gnuplot matrix increased pixel size - matrix

I am having trouble visualizing a large matrix in gnuplot, seemingly due to pixel sizes. As a minimal working example, I try to plot a 5000 x 5000 identity matrix with the following commands:
set term pngcairo enh col
set out "plot.png"
unset key
set datafile commentschars "%#"
set xrange [0:5000]
set yrange [5000:0] reverse
plot 'A' matrix w image
Data is here. The resulting plot looks like this:
You can see some of the diagonal elements but it looks quite bad and much of the diagonal is missing. When I go to 10000 x 10000, none of the diagonal is visible. It seems the pixels sizes aren't large enough. In contrast, the following matlab code produces a nice figure:
A = eye(5000,5000);
imagesc(A);
The figure looks like this:
Here we can see a nice diagonal in the image. How can I make gnuplot produce a similar figure?

Option 1: Make your plot resolution big enough that it can actually represent 5000 pixels per side. If the resulting image file is too large for your purpose you can shrink it with an external tool such as ImageMagick. A likely problem is that the diagonal line is so thin that it will become invisible when you shrink the figure.
set size square
unset key
set datafile commentschars "%#"
set xrange [0:5000]
set yrange [5000:0] reverse
set term pngcairo size 6000,6000 fontscale 10.
set output 'bigplot.png'
plot 'A' matrix w image
unset output
Option 2: Down-sample the matrix so that it fits in a smaller plot resolution. E.g.
set size square
unset key
set datafile commentschars "%#"
set xrange [0:5000]
set yrange [5000:0] reverse
set term pngcairo size 600,600
set output 'smallplot.png'
plot 'A' matrix every 10:10 with image
Shown below is the output from option 2

Related

GIF term animation in gnuplot with multiplot

I came across the gif terminal in gnuplot. I read that it keeps track of each plot command until the second set out command is encountered.
Recently, the need for an animated multiplot came up - is there any way of achieving this with the gif terminal?
What I need essentially is a matrix of three plots, each one animated, in some grid I can specify.
In a normal single plot environment each plot command creates a new frame. In a multiplot environment each set multiplot - unset multiplot pair creates a new frame which can contain several plot commands like this example:
set terminal gif animate delay 100
set output "multiplot_animated.gif"
n = 50
dphi = 2*pi/n
do for [i=0:(n-1)] {
phi = i*dphi
set multiplot layout 2,1
plot sin(x+phi)
plot cos(x+phi)
unset multiplot
}
This is the result. Skip the delay 100 (or change the number) to change the animation speed.

How to decimate / decrease number of tic labels in gnuplot matrix

I have a matrix of data, which is an output of automatic music transcription program. I want to plot it using gnuplot, assigning appropriate labels. Here's my dropbox with some data, where Intensity.dat is actual data, example.stn is a column of string values, some of which are to be displayed on y axis and example.all is just a result of paste example.stn Intensity.dat > example.all Script:
reset
set title "Intensity detection"
set palette negative grayscale
set cbrange [0.01:1]
set xlabel "Time [s]"
set ylabel "Musical note"
set terminal qt font "Verdana,16"
set logscale cb
xincr=0.04644
yincr=1
plot 'example.all' u (($1+0.5)*xincr):($2*yincr):3 matrix with image
produces
plot produced by script 1. Everything's OK, now just tic labels...
After I change the last line to plot 'example.all' u (($1+0.5)*xincr):($2*yincr):3 matrix rowheaders with image, the y-axis becomes too densly populated (It's plot2.jpg from my dropbox, link on top. Sorry guys, I'm new and it doesn't allow me to post more than 2 links).
What I want is a way to present only the labels I want (or hide others, whatever), not all at a time (because it looks unreadable). I'd also like to be able to quickly change them to the others when I need to do so. Supposingly, I want to display every 12th label, but still keep entire matrix with all rows plotted. Or every 12th starting from 2nd label AND every 12th starting from 6th. I've already tried many ways but I'm stuck. Functions like :ytics() or :yticlabels() can't make it, at least for me. And yes, I need this Verdana 16, and removing labels completely is out of question.
I'll be extra grateful if the method applies also for x-axis, as I have an analogical problem with x-axis in other plot, but I generally appreciate any help.
You can separate plotting the image from plotting the ytics like this:
condition(n) = (ceil(n)%12-2 == 0) || (ceil(n)%12-6 == 0)
plot 'Intensity.dat' u (($1+0.5)*xincr):($2*yincr):3 matrix with image ,\
'example.stn' u (NaN):0:ytic(condition($0) ? strcol(1) : "") notitle
The function condition checks whether the label should be plotted or not. I have used ceil to convert from a real number to an integer which is required by the modulo operator (%). The condition function is called with the linenumber $0. The NaN while plotting 'example.stn' avoids plotting data points while keeping the chance for setting the labels. If the condition is met (12th label starting from 2nd or 12th starting from 6th), we use the actual label, else an empty string is used.

vertical lines from data in file in time series plot using gnuplot

I am currently working on a project to plot the development of humidity and temperature at my place. Therefore I am using a raspberry pi 2 with Raspbian Jessie and a DHT-22.
In the end it comes down to a file per day, that stores the measurements all 30 seconds. The file is named like this; 2016-01-30_Temp_Hum_data and contains the following data
2016-01-30-19:30:03 22.0 50.2
2016-01-30-19:30:34 22.0 50.2
2016-01-30-19:31:04 22.0 50.3
2016-01-30-19:31:35 22.0 50.3
2016-01-30-19:32:05 22.0 50.2
whereas the first part is the timestamp, the second value separated by a space is the temperature, followed by the humidity.
Now I plot this with the following script that is called by a for-loop in a bash file that iterates over all data files that I described above.
!/usr/bin/gnuplot
reset
# This command works for a linux computer. In linux, you need to specify the exact location of
# the font you want to use
set terminal png notransparent rounded giant font "/usr/share/fonts/msttcore/arial.ttf" 24 \
size 2600,960
# nomirror means do not put tics on the opposite side of the plot
set xtics nomirror
set ytics nomirror
# Line style for axes
# Define a line style (we're calling it 80) and set
# lt = linetype to 0 (dashed line)
# lc = linecolor to a gray defined by that number
set style line 80 lt 0 lc rgb "#808080"
# Line style for lines
set style line 1 lt 1 lc rgb "#A00000" lw 4
set style line 2 lt 1 lc rgb "#00A000" lw 4
# Add line at 70
# Draw a line from the right end of the graph to the left end of the graph at
# the y value of 70
# The line should not have an arrowhead
# Linewidth = 4
# Linecolor = black
# It should be in front of anything else drawn
set arrow from graph 0,first 70 to graph 1, first 70 nohead lw 2 lc rgb "#500000" front
set arrow from graph 0,first 50 to graph 1, first 50 nohead lw 2 lc rgb "#005000" front
set arrow from graph 0,first 20 to graph 1, first 20 nohead lw 2 lc rgb "#005000" front
# Put a label 80% hum at 80% the width of the graph and y = -2 (it will be just above the line drawn)
set label "70%" at graph 0.8, first 72
set label "50%" at graph 0.8, first 48
set label "20°C" at graph 0.8, first 22
# Define data
set xdata time
set timefmt "%Y-%m-%d-%H:%M:%S"
set format x "%H"
set xlabel "time"
set ylabel "values"
set yrange [10:80]
heading="Kueche Temperatur und Luftfeuchtigkeit " . timestamp
set title heading
set key reverse Left outside
set grid
set style data lines
plot datafile using 1:2 ls 1 title "",datafile using 1:3 ls 2 title ""
It is working quite well like this, but now I made a node everytime I start cooking or the washing machine and made a file like this:
2016-01-30-15:00:00 cooking
2016-01-22-19:00:00 washing machine
2016-01-23-12:30:00 washing machine
Now I would like to add the following functionality. If there is an entry in the cooking/washing file that falls into the x range of the plot, I want a vertical line from the bottom to the top of the plot with a note that says "cooking" or "washing machine.
Unfortunately I don't even get a vertical line at some point. I tried
set arrow from 15,0 to 15,100 nohead lw 2 lc rgb "#500000" front
and
set arrow from 2016-01-30-19:00:00,0 to 2016-01-30-19:00:00,100 no head lw 2 lc rgb "#500000" front
as well as several other examples I found online, but nothing worked.
Can someone help me in finding a way to
At least draw a vertical line on my time series plot
Or even better, tell me how I can automatically detect if there is a point in the additional file that falls into the x range of the actual plot and add vertical lines according to that file?
Thanks in advance!!
I am not going to reproduce your entire script here, but focus on the part that you are asking about - adding the vertical lines.
I will add the labels at the top of the graph, and doing this will require adding an little bit of extra top margin to make them fit. If you place them in the graph itself, you don't need this extra top margin. Additionally, drawing the vertical lines is made much easier as you have fixed the yrange. We could still make this work without doing that, but we would either need to create a plot, figure out the yrange it used, and then draw the new plot using that computed yrange, or use the stats command to figure it out (we actually will need the stats command later to figure out the xrange). We avoid this by having the fixed yrange.
The minimal set-up that I'll need to demonstrate this is the following:
set xdata time
set timefmt "%Y-%m-%d-%H:%M:%S"
set format x "%m/%d"
set yrange [10:80]
set tmargin at screen .9
unset key
When you weave this into your full script, you can add the additional details (title, axis labels, etc). I also changed the x-axis labels to make it clear that the lines are drawn in the correct place (you will use your original labels). You may need to adjust the offset of the title to avoid a collision between the line labels and the title.
Finally, we can plot the vertical lines and labels with (you'll want to combine this with your existing plot command)
plot datafile u 1:(10):(0):(70) with vectors nohead,\
"" u 1:(80):2 with labels offset 0,char 1.1 rotate by 45
We use the vectors style (help vectors) which expects four values: x, y, x_delta, and y_delta. As we want vertical lines, we set x_delta to 0 and as we range from the bottom (y=10) to the top (y=80) we can set y to 10 and y_delta to 70 (80-10).
The labels are, of course, much simpler. Here we place the label at the top of the graph (moved up by 1.1 characters to place it above the graph) and rotated to avoid overlapping labels.
Unfortunately, there is a problem here. The range from your vertical line file may mess up the range determined from the original file. This can be fixed by using the stats command and then fixing the range. The stats command does not like time series data, but we can manually parse the time series as the first step (before set xdata time).
If we put the following two commands at the very top of the script
stats datafile u (strptime("%Y-%m-%d-%H:%M:%S",strcol(1))) nooutput
set xrange[STATS_min:STATS_max]
it will fix the xrange according to the range in datafile, so we don't have this problem.
Your original example data does not have any overlap with the data you provided for drawing the vertical lines. In order to demonstrate this, I added one extra line to the beginning of your data file,
2016-01-30-12:30:03 30.0 70.2
to force there to be an overlap. Thus taking your original script, adding these extra commands (stats and xrange) at the beginning, and adding the two new plot commands to your existing plot command (which now reads
plot datafile1 using 1:2 ls 1 title "",\
"" using 1:3 ls 2 title "", \
datafile2 u 1:(10):(0):(70) with vectors nohead title "",\
"" u 1:(80):2 with labels offset 0,char 1.1 rotate by 45 title ""
), we obtain
I did not use your set terminal command here, so fonts may look different. You will probably have to do some adjustments of sizes and offsets to produce a final plot that you are happy with, but this adds your original requirements. I also did not add the extra margin here, as the title automatically did that. However, if you need to move the title up to avoid the labels (which I didn't in this example), you will probably have to add some extra margin.

workaround for missing pm3d corners2color feature in gnuplot

As written in the manual of Gnuplot at page 136,
Because the pm3d algorithm does not extend the colored surface outside
the range of the input data points, the 'c' coloring options will
result in pixels along two edges of the grid not contributing to the
color of any quadrangle. For example, applying the pm3d algorithm to
the 4x4 grid of data points in script demo/pm3d.dem (please have a
look) produces only (4-1)x(4-1)=9 colored rectangles.
So if I would like to plot a 4x4 pixel sized image, I can't do it in this way without missing the 4th column and row. (I would like not to modify the file.) Is there an efficent workaround for this problem?
To plot a 4x4 image which shows exactly the color rectangles specified in the data file, the splot ... with pm3d is not suited. For this one can use the image plotting style. The pm3d mode must be used e.g when the grid points are not equidistant, or for a 3D representation.
Taking the following file data.dat
1 6 8 3
2 5 4 4
9 1 1 2
5 4 3 8
a more or less minimal script would be
set autoscale fix
set xtics 1 out
set ytics 1 out
plot 'data.dat' matrix with image t ''
The result for set terminal pngcairo is:
The terminal must support plotting with image, this is the case for the most, but not for all (e.g. pstricks does not). In that case one would need to use with image failsafe.

Re-tic axis in gnuplot

I want to show how used space changes on my disk by drawing a figure with x-axis the sampling time point and y-axis storage used on disk.
However, currently, the storage used is recorded in bytes, which is not human-readable when value goes beyond GB.
So, could I re-tic axis in gnuplot? In my case, could I change the value 100000000, for example, into 100MB?
Thanks and Best Regards.
You have two main options. The first (and probably easiest) is to scale things when you plot:
plot 'datafile' using 1:($2/1e6) title 'Usage in MB'
This will plot the second data column in the file datafile with each value divided by 1e6, versus time (first column).
You can also re-tic the axes, but this is a bit less general.
set ytics ("100" 1e8)
Another option would be to use scientific notation on the y axis (as I have been doing with these big numbers above). To do that, the command is
set format y '%.2e'
This will print the y tics using scientific notation with 2 figures after the decimal point. You could also try
set format y '%.2g'
which will print the more compact of either scientific or normal notation.

Resources