Using gnuplot for files with variable names included - gnuplot

I have a data file that is set up as follows:
varName1= 1 varName2= 3
varName1= 3 varName2= 4
# and so on
Is there a gnuplot command that ignores the variable names?
I just need to plot the numbers.
I can't simply do:
plot "fileName.dat" linenumber
because the variable names are included.

In these cases I would suggest to use an external parser like awk or sed.
In your case this should work:
plot "< awk '{print $2 $3}' test.txt" w l

gnuplot will regard the variable names in your file just as another column. Simply plot fname using 2:4 will work in your example.
If you don't always have the space after "=", you can do set datafile separator '= '. (This sets " " and "=" as independend separators, not "= ".)

Related

grep a value from a file then use it as a folder name to locate a file and plot

Sorry for the confusing title. I couldn't find a better title to describe the issue. I am using gnuplot to plot some files. The files that I am trying to plot are locate in a folder titled process. Inside the process folder is another folder named 100; the structure is as below;
"plot" is the file I recall using gnuplot.
The file plot has the following line;
file='file.dat'
time = "cat file | grep 'time' | cut -d' ' -f2 | tr -d ';' | awk 'NR==1{print $1}'"
plot \
"process/".time."/speed.txt" using 1:3 with line lt 2 lc 6 title ""
So, the goal is to look for the word time in the file.dat and cut its value, which in this case is 100, and use it as a folder name where I am trying to plot the speed.txt file. However, what I have doesn't seem to work when I execute gnuplot. Anyone can help please?
Thank you very much!
First of all, to run a shell command from gnuplot and get its standard output as text, use the system function.
filter_command = "cat ..."
time = system( filter_command )
Secondly, the command string "cat ..." which you have defined will not work properly if you just pass it to system. You intend for the string file in the cat file to be expanded as cat file.dat from gnuplot's file variable.
To do that, we need one more step. There are two ways to do that.
Concatnating strings using . operator
file='file.dat'
filter_command = "cat " . file . " | grep 'time' | cut -d' ' -f2 | tr -d ';' | awk 'NR==1{print $1}'"
Using sprintf function
file='file.dat'
filter_template = "cat %s | grep 'time' | cut -d' ' -f2 | tr -d ';' | awk 'NR==1{print $1}'"
filter_command = sprintf(filter_template, file)
Script
The final script looks like this.
file='file.dat'
filter_template = "cat %s | grep 'time' | cut -d' ' -f2 | tr -d ';' | awk 'NR==1{print $1}'"
filter_command = sprintf(filter_template, file)
time = system( filter_command )
plot "process/".time."/speed.txt" using 1:3 with line lt 2 lc 6 title ""
Although gnuplot is not made for parsing files, you nevertheless can do it, sometimes with strange workarounds.
There is certainly a way to do it with the tools you mentioned: cat, grep, cut, tr and awk. However, not everybody is using Linux and has these tools at hand. Hence, if possible and although it's not optimal, I personally prefer to have "gnuplot-only" solutions which are platform-independent.
So, what the code below basically does is to "plot" the file file.dat into a dummy table line by line and everytime checking if the current line contains the string time:. If yes, write the rest of the line into the variabe myValue.
Get more information on the commands: help strstrt, help strlen, help strcol, help ternary, help datafile separator.
File: file.dat
### file.dat
This is a data file
which contains something
but also a line with
time:100
And many more things...
Maybe also some data...?
1 1.1
2 2.2
3 3.3
4 4.4
# end of file
Code:
### extract key&value from a file and use it in path
reset session
myFile = 'file.dat'
myKey = 'time:'
myValue = ''
myPath(s) = sprintf('process/%s/speed.txt',s)
getValue(line) = strstrt(line,myKey) > 0 ? myValue = line[strstrt(line,myKey)+strlen(myKey):] : myValue
# extract the value for key
set datafile separator "\n"
set table $Dummy
plot myFile u (getValue(strcol(1))) w table
unset table
set datafile separator whitespace
print myValue
print myPath(myValue)
# Your plot command would then look, e.g. like this:
plot myPath(myValue) using 1:3 with line lt 2 lc 6 title ""
### end of code
Result:
100
process/100/speed.txt

"x range is invalid" when using values with $

I'm on linux, learning gnuplot. My data.tsv looks like this:
1480420804 2016-11-29 04:00:04 -0800 foo1 $123.00 bar1
1480507205 2016-11-30 04:00:05 -0800 foo2 $124.25 bar2
1480593604 2016-12-01 04:00:04 -0800 foo3 $122.75 bar3
I'm using column #1 (seconds since epoch) as X, and column 4 (price) as Y.
This is my gnuplot script:
#!/usr/bin/gnuplot
set terminal png notransparent interlace size 640,480
set output "output.png"
set datafile separator tab
set xdata time
set timefmt "%s"
set format x "%4Y-%02m-%02d"
plot "data.tsv" using 1:4 title "Blah"
When I try to run this, I get the following error:
"./test.gp", line 9: warning: Skipping data file with no valid points
plot "data.tsv" using 1:4 title "Blah"
^
"./test.gp", line 9: x range is invalid
But if I remove all the dollar signs from the start of column 4 in my data.tsv file, then everything works.
My question: Is there a way to get gnuplot to accept or skip over the "$" in the prices in column #4?
(This is not an answer to your question but an answer to your problem so be welcome to accept another answer if somebody comes up with something better)
Just preprocess you data file before plotting and remove the $:
sed s/\$//g data.tsv >data2.tsv
I tried to do (more-or-less) what #kebs suggested, but it failed with the same "x range is invalid" error message when I was calling it like this within gnuplot:
plot "< sed s/\$//g data.tsv" using 1:4 title "Blah"
I'm not too familiar with sed, so I tried instead to use tr, and that worked like a charm.
Line 9 of my gnuplot script was this:
plot "data.tsv" using 1:4 title "Blah"
I changed it to say this:
plot "< cat data.tsv | tr --delete '$'" using 1:4 title "Blah"

How can I read only one variable from a .txt file with gnuplot?

I want to draw a function with gnuplot and I need to read the slope of the line from a .txt file.
How can I look for this variable with gnuplot?
this is the case:
My .txt file contains:
0.0121200419333 / 200497.710163
0.0150797824833 / 200496.896578
and I need to read the data from the column 1 row 2 and set it as the slope of f(x)=a*x+b and draw it
I think (please be more specific [updated at the end of the answer] if you want more specific help) you have a file (call it file for the sake of being original) like this:
This is a file with some text in it.
The slope of my curve should be slope = 6.
And some more text here.
And want to use the value slope = 6 as the slope of a function in gnuplot. You need to read in this number, for which you should use some bash utility once you know how to find it. In the very simple case above, you could look for slope = in your file with grep and then use = as a delimiter with cut and tell awk to print the first thing it finds:
grep "slope =" file | cut -d "=" -f2 | awk '{print $1}'
Now go to gnuplot and use this as a variable:
slope = `grep "slope =" file | cut -d "=" -f2 | awk '{print $1}'`
plot slope*x
And this is what you get in my example, where slope = 6:
You'll probably need to adapt this to your problem but unless you include more details it's impossible to give you better guidance.
For the specific case where you want the first record on the second line:
a = `awk 'NR==2 {print $1}' file`
plot a*x

Can the string for "set title" be obtained from a file?

I'm using Gnuplot with scripts and data files.
In my script there is a command;
set title "blah title here"
Is it possible to have that string taken from a data file? e.g. such that I can use a single script with many data files, because the data file will contain the title for the plot.
I'm not sure if this would be easy to do in pure gnuplot, but here is a solution using a wrapper bash script. You would use the script by calling plotscript.sh data.dat at the command line.
#!/bin/bash
my_title=$(head -n 1 $1 | sed 's/^# \(.*\)/\1/')
echo "set terminal postscript enhanced color
set output 'plot.eps'
set title '$my_title'
plot '$1' u 1:2" | gnuplot
To make the script usable put the code in a textfile and run chmod +x on it. If you tell me what format the title is in I can try to tailor the script to match that. This script assumes that the title is the first line of the data file in this type of format:
# mytitle
1 4
2 5
3 2
you can use backtic substitution...e.g.
set title "`head -1 datafile.dat`"
However, that doesn't quite get what you want since the backtic substitution is done prior to string operations (You can't specify the datafile name as a string). However, Macros are expanded prior to backtic substitutions.
My test datafile looked like:
"this is the title"
10 20
20 30
30 40
And my test script looked like:
DATAFILE="datafile.dat"
set macro
TI='`head -1 '.DATAFILE.'`' #macro: Single quotes are important here to prevent expansion of backtics.
set title #TI
plot DATAFILE u 1:2 title columnhead(1)
Note that if your title isn't enclosed in double quotes in the datafile, you'll need to add
them so that the resulting set title command is valid. (You can either add them to the macro, or to the datafile)
Even if this is rather late and the OP's account doesn't exist anymore, I need to add an answer, because it is simply not true that you cannot extract a title from a datafile with gnuplot only.
You can run stats (check help stats) without actually being interested in statistics but just for extracting the title.
You limit the data to the line of interest via every (check help every).
This works for gnuplot 4.6.0 (March 2012).
For gnuplot>=4.6.0 you can set a character as datafile separator (check help datafile separator). Take a character which doesn't appear in the line with the title. For gnuplot>=4.6.0 you can set datafile separator "\t" or for gnuplot>=5.0.0 you can also set datafile separator "\n".
Data: SO10968529.dat
# This is a commented line
"Line2: This is a uncommented line in double quotes"
"Line3: my Title"
Line5: This is a title without quotation marks
"Line6: Another title"
# x y
1 5.0
2 3.0
3 4.0
4 2.0
# end of data
Script:
### read title from datafile
reset
FILE = "SO10968529.dat"
set multiplot layout 1,2
set datafile separator "\t"
stats FILE u (myTitle=strcol(1),0) every ::0:0:0:0 nooutput
set datafile separator whitespace
set title myTitle
plot FILE u 1:2 w lp pt 7 lc rgb "red"
set datafile separator "\t"
stats FILE u (myTitle=strcol(1),0) every ::0:1:0:1 nooutput
set datafile separator whitespace
set title myTitle
plot FILE u 1:2 w lp pt 7 lc rgb "blue"
unset multiplot
### end of script
Result:

Shell script - new line after comma?

I have a shell script I wrote that grabs a list of names from a location, and each name is separated by a comma , <-- I was wondering if there is anything I can write to make the list of names that gets stored in the text file to indent to a new line after each comma?
For example the list of names that gets stored in the text file look like this:
"Red", "Blue", "Green"
And I want them to look like this:
Red
Blue
Green
The data gets pulled from html code off a website so they have quotations and commas around them, if it's possible to at least format them to a new line, that would be great. Thanks if you help.
Assuming the comma separated date is in the variable $data, you can tell bash to split it by setting $IFS (the list separator variable) to ', ' and using a for loop:
TMPIFS=$IFS #Stores the original value to be reset later
IFS=', '
echo '' > new_file #Ensures the new file is empty, omit if the file already has contents
for item in $data; do
item=${item//'"'/} #Remove double quotes from entries, use item=${item//"'"/} to remove single quotes
echo "$item" >> new_file #Appends each item to the new file, automatically starts on a new line
done
IFS=$TMPIFS #Reset $IFS in case other programs rely on the default value
This will give you the output in the desired format, albeit with a leading blank line.
Just use sed.
% echo '"Red", "Blue", "Green"' | sed -e 's/\"//g' -e 's/, /\n/g'
Red
Blue
Green
awk -F, '{for(i=1;i<=NF;i++){ print $i;}}'
see below command line:
kent$ echo '"Red", "Blue", "Green"'|sed 's/, /\n/g'
"Red"
"Blue"
"Green"
\n is for new line. Like "Red\n", "Blue\n", "Green\n"

Resources