-#@ MODIF Graph Utilitai DATE 24/05/2005 AUTEUR MCOURTOI M.COURTOIS
+#@ MODIF Graph Utilitai DATE 02/05/2006 AUTEUR MCOURTOI M.COURTOIS
# -*- coding: iso-8859-1 -*-
# CONFIGURATION MANAGEMENT OF EDF VERSION
# ======================================================================
# ======================================================================
# RESPONSABLE MCOURTOI M.COURTOIS
+__all__ = ['Graph', 'AjoutParaCourbe']
import sys
import os
self.Tri = []
self.Titre = ''
self.SousTitre = ''
- self.Min_X = 1.e+99
- self.Max_X = -1.e+99
- self.Min_Y = 1.e+99
+ self.Min_X = None
+ self.Max_X = None
+ self.Min_Y = None
+ self.Max_Y = None
self.MinP_X = 1.e+99 # minimum > 0 pour les échelles LOG
self.MinP_Y = 1.e+99
- self.Max_Y = -1.e+99
self.Legende_X = ''
self.Legende_Y = ''
self.Echelle_X = 'LIN'
self.Grille_Y = -1
# attributs que l'utilisateur ne doit pas modifier
self.NbCourbe = len(self.Valeurs)
- self.BBXmin = self.Min_X
- self.BBXmax = self.Max_X
- self.BBYmin = self.Min_Y
- self.BBYmax = self.Max_Y
+ self.BBXmin = 1.e+99
+ self.BBXmax = -1.e+99
+ self.BBYmin = 1.e+99
+ self.BBYmax = -1.e+99
# pour conserver les paramètres du dernier tracé
self.LastTraceArgs = {}
self.LastTraceFormat = ''
- return
+
# ------------------------------------------------------------------------------
- def SetExtrema(self,marge=0., x0=None, x1=None, y0=None, y1=None):
- """Remplit les limites du tracé (Min/Max_X/Y) avec les valeurs de la
+ def SetExtremaX(self,marge=0., x0=None, x1=None, force=True):
+ """Remplit les limites du tracé (Min/Max_X) avec les valeurs de la
bounding box +/- avec une 'marge'*(Max-Min)/2.
- x0,x1,y0,y1 permettent de modifier la bb.
+ x0,x1 permettent de modifier la bb.
"""
if x0<>None: self.BBXmin=min([self.BBXmin, x0])
if x1<>None: self.BBXmax=max([self.BBXmax, x1])
+
+ dx=max(self.BBXmax-self.BBXmin,0.01*self.BBXmax)
+ if dx == 0.:
+ dx = 1.e-6
+ if force or self.Min_X==None:
+ self.Min_X = self.BBXmin - marge*dx/2.
+ if force or self.Max_X==None:
+ self.Max_X = self.BBXmax + marge*dx/2.
+ return
+
+ def SetExtremaY(self,marge=0., y0=None, y1=None, force=True):
+ """Remplit les limites du tracé (Min/Max_Y) avec les valeurs de la
+ bounding box +/- avec une 'marge'*(Max-Min)/2.
+ y0,y1 permettent de modifier la bb.
+ """
if y0<>None: self.BBYmin=min([self.BBYmin, y0])
if y1<>None: self.BBYmax=max([self.BBYmax, y1])
- dx=max(self.BBXmax-self.BBXmin,0.01*self.BBXmax)
- self.Min_X = self.BBXmin - marge*dx/2.
- self.Max_X = self.BBXmax + marge*dx/2.
dy=max(self.BBYmax-self.BBYmin,0.01*self.BBYmax)
- self.Min_Y = self.BBYmin - marge*dy/2.
- self.Max_Y = self.BBYmax + marge*dy/2.
+ if dy == 0.:
+ dy = 1.e-6
+ if force or self.Min_Y==None:
+ self.Min_Y = self.BBYmin - marge*dy/2.
+ if force or self.Max_Y==None:
+ self.Max_Y = self.BBYmax + marge*dy/2.
+ return
+
+ def SetExtrema(self,marge=0., x0=None, x1=None, y0=None, y1=None, force=True):
+ """Remplit les limites du tracé (Min/Max_X/Y) avec les valeurs de la
+ bounding box +/- avec une 'marge'*(Max-Min)/2.
+ x0,x1,y0,y1 permettent de modifier la bb.
+ """
+ self.SetExtremaX(marge, x0, x1, force=force)
+ self.SetExtremaY(marge, y0, y1, force=force)
return
# ------------------------------------------------------------------------------
def AutoBB(self,debut=-1):
if opts<>{}:
kargs['opts']=opts
if not FORMAT in para.keys():
- print ' <A> <Objet Graph> Format inconnu : %s' % FORMAT
+ UTMESS('A', 'Objet Graph', 'Format inconnu : %s' % FORMAT)
else:
kargs['fmod']=para[FORMAT]['mode']
self.LastTraceArgs = kargs.copy()
# objet Graph sous-jacent
self.Graph=graph
# si Min/Max incohérents
- if graph.Min_X > graph.Max_X or graph.Min_Y > graph.Max_Y:
- graph.SetExtrema(marge=0.05)
- if graph.Min_X < 0. and graph.Echelle_X=='LOG':
- graph.Min_X=graph.MinP_X
- if graph.Min_Y < 0. and graph.Echelle_Y=='LOG':
- graph.Min_Y=graph.MinP_Y
+ if graph.Min_X==None or graph.Max_X==None or graph.Min_X > graph.Max_X:
+ graph.SetExtremaX(marge=0.05, force=True)
+ if graph.Min_Y==None or graph.Max_Y==None or graph.Min_Y > graph.Max_Y:
+ graph.SetExtremaY(marge=0.05, force=True)
+
+ if graph.Echelle_X=='LOG':
+ graph.Grille_X=10
+ # verif si Min<0 à cause de la marge
+ if graph.Min_X < 0.:
+ if graph.BBXmin < 0.:
+ UTMESS('A', 'Graph', 'On limite la fenetre aux abscisses positives.')
+ graph.Min_X=graph.MinP_X
+ if graph.Echelle_Y=='LOG':
+ graph.Grille_Y=10
+ if graph.Min_Y < 0.:
+ if graph.BBYmin < 0.:
+ UTMESS('A', 'Graph', 'On limite la fenetre aux ordonnées positives.')
+ graph.Min_Y=graph.MinP_Y
# formats de base (identiques à ceux du module Table)
self.DicForm={
# let's go
self.Trace()
- return
+
# ------------------------------------------------------------------------------
def __del__(self):
"""Fermeture du(des) fichier(s) à la destruction"""
# ------------------------------------------------------------------------------
def Entete(self):
"""Retourne l'entete"""
- raise StandardError, "Cette méthode doit etre définie par la classe fille."
+ raise NotImplementedError, "Cette méthode doit etre définie par la classe fille."
# ------------------------------------------------------------------------------
def DescrCourbe(self,**args):
"""Retourne la chaine de caractères décrivant les paramètres de la courbe.
"""
- raise StandardError, "Cette méthode doit etre définie par la classe fille."
+ raise NotImplementedError, "Cette méthode doit etre définie par la classe fille."
# ------------------------------------------------------------------------------
def Trace(self):
"""Méthode pour 'tracer' l'objet Graph dans un fichier.
Met en page l'entete, la description des courbes et les valeurs selon
le format et ferme le fichier.
"""
- raise StandardError, "Cette méthode doit etre définie par la classe fille."
+ raise NotImplementedError, "Cette méthode doit etre définie par la classe fille."
# ------------------------------------------------------------------------------
max0=max(abs(t0))
for i in range(1,g.NbCourbe):
if g.Courbe(i)['NbPts']<>g.Courbe(0)['NbPts']:
- msg.append(" <A> <TraceTableau> La courbe %d n'a pas le meme " \
+ msg.append("La courbe %d n'a pas le meme " \
"nombre de points que la 1ère." % i)
else:
ti=Numeric.array(g.Courbe(i)['Abs'])
if max(abs((ti-t0).flat)) > self.EPSILON*max0:
- msg.append(" <A> <TraceTableau> Courbe %d : écart entre les "\
+ msg.append("Courbe %d : écart entre les "\
"abscisses supérieur à %9.2E" % (i+1,self.EPSILON))
msg.append(" Utilisez IMPR_FONCTION pour interpoler " \
"les valeurs sur la première liste d'abscisses.")
Tab.Impr(FICHIER=self.NomFich[0], FORMAT='TABLEAU')
# erreurs ?
if msg:
- print '\n'.join(msg)
+ UTMESS('A', 'Graph.TraceTableau', '\n'.join(msg))
return
# ------------------------------------------------------------------------------
Met en page l'entete, la description des courbes et les valeurs selon
le format et ferme le fichier.
"""
- g=self.Graph
- if self.PILOTE=='INTERACTIF':
- self.NomFich[0]='Trace_'+time.strftime('%y%m%d%H%M%S',time.localtime())+'.dat'
- self.Fich[0]=open(self.NomFich[0],'w')
+ g = self.Graph
+ if self.PILOTE == 'INTERACTIF':
+ self.NomFich[0] = 'Trace_%s.dat' % time.strftime('%y%m%d%H%M%S',time.localtime())
+ self.Fich[0] = open(self.NomFich[0],'w')
# initialise le graph
self._FermFich()
nbsets, x0, x1, y0, y1 = IniGrace(self.NomFich[0])
NumSetIni = nbsets+1
- g.SetExtrema(0.05, x0, x1, y0, y1)
+ g.SetExtrema(0.05, x0, x1, y0, y1, force=False)
# si Min/Max incohérents
- if g.Min_X < 0. and g.Echelle_X=='LOG':
- g.Min_X=g.MinP_X
- if g.Min_Y < 0. and g.Echelle_Y=='LOG':
- g.Min_Y=g.MinP_Y
+ if g.Echelle_X=='LOG':
+ g.Grille_X=10
+ if g.Min_X < 0.:
+ if g.BBXmin < 0.:
+ UTMESS('A', 'TraceXmgrace', 'On limite la fenetre aux abscisses positives.')
+ g.Min_X=g.MinP_X
+ if g.Echelle_Y=='LOG':
+ g.Grille_Y=10
+ if g.Min_Y < 0.:
+ if g.BBYmin < 0.:
+ UTMESS('A', 'TraceXmgrace', 'On limite la fenetre aux ordonnées positives.')
+ g.Min_Y=g.MinP_Y
- self._OuvrFich()
- fich=self.Fich[0]
if g.NbCourbe < 1:
self._FermFich()
return
g.Grille_X=int(round(g.Grille_X))
if deltaY>4:
g.Grille_Y=int(round(g.Grille_Y))
+ if g.Grille_X == 0.:
+ g.Grille_X = 1.e-6
+ if g.Grille_Y == 0.:
+ g.Grille_Y = 1.e-6
# entete
- fich.write('\n'.join(self.Entete()))
- fich.write('\n')
+ content = self.Entete()
+ content.append('')
# valeurs
it=-1
for i in range(g.NbCourbe):
for k in range(dCi['NbCol']-1):
it=it+1
dCi['NumSet'] = NumSetIni + it
- fich.write('\n'.join(self.DescrCourbe(**dCi)))
- fich.write('\n')
+ content.extend(self.DescrCourbe(**dCi))
+ content.append('')
# partie données (.dat)
- lig=[]
it=-1
for i in range(g.NbCourbe):
dCi=g.Courbe(i)
for k in range(dCi['NbCol']-1):
it=it+1
- lig.append('@target g0.s%d' % (NumSetIni + it))
- lig.append('@type xy')
+ content.append('@target g0.s%d' % (NumSetIni + it))
+ content.append('@type xy')
listX, listY = Tri(g.Tri, lx=dCi['Abs'], ly=dCi['Ord'][k])
for j in range(dCi['NbPts']):
- svX=self.DicForm['formR'] % listX[j]
- svY=self.DicForm['formR'] % listY[j]
- lig.append(self.DicForm['formR'] % listX[j] + \
+ svX = self.DicForm['formR'] % listX[j]
+ svY = self.DicForm['formR'] % listY[j]
+ content.append(self.DicForm['formR'] % listX[j] + \
' ' + self.DicForm['formR'] % listY[j])
- lig.append('&')
- fich.write('\n'.join(lig))
- fich.write('\n')
- self._FermFich()
+ content.append('&')
+ content.append('')
# Production du fichier postscript, jpeg ou lancement interactif
pilo=self.PILOTE
- if self.PILOTE<>'':
+ if pilo == '':
+ self._OuvrFich()
+ self.Fich[0].write('\n'.join(content))
+ self._FermFich()
+ else:
xmgr=os.path.join(aster.repout(),'xmgrace')
- nfhard=self.NomFich[0]+'.hardcopy'
+ nfwrk = self.NomFich[0]+'.wrk'
+ open(nfwrk, 'w').write('\n'.join(content))
+ nfhard = self.NomFich[0]+'.hardcopy'
# nom exact du pilote
- if pilo=='POSTSCRIPT':
- pilo='PostScript'
- elif pilo=='INTERACTIF':
- pilo='X11'
+ if pilo == 'POSTSCRIPT':
+ pilo = 'PostScript'
+ elif pilo == 'INTERACTIF':
+ pilo = 'X11'
# ligne de commande
- if pilo=='X11':
- lcmde=xmgr+' '+self.NomFich[0]
+ if pilo == 'X11':
+ lcmde = '%s %s' % (xmgr, nfwrk)
if not os.environ.has_key('DISPLAY') or os.environ['DISPLAY']=='':
os.environ['DISPLAY']=':0.0'
UTMESS('A','TraceXmgrace','Variable DISPLAY non définie')
UTMESS('I','TraceXmgrace','on fixe le DISPLAY à %s' % os.environ['DISPLAY'])
else:
if os.path.exists(os.path.join(aster.repout(),'gracebat')):
- xmgr=os.path.join(aster.repout(),'gracebat')
- lcmde=xmgr+' -hdevice '+pilo+' -hardcopy -printfile '+nfhard+' '+self.NomFich[0]
+ xmgr = os.path.join(aster.repout(),'gracebat')
+ lcmde = '%s -hdevice %s -hardcopy -printfile %s %s' % (xmgr, pilo, nfhard, nfwrk)
# appel xmgrace
UTMESS('I','TraceXmgrace','Lancement de : '+lcmde)
if not os.path.exists(xmgr):
UTMESS('S','TraceXmgrace','Fichier inexistant : '+xmgr)
- iret=os.system(lcmde)
- if iret==0 or os.path.exists(nfhard):
- if pilo not in ['','X11']:
- os.remove(self.NomFich[0]) # necessaire sous windows
- os.rename(nfhard,self.NomFich[0])
+ iret = os.system(lcmde)
+ if iret == 0 or os.path.exists(nfhard):
+ if pilo not in ('', 'X11'):
+ new = open(nfhard, 'r').read()
+ open(self.NomFich[0], 'a').write(new)
else:
- UTMESS('A','TraceXmgrace',"Erreur lors de l'utilisation du filtre "+pilo+"\nLe fichier retourné est le fichier '.agr'")
+ UTMESS('A','TraceXmgrace', "Erreur lors de l'utilisation du filtre %s" \
+ "\nLe fichier retourné est le fichier '.agr'" % pilo)
# menage
- if self.PILOTE=='INTERACTIF':
+ if self.PILOTE == 'INTERACTIF':
os.remove(self.NomFich[0])
return
fnew.write(line)
fpre.close()
fnew.close()
- print """
+ try:
+ UTMESS('I', 'Graph.IniGrace', """
<I> Informations sur le fichier '%s' :
Nombre de courbes : %3d
Bornes des abscisses : [ %13.6G , %13.6G ]
Bornes des ordonnées : [ %13.6G , %13.6G ]
-""" % (fich, ns, x0, x1, y0, y1)
+""" % (fich, ns, x0, x1, y0, y1))
+ except TypeError:
+ # pas un format xmgrace
+ pass
return ns, x0, x1, y0, y1
-#@ MODIF Table Utilitai DATE 17/05/2005 AUTEUR DURAND C.DURAND
+#@ MODIF Table Utilitai DATE 06/11/2006 AUTEUR MCOURTOI M.COURTOIS
# -*- coding: iso-8859-1 -*-
# CONFIGURATION MANAGEMENT OF EDF VERSION
# ======================================================================
# ======================================================================
# RESPONSABLE MCOURTOI M.COURTOIS
+__all__ = ['Table', 'merge']
import sys
-import string
import re
+from copy import copy
-from types import *
-EnumTypes=(ListType, TupleType)
-NumberTypes=(IntType, LongType, FloatType, ComplexType)
+from types import ListType, TupleType, IntType, LongType, FloatType, ComplexType, \
+ DictType, StringType, StringTypes, UnicodeType, NoneType
+EnumTypes = (ListType, TupleType)
+NumberTypes = (IntType, LongType, FloatType, ComplexType)
+
+import transpose
# try/except pour utiliser hors aster
try:
from Utilitai.Utmess import UTMESS
except ImportError:
def UTMESS(code,sprg,texte):
- fmt='\n <%s> <%s> %s\n\n'
- print fmt % (code,sprg,texte)
+ fmt = '\n <%s> <%s> %s\n\n'
+ if code == 'F':
+ raise StandardError, fmt % (code,sprg,texte)
+ else:
+ print fmt % (code,sprg,texte)
if not sys.modules.has_key('Graph'):
try:
import Graph
# formats de base (identiques à ceux du module Graph)
-DicForm={
+DicForm = {
'csep' : ' ', # séparateur
'ccom' : '#', # commentaire
'cdeb' : '', # début de ligne
'cfin' : '\n', # fin de ligne
+ 'sepch' : ';', # séparateur entre deux lignes d'une cellule
'formK' : '%-8s', # chaines
'formR' : '%12.5E', # réels
'formI' : '%8d' # entiers
}
+# type par défaut des chaines de caractères
+Kdef = 'K24'
# ------------------------------------------------------------------------------
# ------------------------------------------------------------------------------
(c'est surtout utile pour vérifier que l'extraction et les filtres sur les
colonnes sont corrects).
"""
+ def __init__(self):
+ """Constructeur.
+ """
+ self.rows=None
+ self.para=None
+ self.type=None
+ self.titr=None
+
def __repr__(self):
return self.ReprTable()
- def Croise(self,**kargs):
- raise StandardError, 'Must be defined in a derived class'
+ def Croise(self, **kargs):
+ raise NotImplementedError, 'Must be defined in a derived class'
+
+ def __len__(self):
+ """Retourne le nombre de ligne dans la Table/Colonne.
+ """
+ return len(self.rows)
# ------------------------------------------------------------------------------
- def Impr(self,FICHIER=None,FORMAT='TABLEAU',dform=None,**opts):
+ def Impr(self, FICHIER=None, FORMAT='TABLEAU', dform=None, **opts):
"""Impresssion de la Table selon le format spécifié.
FICHIER : nom du(des) fichier(s). Si None, on dirige vers stdout
dform : dictionnaire de formats d'impression (format des réels,
'dform' : DicForm.copy(),
'mode' : para[FORMAT]['mode'],
}
- if dform<>None and type(dform)==DictType:
+ if dform != None and type(dform) == DictType:
kargs['dform'].update(dform)
# ajout des options
kargs.update(opts)
else:
if not type(kargs['PAGINATION']) in EnumTypes:
- ppag=[kargs['PAGINATION'],]
+ ppag = [kargs['PAGINATION'],]
else:
- ppag=list(kargs['PAGINATION'])
+ ppag = list(kargs['PAGINATION'])
del kargs['PAGINATION']
- npag=len(ppag)
+ npag = len(ppag)
# paramètres hors ceux de la pagination
- lkeep=[p for p in self.para if ppag.count(p)==0]
+ lkeep = [p for p in self.para if ppag.count(p)==0]
# création des listes des valeurs distinctes
- lvd=[]
+ lvd = []
for p in ppag:
- lvp=getattr(self,p).values()
- lvn=[]
+ lvp = getattr(self,p).values()
+ lvn = []
for it in lvp:
- if it<>None and lvn.count(it)==0:
+ if it != None and lvn.count(it) == 0:
lvn.append(it)
lvn.sort()
lvd.append(lvn)
# création des n-uplets
- s = '[['+','.join(['x'+str(i) for i in range(npag)])+'] '
- s+= ' '.join(['for x'+str(i)+' in lvd['+str(i)+']' for i in range(npag)])+']'
+ s = '[['+','.join(['x'+str(i) for i in range(npag)])+'] '
+ s += ' '.join(['for x'+str(i)+' in lvd['+str(i)+']' for i in range(npag)])+']'
try:
- lnup=eval(s)
+ lnup = eval(s)
except SyntaxError, s:
UTMESS('F','Table','Erreur lors de la construction des n-uplets')
# pour chaque n-uplet, on imprime la sous-table
for nup in lnup:
- tab=self
+ tab = self
for i in range(npag):
tab = tab & (getattr(tab,ppag[i]) == nup[i])
- sl=''
+ sl = ''
if tab.titr: sl='\n'
tab.titr += sl+ppag[i]+': '+str(nup[i])
tab[lkeep].Impr(**kargs)
if kargs.get('FICHIER')<>None:
f.close()
- def ReprTable(self,FORMAT='TABLEAU',dform=DicForm,**ignore):
+# ------------------------------------------------------------------------------
+ def ReprTable(self,FORMAT='TABLEAU',dform=None,**ignore):
"""Représentation d'une Table ou d'une Colonne sous forme d'un tableau.
"""
rows=self.rows
if not type(para) in EnumTypes:
para=[self.para,]
typ =[self.type,]
+ if dform==None:
+ dform = DicForm.copy()
# est-ce que l'attribut .type est renseigné ?
typdef=typ<>[None]*len(typ)
txt=[]
if typdef:
stype=dform['csep'].join([''] + \
[FMT(dform,'formK',typ[i],lmax[i]) % typ[i] for i in range(len(para))])
- txt.append('')
- txt.append('-'*80)
- txt.append('')
+ txt.append(dform['ccom'])
+ txt.append(dform['ccom']+'-'*80)
+ txt.append(dform['ccom'])
ASTER=(FORMAT=='ASTER')
if ASTER:
txt.append('#DEBUT_TABLE')
if ASTER:
txt.extend(['#TITRE '+lig for lig in self.titr.split('\n')])
else:
- txt.append(self.titr)
+ txt.extend([dform['ccom']+lig for lig in self.titr.split('\n')])
txt.append(dform['csep'].join(lspa))
if ASTER and typdef:
txt.append(stype)
if type(rep) is FloatType:
lig.append(FMT(dform,'formR',t,lmax[i]) % rep)
empty=False
- elif type(rep) is IntType:
+ elif type(rep) in (IntType, LongType):
lig.append(FMT(dform,'formI',t,lmax[i]) % rep)
empty=False
else:
s='\\'+s
lig.append(s)
if not empty:
- txt.append(dform['csep'].join(lig))
+ lig2 = [dform['sepch'].join(ch.splitlines()) for ch in lig]
+ txt.append(dform['csep'].join(lig2))
if ASTER:
txt.append('#FIN_TABLE')
+ # ajout du debut de ligne
+ if dform['cdeb']<>'':
+ txt=[dform['cdeb']+t for t in txt]
+
return dform['cfin'].join(txt)
# ------------------------------------------------------------------------------
def ImprTabCroise(self,**kargs):
kargs['FORMAT']='TABLEAU'
tabc.Impr(**kargs)
# ------------------------------------------------------------------------------
- def ImprGraph(self,**kargs):
+ def ImprGraph(self, **kargs):
"""Impression au format XMGRACE : via le module Graph
"""
args=kargs.copy()
- if len(self.para)<>2:
- UTMESS('A','Table','La table doit avoir exactement deux paramètres.')
+ if len(self.para) != 2:
+ UTMESS('A','Table','La table doit avoir exactement deux paramètres '\
+ 'pour une impression au format XMGRACE.')
return
- lx, ly = [[v for v in getattr(self,p).values() if v<>None] for p in self.para]
+ # suppression des lignes contenant une cellule vide
+ tnv = getattr(self, self.para[0]).NON_VIDE() \
+ & getattr(self, self.para[1]).NON_VIDE()
# objet Graph
graph=Graph.Graph()
dicC={
- 'Val' : [lx, ly],
- 'Lab' : self.para,
+ 'Val' : [getattr(tnv, tnv.para[0]).values(),
+ getattr(tnv, tnv.para[1]).values()],
+ 'Lab' : tnv.para,
}
if args['LEGENDE']==None: del args['LEGENDE']
Graph.AjoutParaCourbe(dicC, args)
t.a retourne un objet intermédiaire de la classe Colonne qui mémorise
le nom de la colonne demandée (a, ici).
"""
+# ------------------------------------------------------------------------------
def __init__(self, rows=[], para=[], typ=[], titr=''):
"""Constructeur de la Table :
rows : liste des lignes (dict)
type : liste des types des paramètres
titr : titre de la table
"""
- self.rows=[r for r in rows if r.values()<>[None]*len(r.values())]
- self.para=list(para)
- if len(typ)==len(self.para):
- self.type=list(typ)
+ self.rows = [r for r in rows if r.values() != [None]*len(r.values())]
+ self.para = list(para)
+ for i in self.para :
+ if self.para.count(i) != 1 :
+ UTMESS('F','Table','Parametre en double: %s' %i)
+ if len(typ) == len(self.para):
+ self.type = list(typ)
else:
- self.type=[None]*len(self.para)
- self.titr=titr
+ self.type = [None]*len(self.para)
+ self.titr = titr
+
+# ------------------------------------------------------------------------------
+ def copy(self):
+ """Retourne une copie de la table.
+ """
+ rows = []
+ for r in self.rows:
+ rows.append(copy(r))
+ return Table(rows, self.para[:], self.type[:], self.titr)
+# ------------------------------------------------------------------------------
def append(self, obj):
- """Ajoute une ligne (type dict) à la Table"""
+ """Ajoute une ligne (type dict) qui peut éventuellement définir un
+ nouveau paramètre."""
+ para=obj.keys()
+ for p in para:
+ if not p in self.para:
+ self.para.append(p)
+ self.type.append(_typaster(obj[p]))
+ else:
+ ip=self.para.index(p)
+ self.type[ip]=_typaster(obj[p], self.type[ip])
self.rows.append(obj)
+# ------------------------------------------------------------------------------
+ def SansColonneVide(self):
+ """Retourne une copie de la table dans laquelle on a supprimé les colonnes
+ vides (les lignes vides sont automatiquement supprimées).
+ """
+ tab = self.copy()
+ lp = tab.para[:]
+ for para in lp:
+ if len(tab[para]) == 0:
+ bid = lp.pop(0)
+ return tab[lp]
+
+# ------------------------------------------------------------------------------
+ def __setitem__(self, k_para, k_value):
+ """Ajoute une colonne k_para dont les valeurs sont dans k_value"""
+ if len(k_value)==0:
+ return
+ if k_para in self.para :
+ UTMESS('F','Table','(setitem) Le parametre %s existe déjà.' % k_para)
+ self.para.append(k_para)
+ self.type.append(_typaster(k_value[0]))
+ i=0
+ for row in self:
+ if i<len(k_value):
+ row[k_para]=k_value[i]
+ self.type[-1]=_typaster(k_value[i], self.type[-1])
+ else:
+ row[k_para]=None
+ i+=1
+ for j in range(i,len(k_value)):
+ self.append({k_para:k_value[j]})
+
+# ------------------------------------------------------------------------------
+ def fromfunction(self, nom_para, funct, l_para=None, const=None):
+ """Ajoute une colonne `nom_para` en évaluant la fonction `funct` sur
+ la valeur des paramètres `l_para` (qui doivent exister dans la table).
+ Si `l_para` n'est pas fourni, on prend `funct`.nompar (FORMULE Aster).
+ On peut passer un dictionnaire de constantes dans `const`. Quand on
+ utilise une FORMULE Aster, les constantes sont prises dans le contexte
+ global.
+ """
+ # vérif préalables
+ if not hasattr(funct, '__call__'):
+ UTMESS('F', 'Table', "(fromfunction) '%s' n'a pas d'attribut '__call__'." \
+ % funct.__name__)
+ if nom_para in self.para :
+ UTMESS('F','Table','Le parametre %s existe déjà.' % nom_para)
+ if l_para == None:
+ if not hasattr(funct, 'nompar'):
+ UTMESS('F', 'Table', "(fromfunction) '%s' n'a pas d'attribut 'nompar'." \
+ % funct.__name__)
+ l_para = funct.nompar
+ if not type(l_para) in EnumTypes:
+ l_para = [l_para]
+ not_found = ', '.join([p for p in l_para if not p in self.para])
+ if not_found != '':
+ UTMESS('F','Table','Parametre(s) absent(s) de la table : %s' % not_found)
+ if const == None:
+ const = {}
+ if type(const) is not DictType:
+ UTMESS('F', 'Table', "L'argument 'const' doit etre de type 'dict'.")
+ # liste des valeurs des paramètres
+ tabpar = []
+ for para in l_para:
+ vals = getattr(self, para).values()
+ tabpar.append(vals)
+ tabpar = transpose.transpose(tabpar)
+ # évaluation de la fonction sur ces paramètres
+ vectval = []
+ for lpar in tabpar:
+ # si un paramètre est absent, on ne peut pas évaluer la formule
+ if None in lpar:
+ vectval.append(None)
+ else:
+ vectval.append(funct(*lpar, **const))
+ # ajout de la colonne
+ self[nom_para] = vectval
+
+# ------------------------------------------------------------------------------
def __iter__(self):
"""Itère sur les lignes de la Table"""
return iter(self.rows)
+# ------------------------------------------------------------------------------
def __getattr__(self, column):
"""Construit un objet intermediaire (couple table, colonne)"""
typ=None
typ=self.type[self.para.index(column)]
return Colonne(self, column, typ)
+# ------------------------------------------------------------------------------
def sort(self, CLES=None, ORDRE='CROISSANT'):
"""Tri de la table.
CLES : liste des clés de tri
- ORDRE : CROISSANT ou DECROISSANT (de longueur 1 ou len(keys))
+ ORDRE : CROISSANT ou DECROISSANT
"""
# par défaut, on prend tous les paramètres
- if CLES==None:
- CLES=self.para[:]
+ if CLES == None:
+ CLES = self.para[:]
+ # vérification des arguments
if not type(CLES) in EnumTypes:
- CLES=[CLES,]
+ CLES = [CLES]
else:
- CLES=list(CLES)
- self.rows=sort_table(self.rows, self.para, CLES, (ORDRE=='DECROISSANT'))
-# if not type(order) in EnumTypes:
-# order=[order,]
-# print 'TRI clés=%s, order=%s' % (keys,order)
-# # on ne garde que le premier si les longueurs sont différentes
-# if len(order)<>len(keys):
-# order=[order[0],]
-# else:
-# # si toutes les valeurs sont identiques, on peut ne garder que la 1ère
-# d={}
-# for o in order: d[o]=None
-# if len(order)<>len(keys) or len(d.keys())==1:
-# order=[order[0],]
-# if len(order)==1:
-# self.rows=sort_table(self.rows, self.para, keys, (order[0]=='DECROISSANT'))
-# else:
-# # de la dernière clé à la première
-# for k,o in [(keys[i],order[i]) for i in range(len(keys)-1,-1,-1)]:
-# print 'TRI : clé=%s, order=%s' % (k,o)
-# self.rows=sort_table(self.rows, self.para, [k], (o=='DECROISSANT'))
+ CLES = list(CLES)
+ not_found = ', '.join([p for p in CLES if not p in self.para])
+ if not_found != '':
+ UTMESS('F', 'Table', 'Parametre(s) absent(s) de la table : %s' % not_found)
+ if not ORDRE in ('CROISSANT', 'DECROISSANT'):
+ UTMESS('F', 'Table', 'Valeur incorrecte pour ORDRE : %s' % ORDRE)
+ # tri
+ self.rows = sort_table(self.rows, self.para, CLES, (ORDRE=='DECROISSANT'))
+# ------------------------------------------------------------------------------
def __delitem__(self, args):
"""Supprime les colonnes correspondantes aux éléments de args """
if not type(args) in EnumTypes:
for item in args:
del new_type[new_para.index(item)]
new_para.remove(item)
- for line in new_rows : del line[item]
+ for line in new_rows:
+ del line[item]
return Table(new_rows, new_para, new_type, self.titr)
+# ------------------------------------------------------------------------------
def __getitem__(self, args):
"""Extrait la sous table composée des colonnes dont les paramètres sont dans args """
if not type(args) in EnumTypes:
args=[args,]
else:
args=list(args)
- #print '<getitem> args=',args
new_rows=[]
new_para=args
new_type=[]
new_rows.append(new_line)
return Table(new_rows, new_para, new_type, self.titr)
+# ------------------------------------------------------------------------------
def __and__(self, other):
"""Intersection de deux tables (opérateur &)"""
if other.para<>self.para:
tmp = [ r for r in self if r in other.rows ]
return Table(tmp, self.para, self.type, self.titr)
+# ------------------------------------------------------------------------------
def __or__(self, other):
"""Union de deux tables (opérateur |)"""
if other.para<>self.para:
tmp.extend([ r for r in other if r not in self ])
return Table(tmp, self.para, self.type[:], self.titr)
+# ------------------------------------------------------------------------------
def values(self):
"""Renvoie la table sous la forme d'un dictionnaire de listes dont les
clés sont les paramètres.
dico[column]=Colonne(self, column).values()
return dico
+# ------------------------------------------------------------------------------
+ def dict_CREA_TABLE(self):
+ """Renvoie le dictionnaire des mots-clés à fournir à la commande CREA_TABLE
+ pour produire une table_sdaster.
+ """
+ dico={ 'TITRE' : ['%-80s' % lig for lig in self.titr.split('\n')],
+ 'LISTE' : [], }
+ # remplissage de chaque occurence (pour chaque paramètre) du mot-clé facteur LISTE
+ for i in range(len(self.para)):
+ # nom du paramètre et type si K*
+ d={ 'PARA' : self.para[i], }
+ typ=self.type[i]
+ if typ==None:
+ UTMESS('F', 'Table', 'Type du paramètre %s non défini.' %\
+ self.para[i])
+ elif typ[0]=='K':
+ mc='LISTE_K'
+ if not typ in ('K8', 'K16', 'K24'):
+ UTMESS('A','Table','Type du paramètre %s forcé à %s' % (self.para[i],Kdef))
+ typ=Kdef
+ d['TYPE_K']=typ
+ elif typ=='I':
+ mc='LISTE_I'
+ elif typ=='R':
+ mc='LISTE_R'
+ # valeurs sans trou / avec trou
+ vals=getattr(self, self.para[i]).values()
+ if vals.count(None)==0:
+ d[mc]=vals
+ else:
+ d['NUME_LIGN'] = [j+1 for j in range(len(vals)) if vals[j]<>None]
+ d[mc] = [v for v in vals if v <>None]
+ if len(d[mc])==0:
+ UTMESS('I','Table','Colonne %s vide' % self.para[i])
+ else:
+ dico['LISTE'].append(d)
+ if len(dico['LISTE'])==0:
+ UTMESS('F','Table','La table est vide')
+ return dico
+
+# ------------------------------------------------------------------------------
def Array(self,Para,Champ):
"""Renvoie sous forme de NumArray le résultat d'une extraction dans une table
méthode utile à macr_recal
"""
import Numeric
__Rep = self[Para,Champ].values()
- F=Numeric.zeros((len(__Rep[Para]),2),Numeric.Float)
+ F = Numeric.zeros((len(__Rep[Para]),2), Numeric.Float)
for i in range(len(__Rep[Para])):
- F[i][0] = __Rep[Para][i]
- F[i][1] = __Rep[Champ][i]
+ F[i][0] = __Rep[Para][i]
+ F[i][1] = __Rep[Champ][i]
del(__Rep)
return F
+# ------------------------------------------------------------------------------
def Croise(self):
"""Retourne un tableau croisé P3(P1,P2) à partir d'une table ayant
trois paramètres (P1, P2, P3).
"""
if len(self.para)<>3:
- UTMESS('A','Table','La table doit avoir exactement trois paramètres.')
+ UTMESS('A', 'Table', 'La table doit avoir exactement trois paramètres.')
return Table()
py, px, pz = self.para
ly, lx, lz = [getattr(self,p).values() for p in self.para]
new_titr+=pz + ' FONCTION DE ' + px + ' ET ' + py
return Table(new_rows, new_para, new_type, new_titr)
+# ------------------------------------------------------------------------------
+ def Renomme(self, pold, pnew):
+ """Renomme le paramètre `pold` en `pnew`.
+ """
+ if not pold in self.para:
+ raise KeyError, 'Paramètre %s inexistant dans cette table' % pold
+ elif self.para.count(pnew)>0:
+ raise KeyError, 'Le paramètre %s existe déjà dans la table' % pnew
+ else:
+ self.para[self.para.index(pold)] = pnew
+ for lig in self:
+ lig[pnew] = lig[pold]
+ del lig[pold]
+
# ------------------------------------------------------------------------------
# ------------------------------------------------------------------------------
# ------------------------------------------------------------------------------
Alors on peut écrire la requete simple :
soustable=t.a<10
Ainsi que des requetes plus complexes :
- soustable=t.a<10 & t.b <4
+ soustable=t.a<10 and t.b <4
ou
- soustable=t.a<10 | t.b <4
+ soustable=t.a<10 or t.b <4
Les "alias" EQ, NE, LE, LT, GE, GT permettent à la macro IMPR_TABLE
d'utiliser directement le mot-clé utilisateur CRIT_COMP défini dans le
catalogue : getattr(Table,CRIT_COMP).
"""
+# ------------------------------------------------------------------------------
def __init__(self, table, column, typ=None):
"""Constructeur (objet Table associé, paramètre de la colonne, type du
paramètre).
self.type=typ
self.titr=''
+# ------------------------------------------------------------------------------
def _extract(self, fun):
"""Construit une table avec les lignes de self.Table
dont l'élément de nom self.para satisfait le critère fun,
"""
return Table([row for row in self.Table if fun(row.get(self.para))], self.Table.para, self.Table.type, self.Table.titr)
+# ------------------------------------------------------------------------------
def __le__(self, VALE):
return self._extract(lambda v: v<>None and v<=VALE)
+# ------------------------------------------------------------------------------
def __lt__(self, VALE):
return self._extract(lambda v: v<>None and v<VALE)
+# ------------------------------------------------------------------------------
def __ge__(self, VALE):
return self._extract(lambda v: v<>None and v>=VALE)
+# ------------------------------------------------------------------------------
def __gt__(self, VALE):
return self._extract(lambda v: v<>None and v>VALE)
+# ------------------------------------------------------------------------------
def __eq__(self, VALE, CRITERE='RELATIF', PRECISION=0.):
if type(VALE) in EnumTypes :
return self._extract(lambda v: v in VALE)
vmax=(1.+PRECISION)*VALE
return self._extract(lambda v: v<>None and vmin<v<vmax)
+# ------------------------------------------------------------------------------
+ def REGEXP(self, regexp):
+ """Retient les lignes dont le paramètre satisfait l'expression
+ régulière `regexp`.
+ """
+ if not type(regexp) in StringTypes:
+ return self._extract(lambda v : False)
+ return self._extract(lambda v : v != None and re.search(regexp, v) != None)
+
+# ------------------------------------------------------------------------------
def __ne__(self, VALE, CRITERE='RELATIF', PRECISION=0.):
if type(VALE) in EnumTypes :
return self._extract(lambda v: v not in VALE)
vmax=(1.+PRECISION)*VALE
return self._extract(lambda v: v<>None and (v<vmin or vmax<v))
+# ------------------------------------------------------------------------------
def MAXI(self):
# important pour les performances de récupérer le max une fois pour toutes
maxi=max(self)
return self._extract(lambda v: v==maxi)
+# ------------------------------------------------------------------------------
def MINI(self):
# important pour les performances de récupérer le min une fois pour toutes
mini=min(self)
return self._extract(lambda v: v==mini)
+# ------------------------------------------------------------------------------
def ABS_MAXI(self):
# important pour les performances de récupérer le max une fois pour toutes
abs_maxi=max([abs(v) for v in self.values() if type(v) in NumberTypes])
return self._extract(lambda v: v==abs_maxi or v==-abs_maxi)
+# ------------------------------------------------------------------------------
def ABS_MINI(self):
# important pour les performances de récupérer le min une fois pour toutes
abs_mini=min([abs(v) for v in self.values() if type(v) in NumberTypes])
# tester le type de v est trop long donc pas de abs(v)
return self._extract(lambda v: v==abs_mini or v==-abs_mini)
+# ------------------------------------------------------------------------------
def __iter__(self):
"""Itère sur les éléments de la colonne"""
for row in self.Table:
yield row.get(self.para)
#yield row[self.para]
+# ------------------------------------------------------------------------------
def __getitem__(self, i):
"""Retourne la ième valeur d'une colonne"""
return self.values()[i]
+# ------------------------------------------------------------------------------
def values(self):
"""Renvoie la liste des valeurs"""
- return [r[self.para] for r in self.Table]
+ return [r.get(self.para,None) for r in self.Table]
+
+ def not_none_values(self):
+ """Renvoie la liste des valeurs non 'None'"""
+ return [val for val in self.values() if val != None]
+# ------------------------------------------------------------------------------
# équivalences avec les opérateurs dans Aster
LE=__le__
LT=__lt__
GT=__gt__
EQ=__eq__
NE=__ne__
- def VIDE(self) : return self.__eq__(None)
- def NON_VIDE(self): return self.__ne__(None)
+ def VIDE(self):
+ return self.__eq__(None)
+ def NON_VIDE(self):
+ return self.__ne__(None)
# ------------------------------------------------------------------------------
# ------------------------------------------------------------------------------
# ------------------------------------------------------------------------------
-def sort_table(rows,l_para,w_para,reverse=False):
+def sort_table(rows, l_para, w_para, reverse=False):
"""Sort list of dict.
rows : list of dict
l_para : list of the keys of dict
"""
c_para=[i for i in l_para if i not in w_para]
new_rows=rows
+ # rename sort keys by "__" + number + para
+ # ("__" to avoid conflict with existing parameters)
for i in w_para :
new_key= '__'+str(w_para.index(i))+i
for row in new_rows :
row[new_key]=row[i]
del row[i]
+ # rename others parameters by "___" + para
+ # ("___" to be after sort keys)
for i in c_para :
new_key= '___'+i
for row in new_rows :
row[new_key]=row[i]
del row[i]
+ # sort
new_rows.sort()
+ # reversed sort
if reverse:
new_rows.reverse()
for i in w_para :
if nform=='formK':
# convertit %12.5E en %-12s
fmt=re.sub('([0-9]+)[\.0-9]*[diueEfFgG]+','-\g<1>s',dform['form'+typAster])
- #print nform, typAster, fmt
else:
fmt=dform[nform]
else:
return fmt
# ------------------------------------------------------------------------------
+def merge(tab1, tab2, labels=[]):
+ """Assemble les deux tables tb1 et tb2 selon une liste de labels communs.
+ Si labels est vide:
+ - les lignes de tb2 sont ajoutés à celles de tb1,
+ sinon :
+ - si on trouve les valeurs de tb2 sur les labels dans tb1 (et une seule fois),
+ on surcharge tb1 avec les lignes de tb2 ;
+ - sinon on ajoute la ligne de tb2 à la fin de tb1.
+ """
+ tb1 = tab1.copy()
+ tb2 = tab2.copy()
+ if type(labels) not in EnumTypes:
+ labels=(labels,)
+ for key in labels :
+ if key not in tb1.para : UTMESS('F','Table','Erreur, label non présent %s' % key)
+ if key not in tb2.para : UTMESS('F','Table','Erreur, label non présent %s' % key)
+ # ensemble des paramètres et des types
+ n_para=tb1.para[:]
+ n_type=tb1.type[:]
+ for i in tb2.para:
+ if i not in tb1.para:
+ n_para.append(i)
+ n_type.append(tb2.type[tb2.para.index(i)])
+ # restriction des lignes aux labels communs (peu cher en cpu)
+ rows1 = tb1.rows
+ dlab1 = {}
+ for i1 in range(len(rows1)):
+ tu1 = tuple(map(rows1[i1].__getitem__, labels))
+ if dlab1.get(tu1, '') == '':
+ dlab1[tu1] = i1
+ else:
+ dlab1[tu1] = None
+ # restriction des lignes aux labels communs (peu cher en cpu)
+ rows2 = tb2.rows
+ dlab2 = {}
+ for i2 in range(len(rows2)):
+ tu2 = tuple(map(rows2[i2].__getitem__, labels))
+ if dlab2.get(tu2, '') == '':
+ dlab2[tu2] = i2
+ else:
+ dlab2[tu2] = None
+ # creation de dic1 : dictionnaire de correspondance entre les
+ # lignes a merger dans les deux tableaux
+ dic1 = {}
+ for cle in dlab1.keys():
+ if dlab1[cle] == None or cle == ():
+ bid = dlab1.pop(cle)
+ for cle in dlab2.keys():
+ if dlab2[cle] == None or cle == ():
+ bid = dlab2.pop(cle)
+ for cle in dlab2.keys():
+ if dlab1.has_key(cle):
+ dic1[dlab2[cle]] = dlab1[cle]
+ # insertion des valeurs de tb2 dans tb1 quand les labels sont communs
+ # (et uniques dans chaque table) OU ajout de la ligne de tb2 dans tb1
+ i2 = -1
+ for r2 in rows2:
+ i2 += 1
+ try:
+ rows1[dic1[i2]].update(r2)
+ except KeyError:
+ rows1.append(r2)
+ # concaténation des titres + info sur le merge
+ tit = '\n'.join([tb1.titr, tb2.titr, 'MERGE avec labels=%s' % repr(labels)])
+ return Table(rows1, n_para, n_type, tit)
+
# ------------------------------------------------------------------------------
-# ------------------------------------------------------------------------------
-if __name__ == "__main__":
- listdic = [
- {'NOEUD': 'N1' ,'NUME_ORDRE': 1 ,'INST': 0.5, 'DX': -0.00233, 'COOR_Y': 0.53033,},
- {'NOEUD': 'N1' ,'NUME_ORDRE': 2 ,'INST': 1.0, 'DX': -0.00467, 'COOR_Y': 0.53033,},
- {'NOEUD': 'N1' ,'NUME_ORDRE': 3 ,'INST': 1.5, 'DX': -0.00701, 'COOR_Y': 0.53033,},
- {'NOEUD': 'N1' ,'NUME_ORDRE': 4 ,'INST': 2.0, 'DX': -0.00934, 'COOR_Y': 0.53033,},
- {'NOEUD': 'N1' ,'NUME_ORDRE': 5 ,'INST': 2.5, 'DX': -0.01168, 'COOR_Y': 0.53033,},
- {'NOEUD': 'N2' ,'NUME_ORDRE': 11,'INST': 5.5, 'DX': -0.00233, 'COOR_Y': 0.53033,},
- {'NOEUD': 'N2' ,'NUME_ORDRE': 12,'INST': 6.0, 'DX': -0.00467, 'COOR_Y': 0.53033,},
- {'NOEUD': 'N2' ,'NUME_ORDRE': 13,'INST': 6.5, 'DX': -0.00701, 'COOR_Y': 0.53033,},
- {'NOEUD': 'N2' ,'NUME_ORDRE': 14,'INST': 7.0, 'DX': -0.00934, 'COOR_Y': 0.53033,},
- {'NOEUD': 'N2' ,'NUME_ORDRE': 15,'INST': 7.5, 'DX': -0.01168, 'COOR_Y': 0.53033,},
- ]
- import random
- random.shuffle(listdic)
- listpara=['NOEUD','NUME_ORDRE','INST','COOR_Y','DX']
- listtype=['K8','I','R','R','R']
- t=Table(listdic,listpara,listtype)
-
- tb=t[('NOEUD','DX')]
- print tb.para
- print tb.type
-
- print
- print "------Table initiale----"
- print t
- print
- print "--------- CRIT --------"
- print t.NUME_ORDRE <=5
- print
- print "------- CRIT & CRIT -----"
- print (t.NUME_ORDRE < 10) & (t.INST >=1.5)
- print
- print "----- EQ maxi / min(col), max(col) ------"
- print t.DX == max(t.DX)
- print min(t.DX)
- print max(t.DX)
- print "------ getitem sur 2 paramètres ------"
- print t.NUME_ORDRE
- print t.DX
- print t['DX','NUME_ORDRE']
- print "------ sort sur INST ------"
- t.sort('INST')
- print t
-
- print "------- TABLEAU_CROISE ------"
- tabc=t['NOEUD','INST','DX']
- tabc.Impr(FORMAT='TABLEAU_CROISE')
-
- N=5
- ldic=[]
- for i in range(N):
- ldic.append({'IND':float(i), 'VAL' : random.random()*i})
- para=['IND','VAL']
- t3=Table(ldic, para, titr='Table aléatoire')
- col=t3.VAL.ABS_MAXI()
- col=t3.VAL.MINI()
-
- t3.sort('VAL','IND')
-
- tg=tabc['INST','DX'].DX.NON_VIDE()
- #tg.Impr(FORMAT='XMGRACE')
-
- g=Graph.Graph()
- g.Titre="Tracé d'une fonction au format TABLEAU"
- g.AjoutCourbe(Val=[tg.INST.values(), tg.DX.values()], Lab=['INST','DX'])
- g.Trace(FORMAT='TABLEAU')
-
-# t.Impr(PAGINATION='NOEUD')
- t.Impr(PAGINATION=('NOEUD','INST'))
-
+def _typaster(obj, prev=None, strict=False):
+ """Retourne le type Aster ('R', 'I', Kdef) correspondant à l'objet obj.
+ Si prev est fourni, on vérifie que obj est du type prev.
+ Si strict=False, on autorise que obj ne soit pas du type prev s'ils sont
+ tous les deux numériques ; dans ce cas, on retourne le "type enveloppe" 'R'.
+ """
+ dtyp={
+ IntType : 'I',
+ FloatType : 'R',
+ StringType : Kdef, UnicodeType : Kdef,
+ NoneType : 'I',
+ }
+ if type(obj) in dtyp.keys():
+ typobj=dtyp[type(obj)]
+ if prev in [None, typobj]:
+ return typobj
+ elif strict: # prev<>None et typobj<>prev et strict
+ raise TypeError, "La valeur %s n'est pas de type %s" % (repr(obj),repr(prev))
+ elif prev in ('I','R') and typobj in ('I','R'):
+ return 'R'
+ else:
+ raise TypeError, "La valeur %s n'est pas compatible avec le type %s" \
+ % (repr(obj),repr(prev))
+ else:
+ raise TypeError, 'Une table ne peut contenir que des entiers, réels ' \
+ 'ou chaines de caractères.'
-#@ MODIF UniteAster Utilitai DATE 11/05/2005 AUTEUR MCOURTOI M.COURTOIS
+#@ MODIF UniteAster Utilitai DATE 29/08/2006 AUTEUR MCOURTOI M.COURTOIS
# -*- coding: iso-8859-1 -*-
# CONFIGURATION MANAGEMENT OF EDF VERSION
# ======================================================================
print __tab.EXTR_TABLE()
raise aster.FatalError,"<F> <UniteAster._setinfo> %s" % message
self.infos[unit]['nom'] = nomfich
- DETRUIRE(CONCEPT=_F(NOM=__tab))
+ #print 'DEBUG infos[unit] = ', self.infos[unit]
+ DETRUIRE(CONCEPT=_F(NOM=__tab),INFO=1)
#-------------------------------------------------------------------------------
- def Libre(self, nom=None):
- """Réserve et retourne une unité libre en y associant, s'il est fourni,
- le fichier 'nom'.
+ def Libre(self, nom=None, action='RESERVER'):
+ """Réserve/associe et retourne une unité libre en y associant, s'il est
+ fourni, le fichier 'nom'.
"""
__tab=INFO_EXEC_ASTER(LISTE_INFO=('UNITE_LIBRE'))
unit = __tab['UNITE_LIBRE',1]
- DETRUIRE(CONCEPT=_F(NOM=__tab))
+ DETRUIRE(CONCEPT=_F(NOM=__tab),INFO=1)
if nom==None:
nom='fort.'+str(unit)
self.infos[unit]['nom']
raise aster.FatalError,"<F> <UniteAster.Libre> %s" % message
- DEFI_FICHIER(ACTION='RESERVER', UNITE=unit , FICHIER=nom.strip())
+ DEFI_FICHIER(ACTION=action, UNITE=unit , FICHIER=nom.strip())
self.infos[unit] = {}
self.infos[unit]['nom'] = nom.strip()
self.infos[unit]['etat'] = 'R'
"""Retourne l'état de l'unité si 'etat' n'est pas fourni
et/ou change son état :
kargs['etat'] : nouvel état,
+ kargs['nom'] : nom du fichier,
kargs['TYPE'] : type du fichier à ouvrir ASCII/BINARY/LIBRE,
- kargs['ACCES'] : type d'accès NEW/APPEND/OLD.
+ kargs['ACCES'] : type d'accès NEW/APPEND/OLD (APPEND uniquement en ASCII).
"""
# ul peut etre un entier Aster
try:
DEFI_FICHIER(ACTION='LIBERER', UNITE=unit)
DEFI_FICHIER(ACTION = 'RESERVER',
UNITE = unit,
- FICHIER = self.infos[unit]['nom'])
+ FICHIER = kargs.get('nom', self.infos[unit]['nom']))
+ self._setinfo(unit)
elif new == 'F':
DEFI_FICHIER(ACTION='LIBERER', UNITE=unit)
elif new == 'O':
if self.infos[unit]['etat'] == 'R':
DEFI_FICHIER(ACTION='LIBERER', UNITE=unit)
+ # valeurs par défaut
+ typ = kargs.get('TYPE', 'ASCII')
+ if typ == 'ASCII':
+ acces = 'APPEND'
+ else:
+ acces = 'OLD'
+ acces = kargs.get('ACCES', acces)
DEFI_FICHIER(ACTION ='ASSOCIER',
UNITE = unit,
- FICHIER = self.infos[unit]['nom'],
- TYPE = kargs.get('TYPE', 'ASCII'),
- ACCES = kargs.get('ACCES', 'APPEND'),)
+ FICHIER = kargs.get('nom', self.infos[unit]['nom']),
+ TYPE = typ,
+ ACCES = acces,)
+ self._setinfo(unit)
self.infos[unit]['etat'] = new
return self.infos[unit]['etat']
-#@ MODIF Utmess Utilitai DATE 30/11/2004 AUTEUR MCOURTOI M.COURTOIS
+#@ MODIF Utmess Utilitai DATE 17/10/2005 AUTEUR MCOURTOI M.COURTOIS
# -*- coding: iso-8859-1 -*-
# CONFIGURATION MANAGEMENT OF EDF VERSION
# ======================================================================
def UTMESS(code, sprg, texte):
"""Utilitaire analogue à la routine fortran UTMESS.
- code : 'A', 'E', 'S', 'F'
+ code : 'A', 'E', 'S', 'F', 'I'
sprg : nom du module, classe ou fonction python où l'on se trouve
texte : contenu du message
"""
fmt='\n <%s> <%s> %s\n\n'
- UL={
- 'MESSAGE' : 6,
- 'RESULTAT' : 8,
- #'ERREUR' : 9,
- }
- # On importe la définition des commandes à utiliser dans la macro
-# if jdc:
-# DEFI_FICHIER = jdc.get_cmd('DEFI_FICHIER')
-# else:
-# # on se limite au print !
-# UL={ 'MESSAGE' : 6, }
- try:
- from Cata.cata import DEFI_FICHIER
- except ImportError:
- # on se limite au print !
- UL={ 'MESSAGE' : 6, }
-
- reason=fmt % (code, sprg, texte)
+ sanscode='\n <%s> %s\n\n'
+ UL=[
+ 'MESSAGE',
+ 'RESULTAT',
+ #'ERREUR',
+ ]
+#
+ # Comme l'UTMESS fortran, on supprime le code si on ne fait pas l'abort
+ if aster.onFatalError()=='EXCEPTION':
+ reason=sanscode % (sprg, texte)
+ else:
+ reason=fmt % (code, sprg, texte)
- for nom,ul in UL.items():
- if ul<>6:
- DEFI_FICHIER(ACTION='LIBERER', UNITE=ul, )
- f=open('fort.'+str(ul),'a')
- else:
- f=sys.stdout
+ for nom in UL:
# écriture du message
- f.write(reason)
-
- if ul<>6:
- f.close()
- DEFI_FICHIER(ACTION='ASSOCIER', UNITE=ul, TYPE='ASCII', ACCES='APPEND')
+ aster.affiche(nom,reason)
if code=='S':
raise aster.error, reason
-#@ MODIF sup_gmsh Utilitai DATE 10/05/2005 AUTEUR GJBHHEL E.LORENTZ
+#@ MODIF sup_gmsh Utilitai DATE 08/11/2005 AUTEUR ASSIRE A.ASSIRE
# -*- coding: iso-8859-1 -*-
# CONFIGURATION MANAGEMENT OF EDF VERSION
# ======================================================================
def Create(self, file = 'fort.19') :
self.Save()
-# os.system('gmsh -3 fort.geo')
os.system(self.gmsh + ' -3 fort.geo')
+ try: os.remove(file)
+ except: pass
os.rename('fort.msh',file)
-#@ MODIF t_fonction Utilitai DATE 31/05/2005 AUTEUR DURAND C.DURAND
+#@ MODIF t_fonction Utilitai DATE 25/09/2006 AUTEUR MCOURTOI M.COURTOIS
# -*- coding: iso-8859-1 -*-
# CONFIGURATION MANAGEMENT OF EDF VERSION
# ======================================================================
from Numeric import *
import copy
import types
+from sets import Set
+
+class FonctionError(Exception):
+ pass
def interp(typ_i,val,x1,x2,y1,y2) :
+ """Interpolation linéaire/logarithmique entre un couple de valeurs
+ """
if typ_i==['LIN','LIN']: return y1+(y2-y1)*(val-x1)/(x2-x1)
if typ_i==['LIN','LOG']: return exp(log(y1)+(val-x1)*(log(y2)-log(y1))/(x2-x1))
if typ_i==['LOG','LOG']: return exp(log(y1)+(log(val)-log(x1))*(log(y2)-log(y1))/(log(x2)-log(x1)))
if typ_i[0]=='NON' :
if val==x1 : return y1
elif val==x2 : return y2
- else : raise StandardError, 'fonction : interpolation NON'
+ else : raise FonctionError, 'fonction : interpolation NON'
def is_ordo(liste) :
- listb=dict([(i,0) for i in liste]).keys()
+ listb=list(Set(liste))
listb.sort()
return liste==listb
class t_fonction :
- ### Classe pour fonctions réelles, équivalent au type aster = fonction_sdaster
+ """Classe pour fonctions réelles, équivalent au type aster = fonction_sdaster
+ """
def __init__(self,vale_x,vale_y,para) :
- # création d'un objet fonction
- # vale_x et vale_y sont des listes de réels de meme longueur
- # para est un dictionnaire contenant les entrées PROL_DROITE, PROL_GAUCHE et INTERPOL (cf sd ASTER)
+ """Création d'un objet fonction
+ - vale_x et vale_y sont des listes de réels de meme longueur
+ - para est un dictionnaire contenant les entrées PROL_DROITE, PROL_GAUCHE et INTERPOL (cf sd ASTER)
+ """
pk=para.keys()
pk.sort()
if pk!=['INTERPOL','NOM_PARA','NOM_RESU','PROL_DROITE','PROL_GAUCHE'] :
- raise StandardError, 'fonction : parametres incorrects'
+ raise FonctionError, 'fonction : parametres incorrects'
if para['INTERPOL'] not in [['NON','NON'],['LIN','LIN'],['LIN','LOG'],['LOG','LOG'],['LOG','LIN'],] :
- raise StandardError, 'fonction : parametre INTERPOL incorrect'
+ raise FonctionError, 'fonction : parametre INTERPOL incorrect'
if para['PROL_DROITE'] not in ['EXCLU','CONSTANT','LINEAIRE'] :
- raise StandardError, 'fonction : parametre PROL_DROITE incorrect'
+ raise FonctionError, 'fonction : parametre PROL_DROITE incorrect'
if para['PROL_GAUCHE'] not in ['EXCLU','CONSTANT','LINEAIRE'] :
- raise StandardError, 'fonction : parametre PROL_GAUCHE incorrect'
+ raise FonctionError, 'fonction : parametre PROL_GAUCHE incorrect'
self.vale_x = array(vale_x)
self.vale_y = array(vale_y)
self.para = para
if len(self.vale_x)!=len(self.vale_y) :
- raise StandardError, 'fonction : longueur abscisse <> longueur ordonnées'
+ raise FonctionError, 'fonction : longueur abscisse <> longueur ordonnées'
if not is_ordo(self.vale_x) :
- raise StandardError, 'fonction : abscisses non strictement croissantes'
+ raise FonctionError, 'fonction : abscisses non strictement croissantes'
def __add__(self,other) :
- # addition avec une autre fonction ou un nombre, par surcharge de l'opérateur +
+ """addition avec une autre fonction ou un nombre, par surcharge de l'opérateur +
+ """
if isinstance(other,t_fonction):
para=copy.copy(self.para)
vale_x,para['PROL_GAUCHE'],para['PROL_DROITE']=self.homo_support(other)
elif type(other) in [types.FloatType,types.IntType,types.ComplexType] :
if isinstance(self,t_fonction_c): return t_fonction_c(self.vale_x,self.vale_y+other,self.para)
else : return t_fonction(self.vale_x,self.vale_y+other,self.para)
- else: raise StandardError, 'fonctions : erreur de type dans __add__'
+ else: raise FonctionError, 'fonctions : erreur de type dans __add__'
def __mul__(self,other) :
- # multiplication avec une autre fonction ou un nombre, par surcharge de l'opérateur *
+ """multiplication avec une autre fonction ou un nombre, par surcharge de l'opérateur *
+ """
if isinstance(other,t_fonction):
para=copy.copy(self.para)
vale_x,para['PROL_GAUCHE'],para['PROL_DROITE']=self.homo_support(other)
return t_fonction(self.vale_x,self.vale_y*other,self.para)
elif type(other) ==types.ComplexType :
return t_fonction_c(self.vale_x,self.vale_y*other,self.para)
- else: raise StandardError, 'fonctions : erreur de type dans __mul__'
+ else: raise FonctionError, 'fonctions : erreur de type dans __mul__'
def __repr__(self) :
- # affichage de la fonction en double colonne
+ """affichage de la fonction en double colonne
+ """
texte=[]
for i in range(len(self.vale_x)) :
texte.append('%f %f' % (self.vale_x[i],self.vale_y[i]))
return '\n'.join(texte)
def __getitem__(self,other) :
- # composition de deux fonction F[G]=FoG=F(G(x))
+ """composition de deux fonction F[G]=FoG=F(G(x))
+ """
para=copy.copy(self.para)
if other.para['NOM_RESU']!=self.para['NOM_PARA'] :
- raise StandardError,'''composition de fonctions : NOM_RESU1 et NOM_PARA2 incohérents '''
+ raise FonctionError,'''composition de fonctions : NOM_RESU1 et NOM_PARA2 incohérents '''
para['NOM_PARA']==other.para['NOM_PARA']
return t_fonction(other.vale_x,map(self,other.vale_y),para)
def __call__(self,val,tol=1.e-6):
- # méthode pour évaluer f(x)
- # tolérance, par défaut 1.e-6 en relatif sur la longueur de l'intervalle
- # adjacent, pour capter les erreurs d'arrondi en cas de prolongement exclu
+ """méthode pour évaluer f(x)
+ - tolérance, par défaut 1.e-6 en relatif sur la longueur de l'intervalle
+ - adjacent, pour capter les erreurs d'arrondi en cas de prolongement exclu
+ """
i=searchsorted(self.vale_x,val)
n=len(self.vale_x)
if i==0 :
if self.para['PROL_GAUCHE']=='EXCLU' :
eps_g=(val-self.vale_x[0] )/(self.vale_x[1] -self.vale_x[0])
if abs(eps_g)<=tol : return self.vale_y[0]
- else : raise StandardError, 'fonction évaluée hors du domaine de définition'
+ else : raise FonctionError, 'fonction évaluée hors du domaine de définition'
else :
if self.para['PROL_GAUCHE']=='CONSTANT' : return self.vale_y[0]
if self.para['PROL_GAUCHE']=='LINEAIRE' : return interp(self.para['INTERPOL'],val,self.vale_x[0],
if self.para['PROL_DROITE']=='EXCLU' :
eps_d=(val-self.vale_x[-1])/(self.vale_x[-1]-self.vale_x[-2])
if abs(eps_d)<=tol : return self.vale_y[-1]
- else : raise StandardError, 'fonction évaluée hors du domaine de définition'
+ else : raise FonctionError, 'fonction évaluée hors du domaine de définition'
else :
if self.para['PROL_DROITE']=='CONSTANT' : return self.vale_y[-1]
if self.para['PROL_DROITE']=='LINEAIRE' : return interp(self.para['INTERPOL'],val,self.vale_x[-1],
self.vale_y[i])
def homo_support(self,other) :
- # renvoie le support d'abscisses homogénéisé entre self et other
- # i.e. si prolongement exclu, on retient plus grand min ou plus petit max, selon
- # si prolongement autorisé, on conserve les abscisses d'une fonction, extrapolantes
- # sur l'autre.
- # Pour les points intermédiaires : union et tri des valeurs des vale_x réunis.
+ """Renvoie le support d'abscisses homogénéisé entre self et other
+ i.e. si prolongement exclu, on retient plus grand min ou plus petit max, selon
+ si prolongement autorisé, on conserve les abscisses d'une fonction, extrapolantes
+ sur l'autre.
+ Pour les points intermédiaires : union et tri des valeurs des vale_x réunis.
+ """
if other.vale_x[0]>self.vale_x[0]:
if other.para['PROL_GAUCHE']!='EXCLU' : f_g=self
else : f_g=other
return vale_x,prol_gauche,prol_droite
def cut(self,rinf,rsup,prec,crit='RELATIF') :
- # renvoie la fonction self dont on a 'coupé' les extrémités en x=rinf et x=rsup
- # pour la recherche de rinf et rsup dans la liste d'abscisses :
- # prec=precision crit='absolu' ou 'relatif'
+ """Renvoie la fonction self dont on a 'coupé' les extrémités en x=rinf et x=rsup
+ pour la recherche de rinf et rsup dans la liste d'abscisses :
+ prec=precision crit='absolu' ou 'relatif'
+ """
para=copy.copy(self.para)
para['PROL_GAUCHE']='EXCLU'
para['PROL_DROITE']='EXCLU'
if crit=='ABSOLU' : rinf_tab=greater(abs(self.vale_x-rinf),prec)
elif crit=='RELATIF': rinf_tab=greater(abs(self.vale_x-rinf),prec*rinf)
- else : raise StandardError, 'fonction : cut : critère absolu ou relatif'
+ else : raise FonctionError, 'fonction : cut : critère absolu ou relatif'
if crit=='ABSOLU' : rsup_tab=greater(abs(self.vale_x-rsup),prec)
elif crit=='RELATIF': rsup_tab=greater(abs(self.vale_x-rsup),prec*rsup)
- else : raise StandardError, 'fonction : cut : critère absolu ou relatif'
+ else : raise FonctionError, 'fonction : cut : critère absolu ou relatif'
if alltrue(rinf_tab) : i=searchsorted(self.vale_x,rinf)
else : i=rinf_tab.tolist().index(0)+1
if alltrue(rsup_tab) : j=searchsorted(self.vale_x,rsup)
return t_fonction(vale_x,vale_y,para)
def cat(self,other,surcharge) :
- # renvoie une fonction concaténée avec une autre, avec règles de surcharge
+ """renvoie une fonction concaténée avec une autre, avec règles de surcharge
+ """
para=copy.copy(self.para)
- if self.para['INTERPOL']!=other.para['INTERPOL'] : raise StandardError, 'concaténation de fonctions à interpolations différentes'
+ if self.para['INTERPOL']!=other.para['INTERPOL'] : raise FonctionError, 'concaténation de fonctions à interpolations différentes'
if min(self.vale_x)<min(other.vale_x) :
f1=self
f2=other
return t_fonction(vale_x,vale_y,para)
def tabul(self) :
- # mise en forme de la fonction selon un vecteur unique (x1,y1,x2,y2,...)
+ """mise en forme de la fonction selon un vecteur unique (x1,y1,x2,y2,...)
+ """
__tab=array([self.vale_x,self.vale_y])
return ravel(transpose(__tab)).tolist()
def extreme(self) :
- # renvoie un dictionnaire des valeurs d'ordonnées min et max
+ """renvoie un dictionnaire des valeurs d'ordonnées min et max
+ """
val_min=min(self.vale_y)
val_max=max(self.vale_y)
vm={}
return vm
def trapeze(self,coef) :
- # renvoie la primitive de la fonction, calculée avec la constante d'intégration 'coef'
+ """renvoie la primitive de la fonction, calculée avec la constante d'intégration 'coef'
+ """
trapz = zeros(len(self.vale_y),Float)
trapz[0] = coef
trapz[1:] = (self.vale_y[1:]+self.vale_y[:-1])/2*(self.vale_x[1:]-self.vale_x[:-1])
return t_fonction(self.vale_x,prim_y,para)
def simpson(self,coef) :
- # renvoie la primitive de la fonction, calculée avec la constante d'intégration 'coef'
+ """renvoie la primitive de la fonction, calculée avec la constante d'intégration 'coef'
+ """
para=copy.copy(self.para)
para['PROL_GAUCHE']='EXCLU'
para['PROL_DROITE']='EXCLU'
return t_fonction(self.vale_x,prim_y,para)
def derive(self) :
- # renvoie la dérivée de la fonction
+ """renvoie la dérivée de la fonction
+ """
pas=self.vale_x[1:]-self.vale_x[:-1]
pentes=(self.vale_y[1:]-self.vale_y[:-1])/(self.vale_x[1:]-self.vale_x[:-1])
derive=(pentes[1:]*pas[1:]+pentes[:-1]*pas[:-1])/(pas[1:]+pas[:-1])
return t_fonction(self.vale_x,derv_y,para)
def inverse(self) :
- # renvoie l'inverse de la fonction
- # on intervertit vale_x et vale_y, on swape interpolation
+ """renvoie l'inverse de la fonction
+ on intervertit vale_x et vale_y, on swape interpolation
+ """
para=copy.copy(self.para)
para['NOM_RESU']='TOUTRESU'
para['NOM_PARA']=self.para['NOM_PARA']
return t_fonction(vale_x,vale_y,para)
def abs(self) :
- # renvoie la mm fonction avec valeur absolue des ordonnées
+ """renvoie la mm fonction avec valeur absolue des ordonnées
+ """
para=copy.copy(self.para)
if para['PROL_GAUCHE']=='LINEAIRE' : para['PROL_GAUCHE']='EXCLU'
if para['PROL_DROITE']=='LINEAIRE' : para['PROL_DROITE']='EXCLU'
return t_fonction(self.vale_x,absolute(self.vale_y),para)
def evalfonc(self,liste_val) :
- # renvoie la mm fonction interpolée aux points définis par la liste 'liste_val'
- return t_fonction(liste_val,map(self,liste_val),self.para)
+ """renvoie la mm fonction interpolée aux points définis par la liste 'liste_val'
+ """
+ return self.__class__(liste_val,map(self,liste_val),self.para)
def sup(self,other) :
- # renvoie l'enveloppe supérieure de self et other
+ """renvoie l'enveloppe supérieure de self et other
+ """
para=copy.copy(self.para)
-# commentaire : pour les prolongements et l'interpolation, c'est self
-# qui prime sur other
+ # commentaire : pour les prolongements et l'interpolation, c'est self
+ # qui prime sur other
vale_x=self.vale_x.tolist()+other.vale_x.tolist()
-# on ote les abscisses doublons
+ # on ote les abscisses doublons
vale_x=dict([(i,0) for i in vale_x]).keys()
vale_x.sort()
vale_x=array(vale_x)
return t_fonction(vale_x,vale_y,para)
def inf(self,other) :
- # renvoie l'enveloppe inférieure de self et other
+ """renvoie l'enveloppe inférieure de self et other
+ """
para=copy.copy(self.para)
-# commentaire : pour les prolongements et l'interpolation, c'est self
-# qui prime sur other
+ # commentaire : pour les prolongements et l'interpolation, c'est self
+ # qui prime sur other
vale_x=self.vale_x.tolist()+other.vale_x.tolist()
-# on ote les abscisses doublons
+ # on ote les abscisses doublons
vale_x=dict([(i,0) for i in vale_x]).keys()
vale_x.sort()
vale_x=array(vale_x)
return t_fonction(vale_x,vale_y,para)
def suppr_tend(self) :
- # pour les corrections d'accélérogrammes
- # suppression de la tendance moyenne d'une fonction
+ """pour les corrections d'accélérogrammes
+ suppression de la tendance moyenne d'une fonction
+ """
para=copy.copy(self.para)
xy=sum(self.vale_x*self.vale_y)
x0=sum(self.vale_x)
return t_fonction(self.vale_x,self.vale_y-a1*self.vale_x-a0,self.para)
def normel2(self) :
- # norme de la fonction
+ """norme de la fonction
+ """
__ex=self*self
__ex=__ex.trapeze(0.)
return sqrt(__ex.vale_y[-1])
def fft(self,methode) :
- # renvoie la transformée de Fourier rapide FFT
+ """renvoie la transformée de Fourier rapide FFT
+ """
import FFT
para=copy.copy(self.para)
para['NOM_PARA']='FREQ'
if self.para['NOM_PARA']!='INST' :
- raise StandardError, 'fonction réelle : FFT : NOM_PARA=INST pour une transformée directe'
+ raise FonctionError, 'fonction réelle : FFT : NOM_PARA=INST pour une transformée directe'
pas = self.vale_x[1]-self.vale_x[0]
for i in range(1,len(self.vale_x)) :
ecart = abs(((self.vale_x[i]-self.vale_x[i-1])-pas)/pas)
if ecart>1.e-2 :
- raise StandardError, 'fonction réelle : FFT : la fonction doit etre à pas constant'
+ raise FonctionError, 'fonction réelle : FFT : la fonction doit etre à pas constant'
n=int(log(len(self.vale_x))/log(2))
if methode=='TRONCATURE' :
vale_y=self.vale_y[:2**n]
return t_fonction_c(vale_x,vale_y,para)
class t_fonction_c(t_fonction) :
- ### Classe pour fonctions complexes, équivalent au type aster = fonction_c
+ """Classe pour fonctions complexes, équivalent au type aster = fonction_c
+ """
def tabul(self) :
- # mise en forme de la fonction selon un vecteur unique (x1,yr1,yi1,x2,yr2,yr2,...)
+ """mise en forme de la fonction selon un vecteur unique (x1,yr1,yi1,x2,yr2,yr2,...)
+ """
__tab=array([self.vale_x,self.vale_y.real,self.vale_y.imag])
return ravel(transpose(__tab)).tolist()
def __repr__(self) :
- # affichage de la fonction en double colonne
+ """affichage de la fonction en double colonne
+ """
texte=[]
for i in range(len(self.vale_x)) :
texte.append('%f %f + %f .j' % (self.vale_x[i],self.vale_y[i].real,self.vale_y[i].imag))
return '\n'.join(texte)
def fft(self,methode,syme) :
- # renvoie la transformée de Fourier rapide FFT (sens inverse)
+ """renvoie la transformée de Fourier rapide FFT (sens inverse)
+ """
import FFT
para=copy.copy(self.para)
para['NOM_PARA']='INST'
if self.para['NOM_PARA']!='FREQ' :
- raise StandardError, 'fonction complexe : FFT : NOM_PARA=FREQ pour une transformée directe'
+ raise FonctionError, 'fonction complexe : FFT : NOM_PARA=FREQ pour une transformée directe'
pas = self.vale_x[1]-self.vale_x[0]
for i in range(1,len(self.vale_x)) :
ecart = abs(((self.vale_x[i]-self.vale_x[i-1])-pas)/pas)
if ecart>1.e-3 :
- raise StandardError, 'fonction complexe : FFT : la fonction doit etre à pas constant'
+ raise FonctionError, 'fonction complexe : FFT : la fonction doit etre à pas constant'
n=int(log(len(self.vale_x))/log(2))
if syme=='OUI' and len(self.vale_x)==2**n :
vale_fonc=self.vale_y
vale_fonc=vale_fonc+vale_fon1
vale_fonc=array(vale_fonc)
if syme=='OUI' and len(self.vale_x)!=2**n :
- raise StandardError, 'fonction complexe : FFT : syme=OUI et nombre de points<>2**n'
+ raise FonctionError, 'fonction complexe : FFT : syme=OUI et nombre de points<>2**n'
part1=vale_fonc[:len(vale_fonc)/2+1]
part2=vale_fonc[1:len(vale_fonc)/2]
part2=conjugate(part2)
class t_nappe :
- ### Classe pour nappes, équivalent au type aster = nappe_sdaster
+ """Classe pour nappes, équivalent au type aster = nappe_sdaster
+ """
def __init__(self,vale_para,l_fonc,para) :
- # création d'un objet nappe
- # vale_para est la liste de valeur des parametres (mot clé PARA dans DEFI_NAPPE)
- # para est un dictionnaire contenant les entrées PROL_DROITE, PROL_GAUCHE et INTERPOL (cf sd ASTER)
- # l_fonc est la liste des fonctions, de cardinal égal à celui de vale_para
+ """Création d'un objet nappe
+ - vale_para est la liste de valeur des parametres (mot clé PARA dans DEFI_NAPPE)
+ - para est un dictionnaire contenant les entrées PROL_DROITE, PROL_GAUCHE et INTERPOL (cf sd ASTER)
+ - l_fonc est la liste des fonctions, de cardinal égal à celui de vale_para
+ """
pk=para.keys()
pk.sort()
if pk!=['INTERPOL','NOM_PARA','NOM_PARA_FONC','NOM_RESU','PROL_DROITE','PROL_GAUCHE'] :
- raise StandardError, 'nappe : parametres incorrects'
+ raise FonctionError, 'nappe : parametres incorrects'
if para['INTERPOL'] not in [['NON','NON'],['LIN','LIN'],
['LIN','LOG'],['LOG','LOG'],['LOG','LIN'],] :
- raise StandardError, 'nappe : parametre INTERPOL incorrect'
+ raise FonctionError, 'nappe : parametre INTERPOL incorrect'
if para['PROL_DROITE'] not in ['EXCLU','CONSTANT','LINEAIRE'] :
- raise StandardError, 'nappe : parametre PROL_DROITE incorrect'
+ raise FonctionError, 'nappe : parametre PROL_DROITE incorrect'
if para['PROL_GAUCHE'] not in ['EXCLU','CONSTANT','LINEAIRE'] :
- raise StandardError, 'nappe : parametre PROL_GAUCHE incorrect'
+ raise FonctionError, 'nappe : parametre PROL_GAUCHE incorrect'
self.vale_para = array(vale_para)
if type(l_fonc) not in (types.ListType,types.TupleType) :
- raise StandardError, 'nappe : la liste de fonctions fournie n est pas une liste'
+ raise FonctionError, 'nappe : la liste de fonctions fournie n est pas une liste'
if len(l_fonc)!=len(vale_para) :
- raise StandardError, 'nappe : nombre de fonctions différent du nombre de valeurs du paramètre'
+ raise FonctionError, 'nappe : nombre de fonctions différent du nombre de valeurs du paramètre'
for f in l_fonc :
if not isinstance(f,t_fonction) and not isinstance(f,t_fonction_c) :
- raise StandardError, 'nappe : les fonctions fournies ne sont pas du bon type'
+ raise FonctionError, 'nappe : les fonctions fournies ne sont pas du bon type'
self.l_fonc = l_fonc
self.para = para
def __call__(self,val1,val2):
- # méthode pour évaluer nappe(val1,val2)
+ """méthode pour évaluer nappe(val1,val2)
+ """
i=searchsorted(self.vale_para,val1)
n=len(self.vale_para)
if i==0 :
if val1==self.vale_para[0] : return self.l_fonc[0](val2)
if val1 <self.vale_para[0] :
- if self.para['PROL_GAUCHE']=='EXCLU' : raise StandardError, 'nappe évaluée hors du domaine de définition'
+ if self.para['PROL_GAUCHE']=='EXCLU' : raise FonctionError, 'nappe évaluée hors du domaine de définition'
if self.para['PROL_GAUCHE']=='CONSTANT' : return self.l_fonc[0](val2)
if self.para['PROL_GAUCHE']=='LINEAIRE' : return interp(self.para['INTERPOL'],val1,
self.vale_para[0],
elif i==n :
if val1==self.vale_para[-1] : return self.l_fonc[-1](val2)
if val1 >self.vale_para[-1] :
- if self.para['PROL_DROITE']=='EXCLU' : raise StandardError, 'nappe évaluée hors du domaine de définition'
+ if self.para['PROL_DROITE']=='EXCLU' : raise FonctionError, 'nappe évaluée hors du domaine de définition'
if self.para['PROL_DROITE']=='CONSTANT' : return self.l_fonc[-1](val2)
if self.para['PROL_DROITE']=='LINEAIRE' : return interp(self.para['INTERPOL'],val1,
self.vale_para[-1],
self.l_fonc[i-1](val2),
self.l_fonc[i](val2))
+ def evalfonc(self, liste_val) :
+ """Renvoie la mm nappe dont les fonctions sont interpolées aux points définis
+ par la liste 'liste_val'.
+ """
+ l_fonc = []
+ for f in self.l_fonc:
+ f2 = f.evalfonc(liste_val)
+ l_fonc.append(f2)
+ return t_nappe(self.vale_para, l_fonc, self.para)
+
def __add__(self,other) :
- # addition avec une autre nappe ou un nombre, par surcharge de l'opérateur +
+ """addition avec une autre nappe ou un nombre, par surcharge de l'opérateur +
+ """
l_fonc=[]
if isinstance(other,t_nappe):
- if self.vale_para!=other.vale_para : raise StandardError, 'nappes à valeurs de paramètres différentes'
+ if self.vale_para!=other.vale_para : raise FonctionError, 'nappes à valeurs de paramètres différentes'
for i in range(len(self.l_fonc)) : l_fonc.append(self.l_fonc[i]+other.l_fonc[i])
elif type(other) in [types.FloatType,types.IntType] :
for i in range(len(self.l_fonc)) : l_fonc.append(self.l_fonc[i]+other)
- else: raise StandardError, 't_nappe : erreur de type dans __add__'
+ else: raise FonctionError, 't_nappe : erreur de type dans __add__'
return t_nappe(self.vale_para,l_fonc,self.para)
def __mul__(self,other) :
- # multiplication avec une autre fonction ou un nombre, par surcharge de l'opérateur *
+ """multiplication avec une autre fonction ou un nombre, par surcharge de l'opérateur *
+ """
l_fonc=[]
if isinstance(other,t_nappe):
- if self.vale_para!=other.vale_para : raise StandardError, 'nappes à valeurs de paramètres différentes'
+ if self.vale_para!=other.vale_para : raise FonctionError, 'nappes à valeurs de paramètres différentes'
for i in range(len(self.l_fonc)) : l_fonc.append(self.l_fonc[i]*other.l_fonc[i])
elif type(other) in [types.FloatType,types.IntType] :
for i in range(len(self.l_fonc)) : l_fonc.append(self.l_fonc[i]*other)
- else: raise StandardError, 't_nappe : erreur de type dans __mul__'
+ else: raise FonctionError, 't_nappe : erreur de type dans __mul__'
return t_nappe(self.vale_para,l_fonc,self.para)
def __repr__(self) :
- # affichage de la nappe en double colonne
+ """affichage de la nappe en double colonne
+ """
texte=[]
for i in range(len(self.vale_para)) :
texte.append('paramètre : %f' % self.vale_para[i])
return '\n'.join(texte)
def homo_support(self,other) :
- # renvoie la nappe self avec un support union de celui de self et de other
- # le support est la discrétisation vale_para et les discrétisations des fonctions
+ """Renvoie la nappe self avec un support union de celui de self et de other
+ le support est la discrétisation vale_para et les discrétisations des fonctions
+ """
if self==other : return self
- if self.para!=other.para : raise StandardError, 'combinaison de nappes à caractéristiques interpolation et prolongement différentes'
+ if self.para!=other.para : raise FonctionError, 'combinaison de nappes à caractéristiques interpolation et prolongement différentes'
vale_para=self.vale_para.tolist()+other.vale_para.tolist()
vale_para=dict([(i,0) for i in vale_para]).keys()
vale_para.sort()
l_fonc.append(t_fonction(new_vale_x,new_vale_y,new_para))
if isinstance(other_fonc,t_fonction_c) :
l_fonc.append(t_fonction_c(new_vale_x,new_vale_y,new_para))
- else : raise StandardError, 'combinaison de nappes : incohérence'
+ else : raise FonctionError, 'combinaison de nappes : incohérence'
return t_nappe(vale_para,l_fonc,self.para)
def extreme(self) :
- # renvoie un dictionnaire des valeurs d'ordonnées min et max
+ """renvoie un dictionnaire des valeurs d'ordonnées min et max
+ """
val_min=min([min(fonc.vale_y) for fonc in self.l_fonc])
val_max=max([max(fonc.vale_y) for fonc in self.l_fonc])
vm={'min':[],'max':[]}