GNUPLOT : A better way of piping data into gnuplot script - shell

I have a gnuplot script like this (simplified)
reset session
set terminal pngcairo enhanced font "Times,25" size 800,400
filename = ifilename
stats filename nooutput
N = STATS_columns
M = STATS_records
set angles degrees
set size square 1.25,1
set output ofilename
# does some stuff
...
...
...
set parametric
plot \
for [i=2:N] filename u (posX($0, column(i))):(posY($0, column(i))) w p ps 1.2 pt 7 lc rgb lcolor(i-2)
What I want to do is define ifilename (input file) and ofilename (output file) via a shell script.
So I thought the -e command might just be the one for the job.
So for the gnuploat part of the script I wroth this
gnuplot -e "ifilename='data/points_data1.dat'; ofilename='plot1'" chart.gp
but it threw the error
"chart.gp" line 8: undefined variable: ifilename
which refers to this line
filename = ifilename
I thought maybe that's because it's having some trouble parsing two = signs so I removed that line and rewrote my shell script like this
gnuplot -e "filename='data/points_data1.dat'; ofilename='plot1'" chart.gp
but this time it threw the following error
"chart.gp" line 8: undefined variable: filename
What actually worked was this
echo "data/points_data$i.dat" | gnuplot chart.gp
where I replaced the line filename = ifilename with
FILE = system("read filename; echo $filename")
and every instance of filename with FILE in .gp script.
But I'm not sure how to use that syntax to also define the output file.
So I was wondering, is there a better way of piping shell input into gnuplot script?

Your original command almost worked. The invocation
gnuplot -e "ifilename='data/points_data1.dat'; ofilename='plot1'" chart.gp
correctly defined the input and output file names. But then you clobbered them inside the chart.gp script by issuing the command
reset session
which clears all variable definitions including the ones you specifically wanted. Remove that line from the script and you should be fine. If the intent of the "reset session" command was to make sure that no system-wide or private initialization file is used, then replace it with a "-d" on the command line:
gnuplot -d -e "ifilename='data/points_data1.dat'; ofilename='plot1'" chart.gp

FILE = system("read filename; echo $filename")
is actually fine.
If you want to pipe the output to some file you can just omit set output "something.png"
and instead you could just send the .png output directly to stdout by running a script like this
#!/usr/bin/env gnuplot
reset session
set terminal pngcairo enhanced font "Times,25" size 800,400
...
then you can pipe that output to a .png file like this
./chart.gp > mypng.png
So the final command would look something like this
echo "data/points_data$i.dat" | gnuplot chart.gp > plot$i.png

Related

Unexpected EOF?

I have been trying to create a graph in GNUPLOT using Bash. As I understand it, my following code should input the following lines into the gnuplot command until it reaches an EOF. I then send the "set" lines and "plot" line to gnuplot and follow it up with an EOF, which should end the input into the gnuplot command.
for FILE in ./tempFolder*.done; do
gnuplot <<EOF
set datafile separator ","
set xlabel "Hour"
set ylabel "Temperature"
set term png
set output "${FILE}.png"
plot "${FILE}" using 1:3 with errorbars title "Temperature/Time"
EOF
done
However, I get the following error message: "Syntax error: end of file unexpected (expecting "done")"
When I type try this in Bash outside of the script, it seems to work properly. Anyone have any pointers as to what I'm doing wrong?
You cannot indent the closing EOF; it has to be at the beginning of the line.
If you use <<-EOF instead of <<EOF, the shell will strip any leading tabs from each line of the here document, including the closing EOF.

Echo variable defined as result from command line resets cursor position

If I run this script:
#!/bin/bash
HOSTNAME=$(< ds.tmp)
echo "Hello${HOSTNAME}!"
TEST="1.2.3.4"
echo "Hello${TEST}!"
With the contents of ds.tmp only an ip address (say 1.2.3.4), the result is:
!ello1.2.3.4
Hello1.2.3.4!
So after I print a variable that is assigned by a $(...), the cursor position is reset and it overwrites all text.
Why is this? I have looked everywhere but cannot find a reference this anywhere...
Your ds.tmp file has CR-LF as its line breaks. As a result, ${HOSTNAME} contains 1.2.3.4\r, not just 1.2.3.4.
Unix text files should just use LF as their line breaks. Use dos2unix to fix it.
Try this:
HOSTNAME=$(tr -d "\r" < ds.tmp)

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.

sed Command adding space at start of line

I am trying to use the sed program to replace two lines of text in a config file using bash variables, the line replacement works however there is a extra space at the start of the line.
My commands are as follows:
replacement="computer_id = $server_ref"
(where $server_ref is a user entered variable)
and then:
sed "/computer_id/c \ ${replacement}" -i slapos.cfg
The other line being replaced uses just the same commands just changes a different variable in the config file.
The ouput of this change looks like
computer_id = something
when it should be
computer_id = something
which results in crashing the program using the config as it is not excepting that space.
Might be better to do it like this:
sed -i "s/^\\(computer_id = \\).*/\\1${server_ref}/" slapos.cfg
The program which reads the configuration file isn't very robust if extra whitespace crashed it.

Editing a Perforce label's description through a script

I want to modify an existing Perforce label using a script that I can invoke automatically. Currently I know how to do it using the text editor option:
p4 label <label-name>
This opens up a temporary file in my default text editor, I can then enter a description, save the file and close - updates the label successfully.
However, I want to be able to do this automatically using a script. I will have variables that can be used to form my description.
I can use either a shell script or a bat script (on Windows but have Cygwin).
Perforce command line documentation on labels can be found here, but it's not helping me.
Any ideas?
You would do something along those lines:
p4 label -o > label.txt
sed -i 's/old/new/g' label.txt # or any other automated method to do the modification
p4 label -i < label.txt
sed can be used to (easily) replace text on a single line, but perl's syntax is easier when dealing with the multi-line Description field.
The following bash code exports the label definition for label NAME_OF_CURRENT_LABEL, creates a new label definition of MY_NEW_LABEL and then sets the description to MY_NEW_DESCRIPTION. Note that that it assumes that the description text exists, and is on a single line, below the "Description:" line above. To just update the description, remove the sed line.
p4 label -o NAME_OF_CURRENT_LABEL | # Output label spec for NAME_OF_CURRENT_LABEL \
sed 's/^Label:.*/Label: MY_NEW_LABEL/' | # Update label name to MY_NEW_LABEL \
perl -pe "$/='',s/^Description:\n(.*)$/Description:\n\tMY_NEW_DESCRIPTION\n/s" | # Update one-line description to MY_NEW_DESCRIPTION \
p4 label -i # Create new label with output from pipe

Resources