Gnuplot tic frequency - bash

For a very large data-set, how can gnuplot be used to only put tic marks/labels on the x axis for just the first and last data point?

With gnuplot 4.6 and up, you can use the commands
stats 'data.dat'
set xtics \
(sprintf("%.2g",STATS_min_x) STATS_min_x, \
sprintf("%.2g",STATS_max_x) STATS_max_x)
plot 'data.dat'
With other versions of gnuplot, you can use this similar sequence of commands:
# this setting makes sure we don't make an output right away
set terminal unknown
plot 'data.dat'
set xtics \
(sprintf("%.2g",GPVAL_DATA_X_MIN) GPVAL_DATA_X_MIN, \
sprintf("%.2g",GPVAL_DATA_X_MAX) GPVAL_DATA_X_MAX)
set terminal <actual terminal>
replot
The set xtics command takes comma-separated pairs of strings with data values, all inside parentheses.
(Here I assume you want the minimum and maximum, not the first and last, data points.)
For more info you can run these at the gnuplot command line:
help set format
help set stats
show variables all

I'm adding another answer because my other one really answered a different question, but may be useful. To answer the question,
How to mark the x tics for the first and last data points?
here is my method:
#!/usr/bin/env gnuplot
set terminal png
set output 'test.png'
# define a function to get the first and last values.
# this assumes the file has not changed since first running 'stats',
# (and contains at least one data point)
# `plot/stats 'data.dat' using (firstlast($x))`
# should be interchangable with
# `plot/stats 'data.dat' using x
# that is, the resulting variables should be the same
firstlast(x) = ($0==0) ? (first=$1, last=$1, $1) : (last=$1, $1)
# run stats to find the first and last values
# just on x data column
stats 'data.dat' u (firstlast($1)) nooutput
# set the x tics to the first and last x points
set xtics \
(sprintf("%.2g (first)", first) first, \
sprintf("%.2g (last)", last) last)
print first
print last
plot 'data.dat'
I used this example data file:
data.dat
1 1
2 2
3 3
4 2
0 3
and got this output:

Related

gnuplot format xK or xM

For the format of x-axis, current I am using the following command in pngcairo terminal:
set format x "%.sK"
Which recognizes numbers from 100K to 900K but when it gets to 1 million it prints "1K" instead of "1000K".
what is the command to automatically set the label to "xK" before 1 million and to "xM" after 1 million?
These kind of labels are controlled by gnuplot's own format specifiers (see doc for gprintf):
set format x '%.s%c'

gnuplot read data with unit

I have some data that looks as follow:
test 1 8377.0 ns 105.84 32
test 2 5394.4 ns 66.39 64
test 3 3962.1 ns 45.44 64
test 4 3350.9 ns 70.99 128
When trying to plot this, gnuplot has problems reading "8377.0 ns" because of the unit "ns".
Is there a trick to make gnuplot ignore "ns" and just take the value eg: "5394.4 ns" = "5394.4"
UPDATE:
script I use:
set terminal pngcairo size 800,600 enhanced font 'Verdana,10'
set output './graph.png'
plot "<(sed -n '6,$p' data/data_32x.txt)" using 2:3:4 with errorlines
Thanks
no tricks should be needed here, columns are delimited by whitespace by default:
The command set datafile separator tells gnuplot that data fields in
subsequent input files are separated by a specific character rather than by
whitespace. The most common use is to read in csv (comma-separated value)
files written by spreadsheet or database programs. By default data fields
are separated by whitespace.
This means that the numbers 1,2,3,4 will be loaded as column no. 2, numbers 8377.0,... in column no. 3, and finally numbers 105.84,... in column no. 5
You can distinguish between spaces and tabs if you want:
set datafile separator "\t"
plot "file.dat" using 2:3:4 with errorlines
The " ns" part of the third column is silently discarded when parsing the number from it.

Bash script for gnuplot

I have a c++ code that generates every time a variable number of ".txt" file.
I am using a bash script that loads the txt files and send them to a gnuplot script. Then I have to plot in the same figure always the same 2 columns of each of them (representing a altitude vs time plot).
My problem is that the x coordinate (1st column of txt files) does not finish always at the same value and, when the last value of x coordinate is not zero,I need to insert a cross in the gnuplot plot. Do you have an idea about how to do it?
This is how I am plotting the multiple files
plot for [object in objectnames] object.".txt" using 1:2 w l title object
where "objectnames" is a string with all the filenames sent by the BASH
Now, for plotting the CROSSES, I thought about two ways:
Send a array of coordinates to the gnuplot script and then set some label but GNUPLOT does not like arrays and I cannot create a variable number of label in this way.
The alternative is to read somehow the txt file inside the gnuplot script but I have no idea how to do it.
Thanks for the help
EDIT
BASH SCRIPT
export DATA_DIR=${1:-/home/../output}
export objectname
space=" "
OUT_FILES="$(find -L $DATA_DIR -name '*_Trajectory.txt')"
for file in $OUT_FILES; do
fig=$(basename "$file")
objectID=$(echo $fig| cut -d'_' -f 1)
# filenames concatenation
objectname=$objectname$objectID$space
done
export figNameAltitude="${file/${fig}/altitudePlot.png}"
gnuplot -e "folder='${DATA_DIR}';objectnames='${objectname}';figName='${figNameAltitude}';lineWidth='${linewidth}'" altitudePlot.gp
GNUPLOT SCRIPT ( I avoid to insert all the lines regarding the title, axis and so on)
plot for [object in objectnames] folder.'/'.object."_Trajectory.txt" using 1:2 w l lw lineWidth title object
This might help
set title "Energy vs. Time for Sample Data"
set xlabel "Time"
set ylabel "Energy"
plot "d1.dat" with lines
pause -1 "Hit Enter to continue"
execute the script file as **$**gnuplot filename
click here for more details

Heat map from multiple files with cat, awk or sed (bash)

I'm dealing with multiple files and I want to plot a heat map every ::121::600 using 3:25:43 from those files.
Is there a way to combine all files on the fly to get a heat map with commands like:
set dgrid3d
splot '< cat data1.csv data2.csv data3.csv data4.csv' every ::121::600 using 3:25:43 w pm3d
I tried this but It seems that only the data from data1.csv shows up in the plot. Am I doing something wrong with ' or , ? Is awk, or sed an option?
i know the option set table but I would prefer a clean bash command option to directly make this on the fly.
Is there a good resource to look up all the unix commands with some gnuplot demos?
Thanks so far for the response:
so the 'are for the plot command: e.g. plot 'data1.csv' using 1:2 w l would print row 1 against row 2 from the data1 file with lines. that's why I used to 'in the command. I found this Site where hey explain some bash commands for gunplot but I still haven't found what I'm looking for
Thank you for the great respones and help regarding my problem:
This worked:
plot '< for i in data1.csv data2.csv data3.csv data4.csv; do cat "$i"; echo; done' every ::121::600 using 3:25:43 w pm3d
Worth mentioning that I do had to ad the "around the $ijust as vagoberto proposed
and this worked the same way:
plot '< awk "FNR==1{print \"\"}1" data1.csv data2.csv data3.csv data4.csv' every ::121::600 using 3:25:43 w pm3d
both worked on my Mac OSX Terminal environment, and on Wind 7 with gnuWin32 Package installed.
The every ::121::600 command is telling gnuplot to take the data from lines 121 to 600 (counting from 0) on every block, and not on every files. You need to pre-process the data to create blocks (put a single line between each data).
Consider the following two data files:
#data1.dat #data2.dat
1 2 1.5 2.5 # line 0
3 4 3.5 4.5 # line 1
5 6 5.5 6.5 # line 2
and try to plot with every ::2::2 (i.e. plot only line 2).
The following instruction creates a single block, so gnuplot will plot only the point (5,6):
cat data1.dat data2.dat
1 2
3 4
5 6
1.5 2.5
3.5 4.5
5.5 6.5
The following instruction will create a block for each datafile, so that gnuplot will plot the points (5,6) and (5.5,6.5):
for i in data*.dat; do cat $i; echo; done
1 2
3 4
5 6
1.5 2.5
3.5 4.5
5.5 6.5
You will get a similar result by using awk 'FNR==1{print ""}1' data*.dat.
In summary, the following should work:
plot '< for i in data*.dat; do cat $i; echo; done' every ::2::2 using 1:2
# or
plot '< awk "FNR==1{print \"\"}1" data*.dat' every ::2::2 using 1:2

Gnuplot: One plot per file

I'm trying to plot the 1st and 3rd columns of multiple files, where each file is supposed to be plotted to an own output.png.
My files have the following names:
VIB2--135--398.6241
VIB2--136--408.3192
VIB2--137--411.3725
...
The first number in the file name is an integer, which ranges from 135-162. The second number is just a decimal number and there is no regular spacing between the values.
Basically I want to do something like this
plot for [a=135:162] 'VIB2--'.a.'--*' u 1:3 w l
although this doesn't work, of course, since the ' * ' is just the placeholder I know from bash and I don't know, if there is something similar in gnuplot.
Furthermore, each of the files should be, as already said above, plotted to its own output.png, where the two numbers should be in the output name, e.g. VIB2--135--398.6241.png.
I tried to come up with a bash script for this, like (edited):
#!/bin/bash
for file in *
do
gnuplot < $file
set xtics 1
set xtics rotate
set terminal png size 1920,1080 enhanced
set output $file.png
plot "$file" u 1:3 w l
done
but I still get
gnuplot> 1 14 -0.05
^
line 0: invalid command
gnuplot> 2 14 0.01
^
line 0: invalid command
...
which are actually the numbers from my input file. So gnuplot thinks, that the numbers I want to plot are commands... ?? Also, when the end of the file is reached, I get the following error message
#PLOT 1
plot: an unrecognized command `0x20' was encountered in the input
plot: the input file `VIB2--162--496.0271' could not be parsed
I've seen a few questions similar to mine, but the solutions didn't really work for me and I cannot add a comment, since I do not have the reputation.
Please help me with this.
gnuplot < $file starts gnuplot and feeds it the content of $file as input. That means gnuplot will now try to execute the commands in the data file which doesn't work.
What you want is a "here document":
gnuplot <<EOF
set xtics 1
set xtics rotate
set terminal png size 1920,1080 enhanced
set output $file.png
plot "$file" u 1:3 w l
EOF
What this does is: The shell reads the text up to the line with solemn EOF, replaces all variables, puts that into a temporary file and then starts gnuplot feeding it the temporary file as input.
Be careful that the file names don't contain spaces, or set output $file.png will not work. To be safe, you should probably use set output "$file.png" but my gnuplot is a bit rusty.

Resources