]> SALOME platform Git repositories - tools/eficas.git/blob - Aster/Cata/Utilitai/Graph.py
Salome HOME
CCAR: merge de la version 1.14 dans la branche principale
[tools/eficas.git] / Aster / Cata / Utilitai / Graph.py
1 #@ MODIF Graph Utilitai  DATE 16/10/2007   AUTEUR REZETTE C.REZETTE 
2 # -*- coding: iso-8859-1 -*-
3 #            CONFIGURATION MANAGEMENT OF EDF VERSION
4 # ======================================================================
5 # COPYRIGHT (C) 1991 - 2004  EDF R&D                  WWW.CODE-ASTER.ORG
6 # THIS PROGRAM IS FREE SOFTWARE; YOU CAN REDISTRIBUTE IT AND/OR MODIFY  
7 # IT UNDER THE TERMS OF THE GNU GENERAL PUBLIC LICENSE AS PUBLISHED BY  
8 # THE FREE SOFTWARE FOUNDATION; EITHER VERSION 2 OF THE LICENSE, OR     
9 # (AT YOUR OPTION) ANY LATER VERSION.                                                  
10 #                                                                       
11 # THIS PROGRAM IS DISTRIBUTED IN THE HOPE THAT IT WILL BE USEFUL, BUT   
12 # WITHOUT ANY WARRANTY; WITHOUT EVEN THE IMPLIED WARRANTY OF            
13 # MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. SEE THE GNU      
14 # GENERAL PUBLIC LICENSE FOR MORE DETAILS.                              
15 #                                                                       
16 # YOU SHOULD HAVE RECEIVED A COPY OF THE GNU GENERAL PUBLIC LICENSE     
17 # ALONG WITH THIS PROGRAM; IF NOT, WRITE TO EDF R&D CODE_ASTER,         
18 #    1 AVENUE DU GENERAL DE GAULLE, 92141 CLAMART CEDEX, FRANCE.        
19 # ======================================================================
20
21 # RESPONSABLE MCOURTOI M.COURTOIS
22 __all__ = ['Graph', 'AjoutParaCourbe']
23
24 import sys
25 import os
26 import os.path
27 import string
28 import re
29 import types
30 import time
31 import Numeric
32
33 # try/except pour utiliser hors aster
34 try:
35    import aster
36 except ImportError:
37    class fake_aster:
38       def repout(self): return '/opt/aster/outils'
39    aster=fake_aster()
40
41 from Macro.externe_mess import UTMESS
42
43 if not sys.modules.has_key('Table'):
44    try:
45       from Utilitai import Table
46    except ImportError:
47       import Table
48    
49
50 # ------------------------------------------------------------------------------
51 class Graph:
52    """Cette classe définit l'objet Graph pour Code_Aster.
53    
54    Important :  Utiliser les méthodes dédiées à la manipulation des données
55       (AjoutCourbe, ...) car elles tiennent à jour les attributs "privés"
56       relatifs aux données : NbCourbe, les extrema...
57    
58    Attributs :
59    - Données de chaque courbe :
60       .Valeurs   : liste des valeurs de chaque courbe, pour chaque courbe :
61          (paramètres, parties réelles [, parties imaginaires])
62       .Legendes  : liste des noms de chaque courbe
63       .Labels    : liste des noms des colonnes de chaque courbe
64       .Styles    : liste des infices de styles de ligne
65       .Couleurs  : liste des indices de couleurs
66       .Marqueurs : liste des indices de symboles/marqueurs
67       .FreqMarq  : liste des fréquences des marqueurs
68       .Tri       : liste du tri à effectuer sur les données ('N', 'X', 'Y',
69          'XY' ou 'YX')
70      Pour Lignes, Couleurs, Marqueurs, FreqMarq, -1 signifie valeur par défaut
71      du traceur.
72
73    - Propriétés :
74       .Titre : titre du graphique
75       .SousTitre : sous-titre (appelé commentaire dans agraf)
76    - Axes :
77       .Min_X, .Max_X, .Min_Y, .Max_Y : bornes du tracé (une méthode permet de
78          renseigner automatiquement ces valeurs avec les extréma globaux)
79       .Legende_X, .Legende_Y : légende des axes
80       .Echelle_X, .Echelle_Y : type d'échelle (LIN, LOG)
81       .Grille_X, .Grille_Y : paramètre de la grille (pas ou fréquence au choix
82          de l'utilisateur en fonction du traceur qu'il veut utiliser)
83
84    Attributs privés (modifiés uniquement par les méthodes de la classe) :
85       .NbCourbe : nombre de courbes
86       .BBXmin, BBXmax, BBYmin, BBYmax : extrema globaux (bounding box)
87       .LastTraceArgs, LastTraceFormat : données utilisées lors du dernier tracé
88    """
89 # ------------------------------------------------------------------------------
90    def __init__(self):
91       """Construction + valeurs par défaut des attributs
92       """
93       self.Valeurs   = []
94       self.Legendes  = []
95       self.Labels    = []
96       self.Styles    = []
97       self.Couleurs  = []
98       self.Marqueurs = []
99       self.FreqMarq  = []
100       self.Tri       = []
101       self.Titre     = ''
102       self.SousTitre = ''
103       self.Min_X     = None
104       self.Max_X     = None
105       self.Min_Y     = None
106       self.Max_Y     = None
107       self.MinP_X    =  1.e+99   # minimum > 0 pour les échelles LOG
108       self.MinP_Y    =  1.e+99
109       self.Legende_X = ''
110       self.Legende_Y = ''
111       self.Echelle_X = 'LIN'
112       self.Echelle_Y = 'LIN'
113       self.Grille_X  = -1
114       self.Grille_Y  = -1
115       # attributs que l'utilisateur ne doit pas modifier
116       self.NbCourbe  = len(self.Valeurs)
117       self.BBXmin    =  1.e+99
118       self.BBXmax    = -1.e+99
119       self.BBYmin    =  1.e+99
120       self.BBYmax    = -1.e+99
121       # pour conserver les paramètres du dernier tracé
122       self.LastTraceArgs = {}
123       self.LastTraceFormat = ''
124
125 # ------------------------------------------------------------------------------
126    def SetExtremaX(self,marge=0., x0=None, x1=None, force=True):
127       """Remplit les limites du tracé (Min/Max_X) avec les valeurs de la
128       bounding box +/- avec une 'marge'*(Max-Min)/2.
129       x0,x1 permettent de modifier la bb.
130       """
131       if x0<>None:   self.BBXmin=min([self.BBXmin, x0])
132       if x1<>None:   self.BBXmax=max([self.BBXmax, x1])
133
134       dx=max(self.BBXmax-self.BBXmin,0.01*self.BBXmax)
135       if dx == 0.:
136          dx = 1.e-6
137       if force or self.Min_X==None:
138          self.Min_X = self.BBXmin - marge*dx/2.
139       if force or self.Max_X==None:
140          self.Max_X = self.BBXmax + marge*dx/2.
141       return
142
143    def SetExtremaY(self,marge=0., y0=None, y1=None, force=True):
144       """Remplit les limites du tracé (Min/Max_Y) avec les valeurs de la
145       bounding box +/- avec une 'marge'*(Max-Min)/2.
146       y0,y1 permettent de modifier la bb.
147       """
148       if y0<>None:   self.BBYmin=min([self.BBYmin, y0])
149       if y1<>None:   self.BBYmax=max([self.BBYmax, y1])
150
151       dy=max(self.BBYmax-self.BBYmin,0.01*self.BBYmax)
152       if dy == 0.:
153          dy = 1.e-6
154       if force or self.Min_Y==None:
155          self.Min_Y = self.BBYmin - marge*dy/2.
156       if force or self.Max_Y==None:
157          self.Max_Y = self.BBYmax + marge*dy/2.
158       return
159
160    def SetExtrema(self,marge=0., x0=None, x1=None, y0=None, y1=None, force=True):
161       """Remplit les limites du tracé (Min/Max_X/Y) avec les valeurs de la
162       bounding box +/- avec une 'marge'*(Max-Min)/2.
163       x0,x1,y0,y1 permettent de modifier la bb.
164       """
165       self.SetExtremaX(marge, x0, x1, force=force)
166       self.SetExtremaY(marge, y0, y1, force=force)
167       return
168 # ------------------------------------------------------------------------------
169    def AutoBB(self,debut=-1):
170       """Met à jour automatiquement la "bounding box"
171       (extrema toutes courbes confondues)
172       Appelé par les méthodes de manipulation des données
173       """
174       if debut == -1:
175          debut=self.NbCourbe-1
176       if debut == 0:
177          X0 =  1.e+99
178          X1 = -1.e+99
179          Y0 =  1.e+99
180          Y1 = -1.e+99
181       else:
182          X0 = self.BBXmin
183          X1 = self.BBXmax
184          Y0 = self.BBYmin
185          Y1 = self.BBYmax
186       
187       for i in range(debut,self.NbCourbe):
188          X0 = min([X0,]+list(self.Valeurs[i][0]))
189          X1 = max([X1,]+list(self.Valeurs[i][0]))
190          self.MinP_X = min([self.MinP_X,]+[x for x \
191                   in list(self.Valeurs[i][0]) if x>0])
192          for ny in range(1,len(self.Valeurs[i])):
193             Y0 = min([Y0,]+list(self.Valeurs[i][ny]))
194             Y1 = max([Y1,]+list(self.Valeurs[i][ny]))
195             self.MinP_Y = min([self.MinP_Y,]+[y for y \
196                   in list(self.Valeurs[i][0]) if y>0])
197       self.BBXmin = X0
198       self.BBXmax = X1
199       self.BBYmin = Y0
200       self.BBYmax = Y1
201       return
202 # ------------------------------------------------------------------------------
203    def AjoutCourbe(self,Val,Lab,Leg='',Sty=-1,Coul=-1,Marq=-1,FreqM=-1,Tri='N'):
204       """Ajoute une courbe dans les données
205          Val   : liste de 2 listes (ou 3 si complexe) : abs, ord[, imag]
206          Leg   : une chaine
207          Lab   : liste de 2 chaines (ou 3 si complexe)
208          Sty   : un entier
209          Coul  : un entier
210          Marq  : un entier
211          FreqM : un entier
212          Tri   : chaine de caractères : N, X, Y, XY ou YX
213       Met à jour les attributs : NbCourbe, BBXmin/Xmax/Ymin/Ymax
214       """
215       nbc = len(Val)   # nombre de colonnes : 2 ou 3
216       
217       # verifications : "if not (conditions requises)"
218       if not ( 2 <= nbc <= 3 and \
219          type(Val[0]) in (types.ListType, types.TupleType) and \
220          type(Val[1]) in (types.ListType, types.TupleType) and \
221          (nbc==2 or type(Val[2]) in (types.ListType, types.TupleType)) and \
222          len(Val[0]) == len(Val[1]) and (nbc==2 or len(Val[0]) == len(Val[2])) ):
223             UTMESS('S','Graph','"Val" doit etre une liste de 2 ou 3 listes de rééls de meme longueur')
224       
225       if len(Lab) <> nbc:
226             UTMESS('S','Graph','"Lab" doit etre une liste de 2 ou 3 chaines')
227             
228       # ajout dans les données
229       self.Legendes.append(str(Leg))
230       self.Labels.append([str(L) for L in Lab])
231       self.Valeurs.append(Val)
232       self.Styles.append(Sty)
233       self.Couleurs.append(Coul)
234       self.Marqueurs.append(Marq)
235       self.FreqMarq.append(FreqM)
236       self.Tri.append(Tri)
237
238       self.NbCourbe = self.NbCourbe + 1
239       self.AutoBB()
240       return
241 # ------------------------------------------------------------------------------
242    def Courbe(self,n):
243       """Permet de récupérer les données de la courbe d'indice n sous forme
244       d'un dictionnaire.
245       """
246       dico={
247          'Leg'    : self.Legendes[n],           # légende de la courbe
248          'LabAbs' : self.Labels[n][0],          # labels des abscisses
249          'LabOrd' : [self.Labels[n][1],],       # labels des ordonnées
250          'NbCol'  : len(self.Valeurs[n]),       # nombre de colonnes
251          'NbPts'  : len(self.Valeurs[n][0]),    # nombre de points
252          'Abs'    : self.Valeurs[n][0],         # liste des abscisses
253          'Ord'    : [self.Valeurs[n][1],],      # liste des ordonnées
254          'Sty'    : self.Styles[n],             # style de la ligne
255          'Coul'   : self.Couleurs[n],           # couleur
256          'Marq'   : self.Marqueurs[n],          # marqueur
257          'FreqM'  : self.FreqMarq[n],           # fréquence du marqueur
258          'Tri'    : self.Tri[n],                # ordre de tri des données
259       }
260       if(dico['NbCol'] == 3):
261          dico['LabOrd'].append(self.Labels[n][2]) # labels de la partie imaginaire
262          dico['Ord'].append(self.Valeurs[n][2])   # liste des ordonnées partie imaginaire
263       return dico
264 # ------------------------------------------------------------------------------
265    def Trace(self,FICHIER=None,FORMAT=None,dform=None,**opts):
266       """Tracé du Graph selon le format spécifié.
267          FICHIER : nom du(des) fichier(s). Si None, on dirige vers stdout
268          dform : dictionnaire de formats d'impression (format des réels,
269             commentaires, saut de ligne...)
270          opts  : voir TraceGraph.
271       """
272       para={
273          'TABLEAU' : { 'mode' : 'a', 'driver' : TraceTableau, },
274          'XMGRACE' : { 'mode' : 'a', 'driver' : TraceXmgrace, },
275          'AGRAF'   : { 'mode' : 'a', 'driver' : TraceAgraf,   },
276       }
277       kargs={}
278       if self.LastTraceArgs=={}:
279          kargs['FICHIER']=FICHIER
280          kargs['dform']=dform
281          kargs['opts']=opts
282       else:
283          kargs=self.LastTraceArgs.copy()
284          if FORMAT==None:
285             FORMAT=self.LastTraceFormat
286          if FICHIER<>None:
287             kargs['FICHIER']=FICHIER
288          if dform<>None:
289             kargs['dform']=dform
290          if opts<>{}:
291             kargs['opts']=opts
292       if not FORMAT in para.keys():
293          UTMESS('A', 'Objet Graph', 'Format inconnu : %s' % FORMAT)
294       else:
295          kargs['fmod']=para[FORMAT]['mode']
296          self.LastTraceArgs   = kargs.copy()
297          self.LastTraceFormat = FORMAT
298          # call the associated driver
299          para[FORMAT]['driver'](self,**kargs)
300 # ------------------------------------------------------------------------------
301    def __repr__(self):
302       """Affichage du contenu d'un Graph"""
303       srep=''
304       for attr in ['NbCourbe','Legendes','Labels','Valeurs','Min_X','Max_X','Min_Y','Max_Y','BBXmax','BBXmin','BBYmax','BBYmin','Legende_X','Legende_Y','Echelle_X','Echelle_Y','Grille_X','Grille_Y','Tri']:
305          srep=srep + '%-10s : %s\n' % (attr,str(getattr(self,attr)))
306       return srep
307
308 # ------------------------------------------------------------------------------
309 # ------------------------------------------------------------------------------
310 # ------------------------------------------------------------------------------
311 class TraceGraph:
312    """
313    Cette classe définit le tracé d'un objet Graph dans un fichier.
314    
315    Attributs :
316       .NomFich : liste de noms de fichier de sortie
317
318    Attributs privés (modifiés uniquement par les méthodes de la classe) :
319       .Fich    : liste des objets 'fichier'
320       .Graph   : objet Graph que l'on veut tracer
321       .DicForm : dictionnaire des formats de base (séparateur, format des réels...)
322    
323    Les méthodes Entete, DescrCourbe, Trace (définition de l'entete, partie descriptive
324    d'une courbe, méthode de tracé/impression) sont définies dans une classe dérivée.
325    """
326 # ------------------------------------------------------------------------------
327    def __init__(self,graph,FICHIER,fmod='w',dform=None,opts={}):
328       """Construction, ouverture du fichier, surcharge éventuelle du formatage
329       (dform), mode d'ouverture du fichier (fmod).
330       opts  : dictionnaire dont les valeurs seront affectées comme attributs
331          de l'objet (A utiliser pour les propriétés spécifiques
332          à un format, exemple 'PILOTE' pour Xmgrace).
333       """
334       # attributs optionnels (au début pour éviter un écrasement maladroit !)
335       for k,v in opts.items():
336          setattr(self,k,v)
337
338       # Ouverture du(des) fichier(s)
339       self.NomFich=[]
340       if type(FICHIER) is types.StringType:
341          self.NomFich.append(FICHIER)
342       elif type(FICHIER) in (types.ListType, types.TupleType):
343          self.NomFich=FICHIER[:]
344       else:
345          # dans ce cas, on écrira sur stdout (augmenter le 2 éventuellement)
346          self.NomFich=[None]*2
347       self.Fich=[]
348       for ff in self.NomFich:
349          if ff<>None:
350             self.Fich.append(open(ff,fmod))
351          else:
352             self.Fich.append(sys.stdout)
353       
354       # objet Graph sous-jacent
355       self.Graph=graph
356       # si Min/Max incohérents
357       if graph.Min_X==None or graph.Max_X==None or graph.Min_X > graph.Max_X:
358          graph.SetExtremaX(marge=0.05, force=True)
359       if graph.Min_Y==None or graph.Max_Y==None or graph.Min_Y > graph.Max_Y:
360          graph.SetExtremaY(marge=0.05, force=True)
361
362       if graph.Echelle_X=='LOG':
363          graph.Grille_X=10
364          # verif si Min<0 à cause de la marge
365          if graph.Min_X < 0.:
366             if graph.BBXmin < 0.:
367                UTMESS('A', 'Graph', 'On limite la fenetre aux abscisses positives.')
368             graph.Min_X=graph.MinP_X
369       if graph.Echelle_Y=='LOG':
370          graph.Grille_Y=10
371          if graph.Min_Y < 0.:
372             if graph.BBYmin < 0.:
373                UTMESS('A', 'Graph', 'On limite la fenetre aux ordonnées positives.')
374             graph.Min_Y=graph.MinP_Y
375       
376       # formats de base (identiques à ceux du module Table)
377       self.DicForm={
378          'csep'  : ' ',       # séparateur
379          'ccom'  : '#',       # commentaire
380          'cdeb'  : '',        # début de ligne
381          'cfin'  : '\n',      # fin de ligne
382          'formK' : '%-12s',   # chaines
383          'formR' : '%12.5E',  # réels
384          'formI' : '%12d'     # entiers
385       }
386       if dform<>None and type(dform)==types.DictType:
387          self.DicForm.update(dform)
388       
389       # let's go
390       self.Trace()
391
392 # ------------------------------------------------------------------------------
393    def __del__(self):
394       """Fermeture du(des) fichier(s) à la destruction"""
395       if hasattr(self,'Fich'):
396          self._FermFich()
397 # ------------------------------------------------------------------------------
398    def _FermFich(self):
399       """Fermeture du(des) fichier(s)"""
400       for fp in self.Fich:
401          if fp<>sys.stdout:
402             fp.close()
403 # ------------------------------------------------------------------------------
404    def _OuvrFich(self):
405       """Les fichiers sont ouverts par le constructeur. S'ils ont été fermés,
406       par un appel au Tracé, _OuvrFich ouvre de nouveau les fichiers dans le
407       meme mode"""
408       n=len(self.NomFich)
409       for i in range(n):
410          if self.Fich[i].closed:
411             self.Fich[i]=open(self.NomFich[i],self.Fich[i].mode)
412
413 # ------------------------------------------------------------------------------
414    def Entete(self):
415       """Retourne l'entete"""
416       raise NotImplementedError, "Cette méthode doit etre définie par la classe fille."
417 # ------------------------------------------------------------------------------
418    def DescrCourbe(self,**args):
419       """Retourne la chaine de caractères décrivant les paramètres de la courbe.
420       """
421       raise NotImplementedError, "Cette méthode doit etre définie par la classe fille."
422 # ------------------------------------------------------------------------------
423    def Trace(self):
424       """Méthode pour 'tracer' l'objet Graph dans un fichier.
425       Met en page l'entete, la description des courbes et les valeurs selon
426       le format et ferme le fichier.
427       """
428       raise NotImplementedError, "Cette méthode doit etre définie par la classe fille."
429
430
431 # ------------------------------------------------------------------------------
432 # ------------------------------------------------------------------------------
433 # ------------------------------------------------------------------------------
434 class TraceTableau(TraceGraph):
435    """
436    Impression d'un objet Graph sous forme d'un tableau de colonnes,
437    on suppose que les courbes partagent la meme liste d'abscisse à 'EPSILON'
438    près, sinon on alarme.
439    """
440    EPSILON=1.e-4
441 # ------------------------------------------------------------------------------
442    def Trace(self):
443       """Méthode pour 'tracer' l'objet Graph dans un fichier.
444       Met en page l'entete, la description des courbes et les valeurs selon
445       le format et ferme le fichier.
446       L'ouverture et la fermeture du fichier sont gérées par l'objet Table.
447       """
448       g=self.Graph
449       msg=[]
450       if g.NbCourbe > 0:
451          # validité des données (abscisses identiques)
452          t0=Numeric.array(g.Courbe(0)['Abs'])
453          max0=max(abs(t0))
454          for i in range(1,g.NbCourbe):
455             if g.Courbe(i)['NbPts']<>g.Courbe(0)['NbPts']:
456                msg.append("La courbe %d n'a pas le meme " \
457                      "nombre de points que la 1ère." % i)
458             else:
459                ti=Numeric.array(g.Courbe(i)['Abs'])
460                if max(abs((ti-t0).flat)) > self.EPSILON*max0:
461                   msg.append("Courbe %d : écart entre les "\
462                         "abscisses supérieur à %9.2E" % (i+1,self.EPSILON))
463                   msg.append("     Utilisez IMPR_FONCTION pour interpoler " \
464                         "les valeurs sur la première liste d'abscisses.")
465          # objet Table
466          Tab=Table.Table()
467          # titre / sous-titre
468          tit=[]
469          tit.append(self.DicForm['ccom']+' '+g.Titre)
470          tit.append(self.DicForm['ccom']+' '+g.SousTitre)
471          # legendes
472          for i in range(g.NbCourbe):
473             tit.append(self.DicForm['ccom']+' Courbe '+str(i)+' '+g.Legendes[i])
474          Tab.titr=self.DicForm['cfin'].join(tit)
475          # noms des paramètres/colonnes
476          Tab.para.append(g.Labels[0][0])
477          for i in range(g.NbCourbe):
478             for lab in g.Labels[i][1:]:
479                Tab.para.append(lab)
480          # types
481          Tab.type=['R']*len(Tab.para)
482          # lignes de la Table
483          dC0=g.Courbe(0)
484          for j in range(dC0['NbPts']):
485             row={}
486             row[dC0['LabAbs']]=dC0['Abs'][j]
487             for i in range(g.NbCourbe):
488                dCi=g.Courbe(i)
489                for k in range(dCi['NbCol']-1):
490                   try:
491                      row[dCi['LabOrd'][k]]=dCi['Ord'][k][j]
492                   except IndexError:
493                      row[dCi['LabOrd'][k]]=None
494             Tab.append(row)
495          Tab.Impr(FICHIER=self.NomFich[0], FORMAT='TABLEAU')
496          # erreurs ?
497          if msg:
498             UTMESS('A', 'Graph.TraceTableau', '\n'.join(msg))
499       return
500
501 # ------------------------------------------------------------------------------
502 # ------------------------------------------------------------------------------
503 # ------------------------------------------------------------------------------
504 class TraceXmgrace(TraceGraph):
505    """
506    Impression d'un objet Graph au format XMGRACE.
507    Attribut supplémentaire : .PILOTE
508    """
509    PILOTE=''
510 # ------------------------------------------------------------------------------
511    def Entete(self):
512       """Retourne l'entete du fichier .agr correspondant à la mise en forme
513       """
514       dic_ech={ 'LIN' : 'Normal', 'LOG' : 'Logarithmic' }
515       g=self.Graph
516       entete=[]
517       entete.append("""
518 # Grace project file
519 #
520 @version 50100
521 @page size 842, 595
522 @page scroll 5%
523 @page inout 5%
524 @link page off
525 @map font 0 to "Times-Roman", "Times-Roman"
526 @map font 1 to "Times-Italic", "Times-Italic"
527 @map font 2 to "Times-Bold", "Times-Bold"
528 @map font 3 to "Times-BoldItalic", "Times-BoldItalic"
529 @map font 4 to "Helvetica", "Helvetica"
530 @map font 5 to "Helvetica-Oblique", "Helvetica-Oblique"
531 @map font 6 to "Helvetica-Bold", "Helvetica-Bold"
532 @map font 7 to "Helvetica-BoldOblique", "Helvetica-BoldOblique"
533 @map font 8 to "Courier", "Courier"
534 @map font 9 to "Courier-Oblique", "Courier-Oblique"
535 @map font 10 to "Courier-Bold", "Courier-Bold"
536 @map font 11 to "Courier-BoldOblique", "Courier-BoldOblique"
537 @map font 12 to "Symbol", "Symbol"
538 @map font 13 to "ZapfDingbats", "ZapfDingbats"
539 @map color 0 to (255, 255, 255), "white"
540 @map color 1 to (0, 0, 0), "black"
541 @map color 2 to (255, 0, 0), "red"
542 @map color 3 to (0, 255, 0), "green"
543 @map color 4 to (0, 0, 255), "blue"
544 @map color 5 to (255, 255, 0), "yellow"
545 @map color 6 to (188, 143, 143), "brown"
546 @map color 7 to (220, 220, 220), "grey"
547 @map color 8 to (148, 0, 211), "violet"
548 @map color 9 to (0, 255, 255), "cyan"
549 @map color 10 to (255, 0, 255), "magenta"
550 @map color 11 to (255, 165, 0), "orange"
551 @map color 12 to (114, 33, 188), "indigo"
552 @map color 13 to (103, 7, 72), "maroon"
553 @map color 14 to (64, 224, 208), "turquoise"
554 @map color 15 to (0, 139, 0), "green4"
555 @reference date 0
556 @date wrap off
557 @date wrap year 1950
558 @timestamp off
559 @default linewidth 1.0
560 @default linestyle 1
561 @default color 1
562 @default pattern 1
563 @default font 0
564 @default char size 1.000000
565 @default symbol size 1.000000
566 @default sformat "%.8g"
567 @background color 0
568 @page background fill on
569 @r0 off
570 @link r0 to g0
571 @r0 type above
572 @r0 linestyle 1
573 @r0 linewidth 1.0
574 @r0 color 1
575 @r0 line 0, 0, 0, 0
576 @r1 off
577 @link r1 to g0
578 @r1 type above
579 @r1 linestyle 1
580 @r1 linewidth 1.0
581 @r1 color 1
582 @r1 line 0, 0, 0, 0
583 @r2 off
584 @link r2 to g0
585 @r2 type above
586 @r2 linestyle 1
587 @r2 linewidth 1.0
588 @r2 color 1
589 @r2 line 0, 0, 0, 0
590 @r3 off
591 @link r3 to g0
592 @r3 type above
593 @r3 linestyle 1
594 @r3 linewidth 1.0
595 @r3 color 1
596 @r3 line 0, 0, 0, 0
597 @r4 off
598 @link r4 to g0
599 @r4 type above
600 @r4 linestyle 1
601 @r4 linewidth 1.0
602 @r4 color 1
603 @r4 line 0, 0, 0, 0
604 @g0 on
605 @g0 hidden false
606 @g0 type XY
607 @g0 stacked false
608 @g0 bar hgap 0.000000
609 @with g0
610 @    stack world 0, 0, 0, 0
611 @    znorm 1
612 @    view xmin 0.150000
613 @    view xmax 1.150000
614 @    view ymin 0.150000
615 @    view ymax 0.850000
616 @    title font 0
617 @    title size 1.500000
618 @    title color 1
619 @    subtitle font 0
620 @    subtitle size 1.000000
621 @    subtitle color 1
622 @    xaxes invert off
623 @    yaxes invert off
624 @    xaxis  on
625 @    xaxis  type zero false
626 @    xaxis  offset 0.000000 , 0.000000
627 @    xaxis  bar on
628 @    xaxis  bar color 1
629 @    xaxis  bar linestyle 1
630 @    xaxis  bar linewidth 1.0
631 @    xaxis  label layout para
632 @    xaxis  label place auto
633 @    xaxis  label char size 1.000000
634 @    xaxis  label font 0
635 @    xaxis  label color 1
636 @    xaxis  label place normal
637 @    xaxis  tick on
638 @    xaxis  tick minor ticks 1
639 @    xaxis  tick default 6
640 @    xaxis  tick place rounded true
641 @    xaxis  tick in
642 @    xaxis  tick major size 1.000000
643 @    xaxis  tick major color 1
644 @    xaxis  tick major linewidth 1.0
645 @    xaxis  tick major linestyle 2
646 @    xaxis  tick major grid on
647 @    xaxis  tick minor color 1
648 @    xaxis  tick minor linewidth 1.0
649 @    xaxis  tick minor linestyle 2
650 @    xaxis  tick minor grid off
651 @    xaxis  tick minor size 0.500000
652 @    xaxis  ticklabel on
653 @    xaxis  ticklabel format general
654 @    xaxis  ticklabel prec 5
655 @    xaxis  ticklabel angle 0
656 @    xaxis  ticklabel skip 0
657 @    xaxis  ticklabel stagger 0
658 @    xaxis  ticklabel place normal
659 @    xaxis  ticklabel offset auto
660 @    xaxis  ticklabel offset 0.000000 , 0.010000
661 @    xaxis  ticklabel start type auto
662 @    xaxis  ticklabel start 0.000000
663 @    xaxis  ticklabel stop type auto
664 @    xaxis  ticklabel stop 0.000000
665 @    xaxis  ticklabel char size 0.800000
666 @    xaxis  ticklabel font 0
667 @    xaxis  ticklabel color 1
668 @    xaxis  ticklabel formula ""
669 @    xaxis  ticklabel append ""
670 @    xaxis  ticklabel prepend ""
671 @    xaxis  tick place both
672 @    xaxis  tick spec type none
673 @    yaxis  on
674 @    yaxis  type zero false
675 @    yaxis  offset 0.000000 , 0.000000
676 @    yaxis  bar on
677 @    yaxis  bar color 1
678 @    yaxis  bar linestyle 1
679 @    yaxis  bar linewidth 1.0
680 @    yaxis  label layout para
681 @    yaxis  label place auto
682 @    yaxis  label char size 1.000000
683 @    yaxis  label font 0
684 @    yaxis  label color 1
685 @    yaxis  label place normal
686 @    yaxis  tick on
687 @    yaxis  tick minor ticks 1
688 @    yaxis  tick default 6
689 @    yaxis  tick place rounded true
690 @    yaxis  tick in
691 @    yaxis  tick major size 1.000000
692 @    yaxis  tick major color 1
693 @    yaxis  tick major linewidth 1.0
694 @    yaxis  tick major linestyle 2
695 @    yaxis  tick major grid on
696 @    yaxis  tick minor color 1
697 @    yaxis  tick minor linewidth 1.0
698 @    yaxis  tick minor linestyle 1
699 @    yaxis  tick minor grid off
700 @    yaxis  tick minor size 0.500000
701 @    yaxis  ticklabel on
702 @    yaxis  ticklabel format general
703 @    yaxis  ticklabel prec 5
704 @    yaxis  ticklabel angle 0
705 @    yaxis  ticklabel skip 0
706 @    yaxis  ticklabel stagger 0
707 @    yaxis  ticklabel place normal
708 @    yaxis  ticklabel offset auto
709 @    yaxis  ticklabel offset 0.000000 , 0.010000
710 @    yaxis  ticklabel start type auto
711 @    yaxis  ticklabel start 0.000000
712 @    yaxis  ticklabel stop type auto
713 @    yaxis  ticklabel stop 0.000000
714 @    yaxis  ticklabel char size 0.800000
715 @    yaxis  ticklabel font 0
716 @    yaxis  ticklabel color 1
717 @    yaxis  ticklabel formula ""
718 @    yaxis  ticklabel append ""
719 @    yaxis  ticklabel prepend ""
720 @    yaxis  tick place both
721 @    yaxis  tick spec type none
722 @    altxaxis  off
723 @    altyaxis  off
724 @    legend on
725 @    legend loctype view
726 @    legend 0.85, 0.8
727 @    legend box color 1
728 @    legend box pattern 1
729 @    legend box linewidth 1.0
730 @    legend box linestyle 1
731 @    legend box fill color 0
732 @    legend box fill pattern 1
733 @    legend font 0
734 @    legend char size 0.750000
735 @    legend color 1
736 @    legend length 4
737 @    legend vgap 1
738 @    legend hgap 1
739 @    legend invert false
740 @    frame type 0
741 @    frame linestyle 1
742 @    frame linewidth 1.0
743 @    frame color 1
744 @    frame pattern 1
745 @    frame background color 0
746 @    frame background pattern 0
747 """)
748       entete.append('@    title "'+g.Titre+'"')
749       entete.append('@    subtitle "'+g.SousTitre+'"')
750       entete.append('@    xaxis  label "'+g.Legende_X+'"')
751       entete.append('@    yaxis  label "'+g.Legende_Y+'"')
752       entete.append('@    xaxes scale '+dic_ech[g.Echelle_X])
753       entete.append('@    yaxes scale '+dic_ech[g.Echelle_Y])
754       entete.append('@    xaxis  tick major '+str(g.Grille_X))
755       entete.append('@    yaxis  tick major '+str(g.Grille_Y))
756       entete.append('@    world xmin '+str(g.Min_X))
757       entete.append('@    world xmax '+str(g.Max_X))
758       entete.append('@    world ymin '+str(g.Min_Y))
759       entete.append('@    world ymax '+str(g.Max_Y))
760       return entete
761 # ------------------------------------------------------------------------------
762    def DescrCourbe(self,**args):
763       """Retourne la chaine de caractères décrivant les paramètres de la courbe.
764       """
765       # valeurs par défaut
766       sty   = str(ValCycl(args['Sty'],0,8,1))
767       color = str(ValCycl(args['Coul'],1,15,args['NumSet']+1))
768       symbol= str(ValCycl(args['Marq'],0,10,args['NumSet']))
769       freqm = str(ValCycl(args['FreqM'],0,-1,0))
770
771       sn=str(args['NumSet'])
772       descr=[]
773       descr.append(string.replace("""
774 @    s0 hidden false
775 @    s0 type xy
776 @    s0 symbol size 1.000000
777 @    s0 symbol pattern 1
778 @    s0 symbol linestyle 1
779 @    s0 symbol fill pattern 0
780 @    s0 symbol linewidth 1.0
781 @    s0 symbol char 65
782 @    s0 symbol char font 0
783 @    s0 line type 1
784 @    s0 line linewidth 1.0
785 @    s0 line pattern 1
786 @    s0 baseline type 0
787 @    s0 baseline off
788 @    s0 dropline off
789 @    s0 fill type 0
790 @    s0 fill rule 0
791 @    s0 fill pattern 1
792 @    s0 avalue off
793 @    s0 avalue type 2
794 @    s0 avalue char size 1.000000
795 @    s0 avalue font 0
796 @    s0 avalue rot 0
797 @    s0 avalue format general
798 @    s0 avalue prec 3
799 @    s0 avalue prepend ""
800 @    s0 avalue append ""
801 @    s0 avalue offset 0.000000 , 0.000000
802 @    s0 errorbar on
803 @    s0 errorbar place both
804 @    s0 errorbar pattern 1
805 @    s0 errorbar size 1.000000
806 @    s0 errorbar linewidth 1.0
807 @    s0 errorbar linestyle 1
808 @    s0 errorbar riser linewidth 1.0
809 @    s0 errorbar riser linestyle 1
810 @    s0 errorbar riser clip off
811 @    s0 errorbar riser clip length 0.100000
812
813 @    s0 comment ""
814 """,' s0 ',' s'+sn+' '))
815       descr.append('@    s'+sn+' symbol '+symbol)
816       descr.append('@    s'+sn+' symbol color '+color)
817       descr.append('@    s'+sn+' symbol skip '+freqm)
818       descr.append('@    s'+sn+' symbol fill color '+color)
819       descr.append('@    s'+sn+' line linestyle '+sty)
820       descr.append('@    s'+sn+' line color '+color)
821       descr.append('@    s'+sn+' fill color '+color)
822       descr.append('@    s'+sn+' avalue color '+color)
823       descr.append('@    s'+sn+' errorbar color '+color)
824       descr.append('@    s'+sn+' legend "'+args['Leg']+'"')
825       return descr
826 # ------------------------------------------------------------------------------
827    def Trace(self):
828       """Méthode pour 'tracer' l'objet Graph dans un fichier.
829       Met en page l'entete, la description des courbes et les valeurs selon
830       le format et ferme le fichier.
831       """
832       g = self.Graph
833       if self.PILOTE == 'INTERACTIF':
834          self.NomFich[0] = 'Trace_%s.dat' % time.strftime('%y%m%d%H%M%S',time.localtime())
835          self.Fich[0] = open(self.NomFich[0],'w')
836       # initialise le graph
837       self._FermFich()
838       nbsets, x0, x1, y0, y1 = IniGrace(self.NomFich[0])
839       NumSetIni = nbsets+1
840       g.SetExtrema(0.05, x0, x1, y0, y1, force=False)
841       # si Min/Max incohérents
842       if g.Echelle_X=='LOG':
843          g.Grille_X=10
844          if g.Min_X < 0.:
845             if g.BBXmin < 0.:
846                UTMESS('A', 'TraceXmgrace', 'On limite la fenetre aux abscisses positives.')
847             g.Min_X=g.MinP_X
848       if g.Echelle_Y=='LOG':
849          g.Grille_Y=10
850          if g.Min_Y < 0.:
851             if g.BBYmin < 0.:
852                UTMESS('A', 'TraceXmgrace', 'On limite la fenetre aux ordonnées positives.')
853             g.Min_Y=g.MinP_Y
854       
855       if g.NbCourbe < 1:
856          self._FermFich()
857          return
858       # cohérence des valeurs par défaut
859       if g.Grille_X<0 or g.Grille_Y<0:
860          deltaX=g.Max_X-g.Min_X
861          deltaY=g.Max_Y-g.Min_Y
862          g.Grille_X=deltaX/5.
863          g.Grille_Y=deltaY/5.
864          if deltaX>4:
865             g.Grille_X=int(round(g.Grille_X))
866          if deltaY>4:
867             g.Grille_Y=int(round(g.Grille_Y))
868          if g.Grille_X == 0.:
869             g.Grille_X = 1.e-6
870          if g.Grille_Y == 0.:
871             g.Grille_Y = 1.e-6
872       # entete
873       content = self.Entete()
874       content.append('')
875       # valeurs
876       it=-1
877       for i in range(g.NbCourbe):
878          dCi=g.Courbe(i)
879          for k in range(dCi['NbCol']-1):
880             it=it+1
881             dCi['NumSet'] = NumSetIni + it
882             content.extend(self.DescrCourbe(**dCi))
883             content.append('')
884       # partie données (.dat)
885       it=-1
886       for i in range(g.NbCourbe):
887          dCi=g.Courbe(i)
888          for k in range(dCi['NbCol']-1):
889             it=it+1
890             content.append('@target g0.s%d' % (NumSetIni + it))
891             content.append('@type xy')
892             listX, listY = Tri(g.Tri, lx=dCi['Abs'], ly=dCi['Ord'][k])
893             for j in range(dCi['NbPts']):
894                svX = self.DicForm['formR'] % listX[j]
895                svY = self.DicForm['formR'] % listY[j]
896                content.append(self.DicForm['formR'] % listX[j] + \
897                   ' ' + self.DicForm['formR'] % listY[j])
898             content.append('&')
899       content.append('')
900       
901       # Production du fichier postscript, jpeg ou lancement interactif
902       pilo=self.PILOTE
903       if pilo == '':
904          self._OuvrFich()
905          self.Fich[0].write('\n'.join(content))
906          self._FermFich()
907       else:
908          xmgr=os.path.join(aster.repout(),'xmgrace')
909          nfwrk = self.NomFich[0]+'.wrk'
910          open(nfwrk, 'w').write('\n'.join(content))
911          nfhard = self.NomFich[0]+'.hardcopy'
912          # nom exact du pilote
913          if pilo == 'POSTSCRIPT':
914             pilo = 'PostScript'
915          elif pilo == 'INTERACTIF':
916             pilo = 'X11'
917          # ligne de commande
918          if pilo == 'X11':
919             lcmde = '%s %s' % (xmgr, nfwrk)
920             if not os.environ.has_key('DISPLAY') or os.environ['DISPLAY']=='':
921                os.environ['DISPLAY']=':0.0'
922                UTMESS('A','TraceXmgrace','Variable DISPLAY non définie')
923             UTMESS('I','TraceXmgrace','on fixe le DISPLAY à %s' % os.environ['DISPLAY'])
924          else:
925             if os.path.exists(os.path.join(aster.repout(),'gracebat')):
926                xmgr = os.path.join(aster.repout(),'gracebat')
927             lcmde = '%s -hdevice %s -hardcopy -printfile %s %s' % (xmgr, pilo, nfhard, nfwrk)
928          # appel xmgrace
929          UTMESS('I','TraceXmgrace','Lancement de : '+lcmde)
930          if not os.path.exists(xmgr):
931             UTMESS('S','TraceXmgrace','Fichier inexistant : '+xmgr)
932          iret = os.system(lcmde)
933          if iret == 0 or os.path.exists(nfhard):
934             if pilo not in ('', 'X11'):
935                new = open(nfhard, 'r').read()
936                open(self.NomFich[0], 'a').write(new)
937          else:
938             UTMESS('A','TraceXmgrace', "Erreur lors de l'utilisation du filtre %s" \
939                   "\nLe fichier retourné est le fichier '.agr'" % pilo)
940       # menage
941       if self.PILOTE == 'INTERACTIF':
942          os.remove(self.NomFich[0])
943       return
944
945 # ------------------------------------------------------------------------------
946 # ------------------------------------------------------------------------------
947 # ------------------------------------------------------------------------------
948 class TraceAgraf(TraceGraph):
949    """
950    Impression d'un objet Graph au format AGRAF.
951    """
952 # ------------------------------------------------------------------------------
953    def Entete(self):
954       """Retourne l'entete des directives Agraf"""
955       dic_ech={ 'LIN' : '0', 'LOG' : '1' }
956       g=self.Graph
957       entete=[]
958       entete.append("""
959 ASPECT_GRAPHIQUE:
960   En-tete :Departement Analyses Mecaniques et Acoustique
961   Aspect :0
962   Nombre de vues :1
963   Cesure commentaire :40
964   MinMax :0
965   Fonte Titre :%helvetica-14
966   Fonte Axes :%courier-12
967   Fonte Autre :%times-12
968
969   DEFAUT_COURBE:
970     Couleur (rvb) :     0     0     0
971
972   DEFAUT_COURBE:
973     Couleur (rvb) : 65535     0     0
974
975   DEFAUT_COURBE:
976     Couleur (rvb) : 11822 35723 22359
977
978   DEFAUT_COURBE:
979     Couleur (rvb) :     0     0 65535
980
981   DEFAUT_COURBE:
982     Couleur (rvb) : 65535     0 65535
983
984   DEFAUT_COURBE:
985     Couleur (rvb) :     0 65535 65535
986
987   DEFAUT_COURBE:
988     Couleur (rvb) :     0 65535     0
989
990   DEFAUT_COURBE:
991     Couleur (rvb) : 41120 21074 11565
992
993   DEFAUT_COURBE:
994     Couleur (rvb) : 65535 42405     0
995
996   DEFAUT_COURBE:
997     Couleur (rvb) : 41120  8224 61680
998
999   DEFAUT_COURBE:
1000     Couleur (rvb) : 65535 65535     0
1001
1002   DEFAUT_COURBE:
1003     Couleur (rvb) : 53970 46260 35980
1004
1005 GRAPHIQUE:
1006 """)
1007       if g.Titre=='':
1008          g.Titre='GRAPHIQUE CODE_ASTER'
1009       entete.append('Titre :'+g.Titre+'\n')
1010       if g.SousTitre<>'':
1011          entete.append('Commentaire :'+g.SousTitre+'\n')
1012       entete.append('Frequence Grille X :'+str(int(g.Grille_X))+'\n')
1013       entete.append('Frequence Grille Y :'+str(int(g.Grille_Y))+'\n')
1014       entete.append('Echelle X :'+dic_ech[g.Echelle_X]+'\n')
1015       entete.append('Echelle Y :'+dic_ech[g.Echelle_Y]+'\n')
1016       if g.Legende_X<>'':
1017          entete.append('Legende X :'+g.Legende_X+'\n')
1018       if g.Legende_Y<>'':
1019          entete.append('Legende Y :'+g.Legende_Y+'\n')
1020       entete.append('Min X : '+str(g.Min_X)+'\n')
1021       entete.append('Max X : '+str(g.Max_X)+'\n')
1022       entete.append('Min Y : '+str(g.Min_Y)+'\n')
1023       entete.append('Max Y : '+str(g.Max_Y)+'\n')
1024
1025       return entete
1026 # ------------------------------------------------------------------------------
1027    def DescrCourbe(self,**args):
1028       """Retourne la chaine de caractères décrivant les paramètres de la courbe.
1029       """
1030       # valeurs par défaut
1031       sty   = str(ValCycl(args['Sty'],0,2,0))
1032       color = str(ValCycl(args['Coul'],0,12,args['NumSet']))
1033       symbol= str(ValCycl(args['Marq'],0,12,args['NumSet']))
1034       freqm = str(ValCycl(args['FreqM'],0,-1,0))
1035
1036       descr=[]
1037       descr.append('  COURBE:\n')
1038       descr.append('     Trait :'+sty+'\n')
1039       descr.append('     Couleur :'+color+'\n')
1040       descr.append('     Marqueur :'+symbol+'\n')
1041       descr.append('     Frequence Marqueur :'+freqm+'\n')
1042       if args['Leg']<>'':
1043          descr.append('     Legende :'+args['Leg']+'\n')
1044       descr.append('     Tri :'+args['Tri']+'\n')
1045       descr.append('     Abscisses : [ '+str(args['Bloc'])+', '+str(args['ColX'])+']\n')
1046       descr.append('     Ordonnees : [ '+str(args['Bloc'])+', '+str(args['ColY'])+']\n')
1047       return descr
1048 # ------------------------------------------------------------------------------
1049    def Trace(self):
1050       """Méthode pour 'tracer' l'objet Graph dans un fichier.
1051       Met en page l'entete, la description des courbes et les valeurs selon
1052       le format et ferme le fichier.
1053       """
1054       self._OuvrFich()
1055       fdogr=self.Fich[0]
1056       fdigr=self.Fich[1]
1057       g=self.Graph
1058       if g.NbCourbe > 0:
1059          # cohérence des valeurs par défaut
1060          if g.Grille_X<0 or g.Grille_Y<0:
1061             g.Grille_X=0
1062             g.Grille_Y=0
1063          # entete
1064          for lig in self.Entete():
1065             fdigr.write(lig)
1066          # valeurs
1067          for i in range(g.NbCourbe):
1068             dCi=g.Courbe(i)
1069             dCi['NumSet']=i
1070             # partie directives (.digr)
1071             for k in range(dCi['NbCol']-1):
1072                dCi['Bloc']=i+1
1073                dCi['ColX']=1
1074                dCi['ColY']=k+2
1075                for lig in self.DescrCourbe(**dCi):
1076                   fdigr.write(lig)
1077             # partie données (.dogr)
1078             if dCi['Leg']<>'':
1079                leg=dCi['Leg']
1080             else:
1081                leg='COURBE_'+str(i)
1082             fdogr.write('#NOM DE LA FONCTION: '+leg+'\n')
1083             for j in range(dCi['NbPts']):
1084                for k in range(dCi['NbCol']):
1085                   sv=self.DicForm['formR'] % g.Valeurs[i][k][j]
1086                   fdogr.write(' '+sv)
1087                fdogr.write('\n')
1088             fdogr.write('\n')
1089       self._FermFich()
1090
1091 # ------------------------------------------------------------------------------
1092 # ------------------------------------------------------------------------------
1093 # ------------------------------------------------------------------------------
1094 def ValCycl(val,vmin,vmax,vdef):
1095    """
1096    Retourne une valeur entre vmin et vmax (bornes incluses) :
1097       - si val<vmin, on utilise val=vdef,
1098       - si val>vmax, on cycle tel que val=vmax+1 retourne vmin, etc.
1099       - si vmax<vmin, il n'y a pas de max
1100    """
1101    v = val
1102    if v < vmin:
1103       v = vdef
1104    if vmax < vmin:
1105       return v
1106    else:
1107       return (((v-vmin) % (vmax+1-vmin))+vmin)
1108
1109 # ------------------------------------------------------------------------------
1110 def Tri(tri, lx, ly):
1111    """Retourne les listes triées selon la valeur de tri ('X','Y','XY','YX').
1112    """
1113    dNumCol={ 'X' : 0, 'Y' : 1 }
1114    tab=Numeric.array((lx,ly),Numeric.Float64)
1115    tab=Numeric.transpose(tab)
1116    li=range(len(tri))
1117    li.reverse()
1118    for i in li:
1119       if tri[-i] in dNumCol.keys():
1120          icol=dNumCol[tri[-i]]
1121          tab = Numeric.take(tab, Numeric.argsort(tab[:,icol]))
1122    return [ tab[:,0].tolist(), tab[:,1].tolist() ]
1123
1124 # ------------------------------------------------------------------------------
1125 def AjoutParaCourbe(dCourbe, args):
1126    """Ajoute les arguments fournis par l'utilisateur (args) dans le dictionnaire
1127    décrivant la courbe (dCourbe).
1128    """
1129    # correspondance : mot-clé Aster / clé du dico de l'objet Graph
1130    keys={
1131       'LEGENDE'         : 'Leg',
1132       'STYLE'           : 'Sty',
1133       'COULEUR'         : 'Coul',
1134       'MARQUEUR'        : 'Marq',
1135       'FREQ_MARQUEUR'   : 'FreqM',
1136       'TRI'             : 'Tri',
1137    }
1138    for mc, key in keys.items():
1139       if args.has_key(mc):
1140          dCourbe[key]=args[mc]
1141
1142 # ------------------------------------------------------------------------------
1143 def IniGrace(fich):
1144    """Retourne le numéro de la dernière courbe d'un fichier xmgrace (sinon 0).
1145    """
1146    ns=0
1147    x0=None
1148    x1=None
1149    y0=None
1150    y1=None
1151    if os.path.exists(fich) and os.stat(fich).st_size<>0:
1152       os.rename(fich, fich+'.prev')
1153       fpre=open(fich+'.prev', 'r')
1154       fnew=open(fich,         'w')
1155       for line in fpre:
1156          ikeep=True
1157          mat=re.search('@target g[0-9]+\.s([0-9]+)', line)
1158          if mat<>None and int(mat.group(1))>ns:
1159             ns=int(mat.group(1))
1160          mat=re.search('@[ ]+world[ ]+xmin[ ]+([\-\+\.0-9eEdD]+)', line)
1161          if mat<>None:
1162             try:
1163                x0=float(mat.group(1))
1164                ikeep=False
1165             except ValueError:
1166                pass
1167          mat=re.search('@[ ]+world[ ]+xmax[ ]+([\-\+\.0-9eEdD]+)', line)
1168          if mat<>None:
1169             try:
1170                x1=float(mat.group(1))
1171                ikeep=False
1172             except ValueError:
1173                pass
1174          mat=re.search('@[ ]+world[ ]+ymin[ ]+([\-\+\.0-9eEdD]+)', line)
1175          if mat<>None:
1176             try:
1177                y0=float(mat.group(1))
1178                ikeep=False
1179             except ValueError:
1180                pass
1181          mat=re.search('@[ ]+world[ ]+ymax[ ]+([\-\+\.0-9eEdD]+)', line)
1182          if mat<>None:
1183             try:
1184                y1=float(mat.group(1))
1185                ikeep=False
1186             except ValueError:
1187                pass
1188          if ikeep:
1189             fnew.write(line)
1190       fpre.close()
1191       fnew.close()
1192       try:
1193          UTMESS('I', 'Graph.IniGrace', """
1194    <I> Informations sur le fichier '%s' :
1195       Nombre de courbes    : %3d
1196       Bornes des abscisses : [ %13.6G , %13.6G ]
1197       Bornes des ordonnées : [ %13.6G , %13.6G ]
1198 """ % (fich, ns, x0, x1, y0, y1))
1199       except TypeError:
1200          # pas un format xmgrace
1201          pass
1202    return ns, x0, x1, y0, y1