4 votes

Dessiner l'arbre des processus avec gnuplot

Similaire à cette question aquí Je veux dessiner l'arbre d'un processus où un PID est donné, je devrais pouvoir dessiner ce processus et ses enfants sous forme d'arbre. Cependant, je veux préserver la relation parent-enfant entre les nœuds/chemins. Ce que je veux dire, c'est qu'il ne doit pas y avoir d'arête entre deux enfants. Les coordonnées n'ont pas d'importance. Je suis également ouvert à d'autres options d'outils de dessin. J'ai essayé la réponse acceptée de la question mentionnée, mais elle relie tous les nœuds.

Toute suggestion ou aide me ferait plaisir.

Note : J'utilise Ubuntu

7voto

theozh Points 1727

Vous ne donnez pas trop de détails sur ce que vous avez et ce que vous voulez exactement. Je suppose donc quelque chose. Il y a certainement place pour des améliorations. Pour en savoir plus sur les styles de tracé, dans la console gnuplot, voir help points , help vectors , help labels .

Code :

### drawing a simple tree
reset session

$Children <<EOD
23
34
45
56
67
78
EOD

$Parent <<EOD
123
EOD

unset border
unset tics
Size = 8
set offsets 0.2,0.2,0.2,0.2

plot $Children u (Last=$0):(1):1 w labels not, \
     '' u 0:(1):(Last/2-$0):(1) w vectors nohead lc rgb "black" notitle, \
     '' u 0:(1):(Size) w p pt 7 ps var lc rgb "yellow" not, \
     '' u 0:(1):1 w labels not, \
     $Parent u (Last/2):(2):(Size) w p pt 7 ps var lc rgb "light-grey" not, \
     '' u (Last/2):(2):1 w labels center not
### end of code

Résultat :

enter image description here

Ajout :

En fait, vous pouvez réaliser des diagrammes d'arbres un peu plus complexes avec gnuplot. Heureusement, gnuplot permet d'utiliser des fonctions récursives.

L'entrée se compose de 3 colonnes sans en-tête. Chaque ID n'a qu'un seul parent, sauf un qui est le nœud supérieur. Un ID peut avoir plusieurs enfants.

Prérequis :

  • La colonne 1 contient des numéros d'identification entiers et uniques
  • La colonne 2 contient l'ID parent de l'ID enfant de la colonne 1, ou NaN pour le nœud supérieur.
  • Colonne 3 noms des étiquettes des nœuds

Les améliorations sont les bienvenues.

Code : (en fait, il s'agit d'un arbre "absurde")

### tree diagram with gnuplot
reset session

#ID  Parent   Name
$Data <<EOD
   1    NaN   Ant
   2      1   Ape
   3      1   Ass
   4      2   Bat
   5      2   Bee
   6      2   Cat
   7      3   Cod
   8      3   Cow
   9      3   Dog
  10      7   Eel
  11      7   Elk
  12      7   Emu
  13      9   Fly
  14      9   Fox
  15      4   Gnu
  16      1   Hen
  17     16   Hog
  18     12   Jay
  19     12   Owl
  20     15   Pig
  21     15   Pug
  22     12   Ram
  23     14   Rat
  24     12   Sow
  25      7   Yak
EOD

# put datablock into strings
IDs = Parents = Names = ''
set table $Dummy
    plot $Data u (IDs = IDs.strcol(1).' '): \
                 (Parents = Parents.strcol(2).' '): \
                 (Names = Names.strcol(3).' ') w table
unset table

# Top node has no parent ID 'NaN'
Start(n) = int(sum [i=1:words(Parents)] (word(Parents,i) eq 'NaN' ? int(word(IDs,i)) : 0))

# get list index by ID
ItemIdx(s,n) = n == n ? (tmp=NaN, sum [i=1:words(s)] ((word(s,i)) == n ? (tmp=i,0) : 0), tmp) : NaN

# get parent of ID n
Parent(n) = word(Parents,ItemIdx(IDs,n))

# get level of ID n, recursive function
Level(n) = n == n ? Parent(n)>0 ? Level(Parent(n))-1 : 0 : NaN

# get number of children of ID n
ChildCount(n) = int(sum [i=1:words(Parents)] (word(Parents,i)==n))

# Create child list of ID n
ChildList(n) = (Ch = ' ', sum [i=1:words(IDs)] (word(Parents,i)==n ? (Ch = Ch.word(IDs,i).' ',1) : (Ch,0) ), Ch )

# m-th child of ID n
Child(n,m) = word(ChildList(n),m)

# List of leaves, recursive function
LeafList(n) = (LL='', ChildCount(n)==0 ? LL=LL.n.' ' : sum [i=1:ChildCount(n)] (LL=LL.LeafList(Child(n,i)), 0),LL)

# create list of all leaves
LeafAll = LeafList(Start(0))

# get x-position of ID n, recursive function
XPos(n) = ChildCount(n) == 0 ? ItemIdx(LeafAll,n) : (sum [i=1:ChildCount(n)] (XPos(Child(n,i))))/(ChildCount(n))

# create the tree datablock for plotting
set print $Tree
    do for [j=1:words(IDs)] {
        n = int(word(IDs,j))
        print sprintf("% 3d % 7.2f % 4d % 5s", n, XPos(n), Level(n), word(Names,j))
    }
set print
print $Tree

# get x and y distance from ID n to its parent
dx(n) = XPos(Parent(int(n))) - XPos(int(n))
dy(n) = Level(Parent(int(n))) - Level(int(n))

unset border
unset tics
set offsets 0.25, 0.25, 0.25, 0.25

plot $Tree u 2:3:(dx($1)):(dy($1)) w vec nohead ls -1 not,\
        '' u 2:3 w p pt 7 ps 6 lc rgb 0xccffcc not, \
        '' u 2:3 w p pt 6 ps 6 lw 1.5 lc rgb "black" not, \
        '' u 2:3:4 w labels offset 0,0.1 center not
### end of code

Résultat :

enter image description here

0voto

Si nous sommes vraiment ouverts à toutes les options, permettez-moi de vous suggérer celle que je préfère :

pstree -p <pid>
or
pstree -ap <pid>

ce qui peut vous donner quelque chose comme ceci :

foo,26943 /a/b/c/foo -i...
  foo1,26951 /a/b/c/foo1 -x...
      foo2,27103 /a/b/c/foo2 -y...

homme pstree - peut vous fournir diverses options pour régler ce que vous voulez/ne voulez pas voir dans le graphique

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