1
votes

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

1
After your comment to my answer and your modified question I'm even more confused than before. Could you maybe please describe in words what you have and what you want? I don't know awk, so my guess would be that you have a list of files in the same directory and want to extract from each of them the value of the 5th row of the 1st column and with these values normalize the 2nd column of other related files which are in different directories. Please correct me if I'm wrong. This could also be achieved without using awk. - theozh
You're wright. I corrected the first message to explain it in detail. awk is a bash command to get the value of Utau. Could you explain me how to get the value of Utau without using awk knowing that the values of Utau (Utaufwal055wal055 and Utaufwal055wal055_c2) are localised in separated files (file_fwal055wal055 and file_fwal055wal055_c2) which are different from the plot files "stat_coupe" ? I thought to : stats "file_fwal055wal055" every ::5::5 u $1 nooutput But I do not see how to put it inside the for loop in order to specify the iteration fwal055wal055 or fwal055wal055_c2. - Martin7

1 Answers

0
votes

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