gnuplot with muliple columns using loop - shell

I have a number of files (having 10 columns each) with following order:
file_001.txt, file_002.txt, file_003_txt,
file_021.txt, file_023.txt, file_023.txt,
file_041.txt, file_042.txt, file_043.txt,
file_061.txt, file_062.txt, file_063.txt,
file_081.txt, file_082.txt, file_083.txt,
I would like to plot each file with different line. e.g. using 1:2, using 1:3, using 1:5, using 1:8. I can not able to make a loop to call different columns. My following script is not working for k field
plot for [k=2, 3, 5, 8] for [j=0:8:2] for [i=1:3] 'file_0'.j.i.'.txt' u 1:k;

Use for [k in "2 3 5 8"] if you have a list rather than a range.

If j can be > 9, you should set up a function
fname(j,i) = sprintf("name%02.f%.f",j,i)
to get proper file names.
Format string "%02.f" means float (f), no digits after the comma (.), minimum two postions (2), fill empty space with zeroes.
print fname(2,3)
name023
print fname(13,3)
name133
print fname(113,3)
name1133
These are libc format strings, they are not documented inside the gnuplot docs, but there are many sources in the web.

Related

gnuplot : variable paths to data file in a for loop

I would like to plot multiple curve on the same graph using a for loop. Each data file (named stat_coupe) is located in a different folder (fwal055wal055/rep16/ and fwal055wal055_c2/rep20/). fwal055wal055 and fwal055wal055_c2 correspond to names of simulation. First, I need to get a previous result, a single number (Utau), in other files (named file_fwal055wal055 and file_fwal055wal055_c2). This is successfully done thanks to the command awk. The result depend on the file: Utaufwal055wal055=10.5 and Utaufwal055wal055_c2=12.2.
Then I need to divid the 1st column of the file stat_coupe corresponding to the path fwal055wal055/rep16/ by the value of Utaufwal055wal055 and do the same thing for the file stat_coupe corresponding to the path fwal055wal055_c2/rep20/ with the value of Utaufwal055wal055_c2. Moreover, each plot should have a specific format which depend on the type of simulation run (fwal055wal055 or fwal055wal055_c2).
The presented problem is reduced to 2 simulations fwal055wal055 and fwal055wal055_c2 and 1 plot but I have about 20 simulations and 15 various graphs to plot that is why I would like to use the for loop.
To summary at each iteration I have:
a specific format,
a specific path,
a specific value of Utau
I want to indicate the wright format, path and value of Utau at each iteration of the for loop. The solution I propose below successfully permits to obtain the value of Utau for each simulation but the code #path_.i and #format_.i does not work.
#!/bin/bash
for elem in fwal055wal055 fwal055wal055_c2;
do
Utau[${elem}]=$(awk 'FNR==5{print $1}' file_$elem)
done
gnuplot -persist <<-EOFMarker
format_fwal055wal055='pt 1 ps 1.0 lc 0 title "WALE"'
format_fwal055wal055_c2='pt 2 ps 1.0 lc 0 title "WALE c2"'
path_fwal055wal055='"fwal055wal055/rep16/stat_coupe"'
path_fwal055wal055_c2='"fwal055wal055_c2/rep20/stat_coupe"'
list="fwal055wal055 fwal055wal055_c2"
plot for [i in list] #path_.i u 1:(\$2/${Utau[${i}]}) #format_.i
EOFMarker
I would like to obtain something equivalent to:
plot #path_fwal055wal055 u 1:(\$2/${Utau[${i}]}) #format_fwal055wal055,\
#path_fwal055wal055_c2 u 1:(\$2/${Utau[${i}]}) #format_fwal055wal055_c2
Can someone help me to solve this issue ?
Thank you very much,
Martin
Check help sprintf, help words and help word.
I would create two strings with the same number of items and then combine them with sprintf(). From gnuplot 5.2 on you could also do it with arrays.
# Version 1
PATHS = '"fwal055wal055/rep16/stat_coupe" "fwal055wal055_c2/rep20/stat_coupe"'
FILES = "fwal055wal055 fwal055wal055_c2"
plot for [i=1:words(FILES)] sprintf("%s_%s",word(PATHS,i),word(FILES,i)) u 1:2
or you could define a function for your filenames to keep the plot command short and readable.
# Version 2
PATHS = '"rep16/stat_coupe" "rep20/stat_coupe"'
FILES = "fwal055wal055 fwal055wal055_c2"
myFilename(i) = sprintf("%s/%s_%s",word(FILES,i),word(PATHS,i),word(FILES,i))
plot for [i=1:words(FILES)] myFilename(i) u 1:2
Addition (after some clarifications...)
If I understand your question now correctly, the following code should do the job.
For the extraction of the UTAUS you do a separate loop before plotting and store the extracted values in a string. During plotting you get these values back via word(UTAUS,i). Since you do the mathematical operation column(2)/word(UTAUS,i), gnuplot will interpret them as number. Check help words, help word, help sprintf, help every.
Code:
### extract and normalize in a loop with individual files and directories
reset session
FILES = 'fwal055wal055 fwal055wal055_c2'
DIRS = 'rep16 rep20'
TITLES = '"WALE" "WALE c2"' # if you have spaces you need to put it into double quotes
UTAUS = ''
# define functions for better readability
myExtractionFile(i) = sprintf("file_%s",word(FILES,i))
myDataFile(i) = sprintf("%s/%s/stat_coupe",word(FILES,i),word(DIRS,i))
myTitle(i) = word(TITLES,i)
# define point or line appearance. Add more if you have more files
set style line 1 pt 1 ps 1.0 lc 0
set style line 2 pt 2 ps 1.0 lc 1
# extract the UTAUs
do for [i=1:words(FILES)] {
set table $Dummy
plot myExtractionFile(i) u (utau=$1) every ::4::4 w table # extract value row 5, column 1 (not counting header lines)
unset table
UTAUS = UTAUS.sprintf(" %g",utau) # append the extracted value as string
}
plot for [i=1:words(FILES)] myDataFile(i) u 1:(column(2)/word(UTAUS,i)) ls i title myTitle(i)
### end of code

Shell Scripting: How to choose a randow number from three values?

I want to write a Shell Script.
The task is, that I have to pick a random number.
But the numbers must be one of the following three.
5,10,15
So if "let's say" 'a' is smaller than 5, I have to pick randomly a number of 5,10 or 15.
How can I do that?
Here's a hint to help you do this.
First, create a variable (array) containing your 3 values : arr = (5 10 15).
Then, create a random number called index and floor it to 2.
Finally, retrieve the number ${arr[$index]}.
Try the following
#!/bin/bash
arr=(5 10 15);
picked_element=${arr[$(($RANDOM % 3))]};
echo $picked_element;

Can I calculate something inside a for loop and then plot those values on the same graph?

I have the following code, which plots 4 lines:
plot for [i=1:4] \
path_to_file using 1:(column(i)) , \
I also want to plot 8 horizontal lines on this graph, the values of which come from mydata.txt.
I have seen, from the answer to Gnuplot: How to load and display single numeric value from data file, that I can use the stats command to access the constant values I am interested in. I think I can access the cell (row, col) as follows:
stats 'mydata.txt' every ::row::row using col nooutput
value = int(STATS_min)
But their location is a function of i. So, inside the plot command, I want to add something like:
for [i=1:4] \
stats 'mydata.txt' every ::(1+i*10)::(1+i*10) using 1 nooutput
mean = int(STATS_min)
stats 'mydata.txt' every ::(1+i*10)::(1+i*10) using 2 nooutput
SE = int(STATS_min)
upper = mean + 2 * SE
lower = mean - 2 * SE
and then plot upper and lower, as horizontal lines on the graph, above.
I think I can plot them separately by typing plot upper, lower but how do I plot them on the graph, above, for all i?
Thank you.
You can create an array and store the values in it, then using an index that refers to the value's position in the array you can access it inside a loop.
You can create the array as follows:
array=""
do for [i=1:4] {
val = i / 9.
array = sprintf("%s %g",array,val)
}
where I have stored 4 values: 1/9, 2/9, 3/9 and 4/9. In your case you would run stats and store your upper and/or lower variables. You can check what the array looks like in this way:
gnuplot> print array
0.111111 0.222222 0.333333 0.444444
For plotting, you can access the different elements in the array using word(array,i), where i refers to the position. Since the array is a string, you need to convert it to float, which can be done multiplying by 1.:
plot for [i=1:4] 1.*word(array,i)
If you have values stored in a data file, you can process it with awk or even with gnuplot:
array = ""
plot for [i=1:4] "data" every ::i::i u (array=sprintf("%s %g",array,$1), 1/0), \
for [i=1:4] 1.*word(array,i)
The first plot instance creates the array from the first column data entries without plotting the points (the 1/0 option tells gnuplot to ignore them, so expect warning messages) and the second plot instance uses the values stored in array as variables (hence as horizontal lines in this case). Note that every takes 0 as the first entry, so [i=1:4] runs from the second through to the fifth lines of the file.

write cell array into text file as two column data

I have two different variables which are stored as cell arrays. I try to open text file and store these variables as two column arrays. Below is my code, i used \t to seperate x and y data, but in the output file, the x data is written first which is followed by the y data. How can I obtain two column array in the text file?
for j=1:size(data1,2)
file1=['dir\' file(j,1).name];
f1{j}=fopen(file1,'a+')
fprintf(f1{j},'%7.3f\t%20.10f\n',x{1,j}',y{1,j});
fclose(f1{j});
end
Thanks in advance!
You can use dlmwrite as well to accomplish this for numeric data:
x = [1;2;3]; y = [4;5;6]; % two column vectors
dlmwrite('foo.dat',{x,y},'Delimiter','\t')
This produces the output:
1 4
2 5
3 6
Use a MATLAB table if you have R2013b or beyond:
data1 = {'a','b','c'}'
data2 = {1, 2, 3}'
t = table(data1, data2)
writetable(t, 'data.csv')
More info here.

Numpy savetxt loop

Using Numpy, I am going to split an array of dimension (557124,2), dtype = "S10", in 6 subarrays using:
sub_arr = np.split(arr, 6)
Now I would like to use a for loop on savetxt and save the 6 subarrays to 6 .txt files.
I tried:
for i in sub_array:
np.savetxt(("Subarray", i, ".txt"), sub_array[i], fmt='%s')
There are 2 problems:
It's incorrect to say in sub_array. I should use range(5) but I want to make it adaptable to any number of sub arrays.
I thought I could use a sort of "paste" as in R when I did ("Subarray", i, ".txt"). Is there anything alike in Numpy?
Any idea?
From what I've understood
sub_arr = np.split(arr, 6)
returns a list of 6 numpy arrays. Then you can use enumerate to get each array and its index
fname_template = "Subarray.{i}.txt"
for i, sarr in enumerate(sub_arr):
np.savetxt(fname_template.format(i=i), sarr, fmt='%s')
To create the file name I've used the new string formatting. Otherwise you can concatenate strings with + as "Subarray."+str(i)+".txt", but you have to make sure that all the elements that you concatenate are strings.

Resources