2 votes

Appel de Gnuplot à partir de GAWK et Bash scripts, trace seulement le premier tracé

Ok, alors voici l'affaire. Je commence ma thèse de premier cycle en science computationnelle des matériaux et j'essaie de mettre quelques scripts ensemble pour aider à préparer l'analyse des données.

J'ai préparé un script GAWK qui va essentiellement prendre des données (disposées en 4 colonnes) et en capturer deux pour les tracer dans GNUPLOT. Pour y parvenir, je lis le fichier de données qui contient plusieurs pas de temps et leurs données associées, je divise le fichier en fichiers .dat individuels pour chaque pas de temps.

A partir de là, je génère simplement une entrée de base script pour GNUPLOT et je trace chaque pas de temps comme ils se produisent dans le fichier de données.

Le problème est que, pour une raison quelconque, tous les graphiques générés sont exactement les mêmes (dans ce cas, il s'agit toujours du premier pas de temps), mais ils sont enregistrés avec le pas de temps correct.

J'ai déjà parcouru et suivi chaque variable/filename tout au long du script et j'ai finalement déterminé que le problème est en quelque sorte avec GNUPLOT étant appelé à partir d'un script. J'ai retiré ma commande système et écrit un court script bash qui appelle gnuplot à partir d'une boucle for :

#!/bin/bash
for file in ./*gnu
do
   gnuplot $file
done

Et cela cause toujours le même problème où toutes les intrigues sont les mêmes. J'ai ensuite exécuté la commande gnuplot *gnu à partir de la ligne de commande dans le répertoire contenant les fichiers .gnu et cela a fonctionné.

Je suppose que je me demande s'il y a un tampon que je dois vider ou si je manque quelque chose ?

Le script de GAWK est donné ci-dessous. Je suis encore novice dans ce domaine, donc si vous souhaitez commenter le script avec une critique constructive, je l'apprécierais grandement aussi.

#!/opt/local/bin/gawk -v inputf=$1 -f                                                   

# Write gnuplot files and plot RDF data                                                 
function plot_rdf(timestep, Load_RDF_dat)
{
# Set number of digits in filenames to 6 so data is organized                           
    if (timestep < 10){
        pad_timestep="00000"timestep;
    }
    else if (timestep < 100){
        pad_timestep="0000"timestep;
    }
    else if (timestep < 1000){
        pad_timestep="000"timestep;
    }
    else if (timestep < 10000){
        pad_timestep="00"timestep;
    }
    else if (timestep < 100000){
        pad_timestep="0"timestep;
    }
    else{
        pad_timestep=timestep;
    }

# Give output filenames                                                                 
       gnu_file="plot_RDF_"pad_timestep".gnu";
       png_file="RDF_"pad_timestep".png";

# Create input files for gnuplot                                                        
       print "set output \""png_file"\"" >> gnu_file;
       print "set terminal png" >> gnu_file;
       print "plot './"Load_RDF_dat"' u 1:2" >> gnu_file;
       close(gnu_file);
       system("gnuplot "gnu_file);
}

# Main part of script                                                                   
{
# Parse the RDF data and save it to GNUPLOT readable files                              
    while(getline < inputf){
       if ($1 == "#"){
           # skips the three commented header lines                                     
           next;
       }
       else if (NF == 2){
           timestep=$1;
           bin_num=$2;
           print "Reading timestep "timestep;
           RDF_dat="RDF_"timestep".dat";
           next;
       }
       else if (NF == 4){
           print $2" "$3 >> RDF_dat;
           if ($1 == bin_num){
               plot_rdf(timestep, RDF_dat);
               close(RDF_dat);
           }
           next;
       }
    }
    close(inputf);
    close(RDF_dat);
 }

Voici un extrait du fichier de données que je lis :

# Time-averaged data for fix rdf
# TimeStep Number-of-rows
# Row c_allrdf[1] c_allrdf[2] c_allrdf[3]
500 100
1 0.005 0 0
2 0.015 0 0
3 0.025 0 0
4 0.035 0 0
5 0.045 0 0
6 0.055 1.16597 0.00133333
7 0.065 2.08865 0.00466667
8 0.075 1.56958 0.008
9 0.085 0.733433 0.01
10 0.095 0.587288 0.012
600 100
1 0.005 0 0
2 0.015 0 0
3 0.025 2.79219 0.000666667
4 0.035 2.86766 0.002
5 0.045 0 0.002
6 0.055 0.582985 0.00266667
7 0.065 2.08865 0.006
8 0.075 0.62783 0.00733333
9 0.085 0.488955 0.00866667
10 0.095 1.17458 0.0126667

Il y a généralement 100 ensembles de données dans chaque section de pas de temps, mais je me suis dit que j'allais raccourcir ici pour que vous compreniez l'idée.

0voto

mgilson Points 92954

Je ne suis pas sûr de pouvoir répondre à votre question - cependant, je peux vous dire que lorsque j'ai légèrement modifié votre fichier de données, il a (semblé) fonctionner parfaitement pour moi.

Voici ma version modifiée de votre fichier de données :

# Time-averaged data for fix rdf
# TimeStep Number-of-rows
# Row c_allrdf[1] c_allrdf[2] c_allrdf[3]
500 100
1 0.005 0 0
2 0.015 0 0
3 0.025 0 0
4 0.035 0 0
5 0.045 0 0
6 0.055 1.16597 0.00133333
7 0.065 2.08865 0.00466667
8 0.075 1.56958 0.008
9 0.085 0.733433 0.01
10 0.095 0.587288 0.012
100 0.095 0.56 0.014     #<-added this line
600 100
1 0.005 0 0
2 0.015 0 0
3 0.025 2.79219 0.000666667
4 0.035 2.86766 0.002
5 0.045 0 0.002
6 0.055 0.582985 0.00266667
7 0.065 2.08865 0.006
8 0.075 0.62783 0.00733333
9 0.085 0.488955 0.00866667
10 0.095 1.17458 0.0126667
100 0.095 1.179 0.12      #<-added this line

Ces lignes étaient nécessaires pour "déclencher" la fonction de traçage de gnuplot à cause des lignes :

   if ($1 == bin_num){
       plot_rdf(timestep, RDF_dat);
       close(RDF_dat);
   }

Desde bin_num est extrait du deuxième champ de l'"en-tête". (par exemple 600 100 ).

Je ne suis pas sûr que vous l'ayez correctement configuré dans votre fichier de données complet ou non. Aussi, j'ai appelé le script comme :

gawk -f test.awk -v inputf=test.dat test.dat

ce qui ignore complètement votre shebang au début, mais j'ai lu que beaucoup de systèmes ont du mal à les séparer correctement.

Enfin, quelle version de gnuplot avez-vous ? Si vous avez la version 4.6, vous pouvez éviter une grande partie de ces difficultés, en sautant pratiquement l'étape de l'analyse des données. gawk script entièrement et le remplacer par un autre beaucoup plus simple.

0voto

jwpat7 Points 5502

Comme le note mgilson, il se peut que vous n'ayez pas réussi à appeler plot_rdf parce que vous n'aviez pas de $1 == bin_num . Notez que le fait d'invoquer awk avec le nom du fichier de données sur la ligne de commande permet d'utiliser facilement la boucle de lecture de fichier intégrée à awk. Ceci est illustré dans la réécriture suivante de votre programme awk. Notez également :
- en utilisant > au lieu de >> en deux endroits
- fermeture de RDF_dat avant l'exécution de gnuplot, au lieu d'après
- en utilisant pad_timestep = sprintf("%06d", timestep); au lieu d'une série maladroite de if déclarations

Pour la suite, j'ai mis le programme dans le fichier so-gnuplot-awk les données telles quelles dans le fichier data-so-gnuplot et a invoqué le programme via

awk -f so-gnuplot-awk data-so-gnuplot

Programme :

# Parse the RDF data and save it to GNUPLOT readable files
BEGIN { dopen=0 }

NF==2 {
    if (dopen) plot_rdf(timestep, RDF_dat);
    timestep = $1;
    print "Reading timestep "timestep;
    RDF_dat="RDF_"timestep".dat";
    printf "" > RDF_dat     # Init empty file
    dopen = 1;
}

NF == 4 {  if (dopen) print $2" "$3 >> RDF_dat; }

# Write gnuplot files and plot RDF data
function plot_rdf(timestep, Load_RDF_dat) {
# Set output filenames & create gnuplot command file
    pad_timestep = sprintf("%06d", timestep);
    gnu_file="plot_RDF_"pad_timestep".gnu";
    png_file="RDF_"pad_timestep".png";
    print "set output \""png_file"\"" > gnu_file; # Use > first
    print "set terminal png" >> gnu_file;
    print "plot './"Load_RDF_dat"' u 1:2" >> gnu_file;
    close(gnu_file);
    close(RDF_dat);
    print "Plotting with "RDF_dat" into "png_file
    system("gnuplot "gnu_file);
    dopen=0
}

END { if (dopen) plot_rdf(timestep, RDF_dat); }

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X