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.
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.
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 # ======================================================================
21 # RESPONSABLE MCOURTOI M.COURTOIS
22 __all__ = ['Graph', 'AjoutParaCourbe']
33 # try/except pour utiliser hors aster
38 def repout(self): return '/opt/aster/outils'
41 from Macro.externe_mess import UTMESS
43 if not sys.modules.has_key('Table'):
45 from Utilitai import Table
50 # ------------------------------------------------------------------------------
52 """Cette classe définit l'objet Graph pour Code_Aster.
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...
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',
70 Pour Lignes, Couleurs, Marqueurs, FreqMarq, -1 signifie valeur par défaut
74 .Titre : titre du graphique
75 .SousTitre : sous-titre (appelé commentaire dans agraf)
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)
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é
89 # ------------------------------------------------------------------------------
91 """Construction + valeurs par défaut des attributs
107 self.MinP_X = 1.e+99 # minimum > 0 pour les échelles LOG
111 self.Echelle_X = 'LIN'
112 self.Echelle_Y = 'LIN'
115 # attributs que l'utilisateur ne doit pas modifier
116 self.NbCourbe = len(self.Valeurs)
118 self.BBXmax = -1.e+99
120 self.BBYmax = -1.e+99
121 # pour conserver les paramètres du dernier tracé
122 self.LastTraceArgs = {}
123 self.LastTraceFormat = ''
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.
131 if x0<>None: self.BBXmin=min([self.BBXmin, x0])
132 if x1<>None: self.BBXmax=max([self.BBXmax, x1])
134 dx=max(self.BBXmax-self.BBXmin,0.01*self.BBXmax)
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.
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.
148 if y0<>None: self.BBYmin=min([self.BBYmin, y0])
149 if y1<>None: self.BBYmax=max([self.BBYmax, y1])
151 dy=max(self.BBYmax-self.BBYmin,0.01*self.BBYmax)
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.
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.
165 self.SetExtremaX(marge, x0, x1, force=force)
166 self.SetExtremaY(marge, y0, y1, force=force)
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
175 debut=self.NbCourbe-1
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])
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]
207 Lab : liste de 2 chaines (ou 3 si complexe)
212 Tri : chaine de caractères : N, X, Y, XY ou YX
213 Met à jour les attributs : NbCourbe, BBXmin/Xmax/Ymin/Ymax
215 nbc = len(Val) # nombre de colonnes : 2 ou 3
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')
226 UTMESS('S','Graph','"Lab" doit etre une liste de 2 ou 3 chaines')
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)
238 self.NbCourbe = self.NbCourbe + 1
241 # ------------------------------------------------------------------------------
243 """Permet de récupérer les données de la courbe d'indice n sous forme
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
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
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.
273 'TABLEAU' : { 'mode' : 'a', 'driver' : TraceTableau, },
274 'XMGRACE' : { 'mode' : 'a', 'driver' : TraceXmgrace, },
275 'AGRAF' : { 'mode' : 'a', 'driver' : TraceAgraf, },
278 if self.LastTraceArgs=={}:
279 kargs['FICHIER']=FICHIER
283 kargs=self.LastTraceArgs.copy()
285 FORMAT=self.LastTraceFormat
287 kargs['FICHIER']=FICHIER
292 if not FORMAT in para.keys():
293 UTMESS('A', 'Objet Graph', 'Format inconnu : %s' % FORMAT)
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 # ------------------------------------------------------------------------------
302 """Affichage du contenu d'un Graph"""
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)))
308 # ------------------------------------------------------------------------------
309 # ------------------------------------------------------------------------------
310 # ------------------------------------------------------------------------------
313 Cette classe définit le tracé d'un objet Graph dans un fichier.
316 .NomFich : liste de noms de fichier de sortie
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...)
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.
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).
334 # attributs optionnels (au début pour éviter un écrasement maladroit !)
335 for k,v in opts.items():
338 # Ouverture du(des) fichier(s)
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[:]
345 # dans ce cas, on écrira sur stdout (augmenter le 2 éventuellement)
346 self.NomFich=[None]*2
348 for ff in self.NomFich:
350 self.Fich.append(open(ff,fmod))
352 self.Fich.append(sys.stdout)
354 # objet Graph sous-jacent
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)
362 if graph.Echelle_X=='LOG':
364 # verif si Min<0 à cause de la marge
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':
372 if graph.BBYmin < 0.:
373 UTMESS('A', 'Graph', 'On limite la fenetre aux ordonnées positives.')
374 graph.Min_Y=graph.MinP_Y
376 # formats de base (identiques à ceux du module Table)
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
386 if dform<>None and type(dform)==types.DictType:
387 self.DicForm.update(dform)
392 # ------------------------------------------------------------------------------
394 """Fermeture du(des) fichier(s) à la destruction"""
395 if hasattr(self,'Fich'):
397 # ------------------------------------------------------------------------------
399 """Fermeture du(des) fichier(s)"""
403 # ------------------------------------------------------------------------------
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
410 if self.Fich[i].closed:
411 self.Fich[i]=open(self.NomFich[i],self.Fich[i].mode)
413 # ------------------------------------------------------------------------------
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.
421 raise NotImplementedError, "Cette méthode doit etre définie par la classe fille."
422 # ------------------------------------------------------------------------------
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.
428 raise NotImplementedError, "Cette méthode doit etre définie par la classe fille."
431 # ------------------------------------------------------------------------------
432 # ------------------------------------------------------------------------------
433 # ------------------------------------------------------------------------------
434 class TraceTableau(TraceGraph):
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.
441 # ------------------------------------------------------------------------------
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.
451 # validité des données (abscisses identiques)
452 t0=Numeric.array(g.Courbe(0)['Abs'])
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)
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.")
469 tit.append(self.DicForm['ccom']+' '+g.Titre)
470 tit.append(self.DicForm['ccom']+' '+g.SousTitre)
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:]:
481 Tab.type=['R']*len(Tab.para)
484 for j in range(dC0['NbPts']):
486 row[dC0['LabAbs']]=dC0['Abs'][j]
487 for i in range(g.NbCourbe):
489 for k in range(dCi['NbCol']-1):
491 row[dCi['LabOrd'][k]]=dCi['Ord'][k][j]
493 row[dCi['LabOrd'][k]]=None
495 Tab.Impr(FICHIER=self.NomFich[0], FORMAT='TABLEAU')
498 UTMESS('A', 'Graph.TraceTableau', '\n'.join(msg))
501 # ------------------------------------------------------------------------------
502 # ------------------------------------------------------------------------------
503 # ------------------------------------------------------------------------------
504 class TraceXmgrace(TraceGraph):
506 Impression d'un objet Graph au format XMGRACE.
507 Attribut supplémentaire : .PILOTE
510 # ------------------------------------------------------------------------------
512 """Retourne l'entete du fichier .agr correspondant à la mise en forme
514 dic_ech={ 'LIN' : 'Normal', 'LOG' : 'Logarithmic' }
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"
559 @default linewidth 1.0
564 @default char size 1.000000
565 @default symbol size 1.000000
566 @default sformat "%.8g"
568 @page background fill on
608 @g0 bar hgap 0.000000
610 @ stack world 0, 0, 0, 0
617 @ title size 1.500000
620 @ subtitle size 1.000000
625 @ xaxis type zero false
626 @ xaxis offset 0.000000 , 0.000000
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
635 @ xaxis label color 1
636 @ xaxis label place normal
638 @ xaxis tick minor ticks 1
639 @ xaxis tick default 6
640 @ xaxis tick place rounded true
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
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
674 @ yaxis type zero false
675 @ yaxis offset 0.000000 , 0.000000
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
684 @ yaxis label color 1
685 @ yaxis label place normal
687 @ yaxis tick minor ticks 1
688 @ yaxis tick default 6
689 @ yaxis tick place rounded true
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
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
725 @ legend loctype view
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
734 @ legend char size 0.750000
739 @ legend invert false
742 @ frame linewidth 1.0
745 @ frame background color 0
746 @ frame background pattern 0
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))
761 # ------------------------------------------------------------------------------
762 def DescrCourbe(self,**args):
763 """Retourne la chaine de caractères décrivant les paramètres de la courbe.
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))
771 sn=str(args['NumSet'])
773 descr.append(string.replace("""
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
782 @ s0 symbol char font 0
784 @ s0 line linewidth 1.0
794 @ s0 avalue char size 1.000000
797 @ s0 avalue format general
799 @ s0 avalue prepend ""
800 @ s0 avalue append ""
801 @ s0 avalue offset 0.000000 , 0.000000
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
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']+'"')
826 # ------------------------------------------------------------------------------
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.
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
838 nbsets, x0, x1, y0, y1 = IniGrace(self.NomFich[0])
840 g.SetExtrema(0.05, x0, x1, y0, y1, force=False)
841 # si Min/Max incohérents
842 if g.Echelle_X=='LOG':
846 UTMESS('A', 'TraceXmgrace', 'On limite la fenetre aux abscisses positives.')
848 if g.Echelle_Y=='LOG':
852 UTMESS('A', 'TraceXmgrace', 'On limite la fenetre aux ordonnées positives.')
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
865 g.Grille_X=int(round(g.Grille_X))
867 g.Grille_Y=int(round(g.Grille_Y))
873 content = self.Entete()
877 for i in range(g.NbCourbe):
879 for k in range(dCi['NbCol']-1):
881 dCi['NumSet'] = NumSetIni + it
882 content.extend(self.DescrCourbe(**dCi))
884 # partie données (.dat)
886 for i in range(g.NbCourbe):
888 for k in range(dCi['NbCol']-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])
901 # Production du fichier postscript, jpeg ou lancement interactif
905 self.Fich[0].write('\n'.join(content))
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':
915 elif pilo == 'INTERACTIF':
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'])
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)
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)
938 UTMESS('A','TraceXmgrace', "Erreur lors de l'utilisation du filtre %s" \
939 "\nLe fichier retourné est le fichier '.agr'" % pilo)
941 if self.PILOTE == 'INTERACTIF':
942 os.remove(self.NomFich[0])
945 # ------------------------------------------------------------------------------
946 # ------------------------------------------------------------------------------
947 # ------------------------------------------------------------------------------
948 class TraceAgraf(TraceGraph):
950 Impression d'un objet Graph au format AGRAF.
952 # ------------------------------------------------------------------------------
954 """Retourne l'entete des directives Agraf"""
955 dic_ech={ 'LIN' : '0', 'LOG' : '1' }
960 En-tete :Departement Analyses Mecaniques et Acoustique
963 Cesure commentaire :40
965 Fonte Titre :%helvetica-14
966 Fonte Axes :%courier-12
967 Fonte Autre :%times-12
970 Couleur (rvb) : 0 0 0
973 Couleur (rvb) : 65535 0 0
976 Couleur (rvb) : 11822 35723 22359
979 Couleur (rvb) : 0 0 65535
982 Couleur (rvb) : 65535 0 65535
985 Couleur (rvb) : 0 65535 65535
988 Couleur (rvb) : 0 65535 0
991 Couleur (rvb) : 41120 21074 11565
994 Couleur (rvb) : 65535 42405 0
997 Couleur (rvb) : 41120 8224 61680
1000 Couleur (rvb) : 65535 65535 0
1003 Couleur (rvb) : 53970 46260 35980
1008 g.Titre='GRAPHIQUE CODE_ASTER'
1009 entete.append('Titre :'+g.Titre+'\n')
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')
1017 entete.append('Legende X :'+g.Legende_X+'\n')
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')
1026 # ------------------------------------------------------------------------------
1027 def DescrCourbe(self,**args):
1028 """Retourne la chaine de caractères décrivant les paramètres de la courbe.
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))
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')
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')
1048 # ------------------------------------------------------------------------------
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.
1059 # cohérence des valeurs par défaut
1060 if g.Grille_X<0 or g.Grille_Y<0:
1064 for lig in self.Entete():
1067 for i in range(g.NbCourbe):
1070 # partie directives (.digr)
1071 for k in range(dCi['NbCol']-1):
1075 for lig in self.DescrCourbe(**dCi):
1077 # partie données (.dogr)
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]
1091 # ------------------------------------------------------------------------------
1092 # ------------------------------------------------------------------------------
1093 # ------------------------------------------------------------------------------
1094 def ValCycl(val,vmin,vmax,vdef):
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
1107 return (((v-vmin) % (vmax+1-vmin))+vmin)
1109 # ------------------------------------------------------------------------------
1110 def Tri(tri, lx, ly):
1111 """Retourne les listes triées selon la valeur de tri ('X','Y','XY','YX').
1113 dNumCol={ 'X' : 0, 'Y' : 1 }
1114 tab=Numeric.array((lx,ly),Numeric.Float64)
1115 tab=Numeric.transpose(tab)
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() ]
1124 # ------------------------------------------------------------------------------
1125 def AjoutParaCourbe(dCourbe, args):
1126 """Ajoute les arguments fournis par l'utilisateur (args) dans le dictionnaire
1127 décrivant la courbe (dCourbe).
1129 # correspondance : mot-clé Aster / clé du dico de l'objet Graph
1134 'MARQUEUR' : 'Marq',
1135 'FREQ_MARQUEUR' : 'FreqM',
1138 for mc, key in keys.items():
1139 if args.has_key(mc):
1140 dCourbe[key]=args[mc]
1142 # ------------------------------------------------------------------------------
1144 """Retourne le numéro de la dernière courbe d'un fichier xmgrace (sinon 0).
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')
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)
1163 x0=float(mat.group(1))
1167 mat=re.search('@[ ]+world[ ]+xmax[ ]+([\-\+\.0-9eEdD]+)', line)
1170 x1=float(mat.group(1))
1174 mat=re.search('@[ ]+world[ ]+ymin[ ]+([\-\+\.0-9eEdD]+)', line)
1177 y0=float(mat.group(1))
1181 mat=re.search('@[ ]+world[ ]+ymax[ ]+([\-\+\.0-9eEdD]+)', line)
1184 y1=float(mat.group(1))
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))
1200 # pas un format xmgrace
1202 return ns, x0, x1, y0, y1