1 #@ MODIF calc_spec_ops Macro DATE 21/10/2008 AUTEUR CORUS M.CORUS
3 # CONFIGURATION MANAGEMENT OF EDF VERSION
4 # ======================================================================
5 # COPYRIGHT (C) 1991 - 2008 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 # ======================================================================
23 from SD.sd_fonction import sd_fonction
25 # -----------------------------------------------------------------------------
26 class FonctionError(Exception): pass
27 class ParametreError(FonctionError): pass # probleme de NOM_PARA
28 class InterpolationError(FonctionError): pass
29 class ProlongementError(FonctionError): pass
31 # -----------------------------------------------------------------------------
34 def calc_spec_ops(self,TAB_ECHANT,ECHANT,INTERSPE,TRANSFERT,TITRE,INFO,**args):
35 # ------------------------------------------------------------------
36 # Calcul d'une matrice interspectrale
37 # a partir de fonctions reelles
40 from types import ListType, TupleType
41 EnumTypes = (ListType, TupleType)
43 from Utilitai.Utmess import UTMESS
50 # La macro compte pour 1 dans la numerotation des commandes
53 # Le concept sortant (de type table_sdaster ou derive) est tab
54 self.DeclareOut('tabout', self.sd)
56 # On importe les definitions des commandes a utiliser dans la macro
57 # Le nom de la variable doit etre obligatoirement le nom de la commande
58 CREA_TABLE = self.get_cmd('CREA_TABLE')
59 CALC_TABLE = self.get_cmd('CALC_TABLE')
60 DEFI_FONCTION = self.get_cmd('DEFI_FONCTION')
62 #--- Verifications sur les entrees --#
64 if (ECHANT==None and TAB_ECHANT==None) :
65 raise FonctionError, 'Vous devez specifier des fonctions en entree'
67 if TAB_ECHANT==None : TAB_ECHANT=[]
68 if ECHANT==None : ECHANT=[]
69 if INTERSPE==None : INTERSPE=[]
70 if TRANSFERT==None : TRANSFERT=[]
71 if len(TAB_ECHANT)*len(ECHANT) !=0 :
72 raise FonctionError, 'Vous pouvez specifier une table_fonction ou' + ' une liste de fonctions en entree, mais pas les deux'
73 if len(TRANSFERT)*len(INTERSPE) !=0 :
74 raise FonctionError, 'Vous ne pouvez specifier qu' +"'"+'un type de calcul par appel'
78 #-- Recuperation des entrees --#
84 # for occ in TAB_ECHANT :
85 # l_t.append(('TAB_ECHANT',occ))
87 l_t = TAB_ECHANT.List_F()[0]
90 l_f.append(('ECHANT',occ))
92 l_G.append(('INTERSPE',occ))
93 for occ in TRANSFERT :
94 l_H.append(('TRANSFERT',occ))
97 # Pour dimensionner les fenetres :
98 # Cas ECHANT : on recupere simplement la premiere fonction
99 # Cas_TAB_ECHANT : on recupere toutes les fonctions
102 vale_sig=l_f[0][1]['FONCTION'].Valeurs();
103 l_ech=len(vale_sig[0])
104 dt=vale_sig[0][1]-vale_sig[0][0]
106 #tab_ast=l_t[0][1]['NOM_TAB'];
107 tab_ast=l_t['NOM_TAB'] #MC
108 tab_py=tab_ast.EXTR_TABLE();
110 nom_fonc= tab_py['FONCTION'].values()['FONCTION']
111 fonc_py = [sd_fonction(fonc) for fonc in nom_fonc]
112 temp=fonc_py[0].VALE.get();
115 l_ech_temp=l_t['LONGUEUR_ECH'];
116 recouvr_temp=l_t['RECOUVREMENT'];
117 l_ech_t=[l_ech_temp[0]['DUREE'] , l_ech_temp[0]['POURCENT'],l_ech_temp[0]['NB_PTS'] ];
118 recouvr_t=[recouvr_temp[0]['DUREE'] , recouvr_temp[0]['POURCENT'],recouvr_temp[0]['NB_PTS'] ];
119 if l_ech_t.count(None)==3 : l_ech=len(temp)/2;
120 if recouvr_t.count(None)==3 : recouvr=0;
121 if l_ech_t.count(None)<2 :
122 raise FonctionError, 'Vous ne pouvez utiliser qu'+"'"+ 'un mot clef pour definir la longueur des echantillons'
123 if recouvr_t.count(None)<2 :
124 raise FonctionError, 'Vous ne pouvez utiliser qu'+"'"+'un mot clef pour definir la longueur de recouvrement des echantillons'
126 if l_ech_t[i1] !=None :
128 l_ech=int(Numeric.floor(l_ech_t[i1]/dt));
130 l_ech=int(Numeric.floor((len(temp)/2)*l_ech_t[i1]*0.01));
132 l_ech=int(Numeric.floor(l_ech_t[i1]))
133 if l_ech > len(temp)/2 :
134 raise FonctionError, 'Vous devez specifier une longueur d'+"'"+'echantillon inferieure a la longueur totale de l'+"'"+'acquisition'
136 if recouvr_t[i1] !=None :
138 recouvr=int(Numeric.floor(recouvr_t[i1]/dt));
140 recouvr=int(Numeric.floor((l_ech)*recouvr_t[i1]*0.01));
142 recouvr=int(Numeric.floor(recouvr_t[i1]))
144 raise FonctionError, 'La longueur de recouvrement ne peut exceder la longueur '
146 #-- Recuperation des fenetres
149 if occ[1]['FENETRE'] == 'RECT' :
151 elif occ[1]['FENETRE'] == 'HAMM' :
152 fene=[0.54-0.46*Numeric.cos(2*Numeric.pi*i1/(l_ech-1)) for i1 in range(l_ech)]
153 elif occ[1]['FENETRE'] == 'HANN' :
154 fene=[0.5-0.5*Numeric.cos(2*Numeric.pi*i1/(l_ech-1)) for i1 in range(l_ech)]
155 elif occ[1]['FENETRE'] == 'EXPO' :
156 para=occ[1]['DEFI_FENE']
158 raise FonctionError, 'Erreur de taille dans DEFI_FENE : ' + 'la fenetre exponentielle est definie par exactement deux valeurs'
159 fene=[1.]*int(para[0]-1)+[Numeric.exp(para[1]*(i1-int(para[0]-1))*dt) for i1 in range(int(para[0]-1),l_ech)]
160 elif occ[1]['FENETRE'] == 'PART' :
161 fene=occ[1]['DEFI_FENE']
162 if len(fene) != l_ech :
163 raise FonctionError, 'Erreur de taille dans DEFI_FENE : ' + 'La fenetre doit etre definie avec le meme nombre de points que les echantillons'
165 if len(TRANSFERT)+len(INTERSPE) == 0 : #-- on ne rentre rien : interspectre par defaut - fenetre rectangulaire
170 #-- Recuperation des signaux --#
171 #-- Verifications et transformations de Fourier --#
172 #-- Entrees sous formes de table --#
183 if TAB_ECHANT : # Cas TAB_ECHANT
184 num_mes_temp= tab_py['NUME_MES'].values()['NUME_MES']
185 max_mes=Numeric.maximum.reduce(num_mes_temp);
186 num_ord_temp= tab_py['NUME_ORDRE_I'].values()['NUME_ORDRE_I']
187 long_fonc=[len(fonc_py[i1].VALE.get()) for i1 in range(len(fonc_py))]
189 N_fen=int(Numeric.floor((Numeric.minimum.reduce(long_fonc)/2-l_ech)/(l_ech-recouvr))+1)
193 for i1 in range(len(fonc_py)) :
194 vale=fonc_py[i1].VALE.get();
195 temp=(list(vale[0:int(len(vale)/2)]));
196 sig.append(list(vale[int(len(vale)/2):]));
197 test_pas=Numeric.subtract(temp[1:],temp[0:-1])
198 crit=test_pas.tolist();
201 if abs((crit[-1]-crit[0])/crit[-1]) > 1.e-5 :
202 raise FonctionError, 'L'+"'"+'echantillonage doit etre fait a pas constant'
204 for j1 in range(N_fen) :
205 for i1 in range(len(fonc_py)) :
206 fft.append(FFT.fft(Numeric.multiply(sig[i1][j1*(l_ech-recouvr):(j1*(l_ech-recouvr)+l_ech)],fene)))
207 if j1 == 0 : df.append(1./(dt[i1])/l_ech);
208 num_mes.append(num_mes_temp[i1]+max_mes*j1);
209 num_ord.append(num_ord_temp[i1]);
211 test_df=Numeric.subtract(df[1:],df[0:-1])
212 test_df=test_df.tolist();
214 if abs(test_df[-1]) > 1.e-5 :
215 raise FonctionError, 'Toutes les fonctions doivent etre definies ' + 'avec la meme frequence d'+"'"+'echantillonage'
217 frq = [df[-1]*i1 for i1 in range(l_ech)]
220 #-- Recuperation des signaux --#
221 #-- Verifications et transformations de Fourier --#
222 #-- Entrees sous formes de fonction --#
226 vale_sig=occ[1]['FONCTION'].Valeurs();
227 #-- pour les tests ulterieurs --#
228 lt.append(len(vale_sig[0]))
229 if len(vale_sig[0]) != len(vale_sig[1]) :
230 raise FonctionError, 'Les vecteurs associes au temps '+'et aux echantillons doivent etre de meme longueur'
231 num_mes.append(occ[1]['NUME_MES'])
232 num_ord.append(occ[1]['NUME_ORDRE_I'])
234 tmp.append(vale_sig[0])
235 test_pas=Numeric.subtract(vale_sig[0][1:],vale_sig[0][0:-1])
236 crit=test_pas.tolist();
238 if abs((crit[-1]-crit[0])/crit[-1]) > 1.e-5 :
239 raise FonctionError, 'L'+"'"+'echantillonage doit etre fait a pas constant'
240 fft.append(FFT.fft(Numeric.multiply(vale_sig[1],fene)))
241 df.append(1./(crit[-1])/len(vale_sig[0]));
244 #-- Verification des longueurs --#
246 test_long=Numeric.subtract(lt[1:],lt[0:-1])
247 test_long=test_long.tolist();
249 if (test_long[-1]-test_long[0]) != 0 :
250 raise FonctionError, 'Toutes les fonctions doivent etre definies avec le meme nombre de points'
253 test_df=Numeric.subtract(df[1:],df[0:-1])
254 test_df=test_df.tolist();
256 if abs(test_df[-1]) > 1.e-5 :
257 raise FonctionError, 'Toutes les fonctions doivent etre definies '+'avec la meme frequence d'+"'"+'echantillonage'
259 frq = [df[-1]*i1 for i1 in range(lt[-1])]
262 #-- index des numeros d'ordre pour le moyennage
272 list_ord.append(uu[0])
274 for i1 in range(uu.count(uu[0])) :
275 tt.append(vv.index(uu[0]))
278 uu=uu[int(uu.count(uu[0])):]
280 #-- Calcul de la matrice inter spectrale
282 if len(INTERSPE) != 0 :
283 dimh = (len(list_ord)*(len(list_ord)+1))/2
288 for i1 in range(len(list_ord)) :
289 for j1 in range(i1,len(list_ord)) :
290 #-- on ne calcule les spectres que pour des numeros de mesures correspondants
291 #-- Ca n'a a priori pas de sens de calculer l'interspectre entre deux signaux acquis a des instants differents
292 #-- Par contre, on peut moyenner deux interspectres obtenus a des instants differents, sous reserve
293 #-- de stationnarite et d'ergodicite du signal
294 mes_i1=[num_mes[k1] for k1 in ind_ord[i1]]
295 mes_j1=[num_mes[k1] for k1 in ind_ord[j1]]
297 #-- recuperation des indices des fft a prendre en compte pour l'interspectre
298 for k1 in range(len(mes_i1)) :
299 if mes_i1[k1] in mes_j1 :
300 ind_mes.append([ind_ord[i1][k1],ind_ord[j1][mes_j1.index(mes_i1[k1])]])
302 #-- Calcul des interspectres
304 if len(ind_mes) > 0 :
305 for l1 in range(len(ind_mes)) :
306 dsp_t=Numeric.multiply(Numeric.conjugate(fft[ind_mes[l1][0]]),fft[ind_mes[l1][1]])
307 dsp_t=Numeric.divide(dsp_t,l_ech*len(ind_mes))
308 dsp=Numeric.add(dsp,dsp_t)
312 for k1 in range(int(Numeric.floor(l_ech/2))) :
313 dsp_r=dsp_r+[frq[k1],dsp[k1].real,dsp[k1].imag]
315 _fonc = DEFI_FONCTION(NOM_PARA='FREQ',VALE_C=dsp_r,);
316 l_fc.append(_fonc.nom)
317 nume_i1.append(list_ord[i1])
318 nume_j1.append(list_ord[j1])
321 mcfact.append(_F(PARA='NOM_CHAM' ,LISTE_K='DSP' ))
322 mcfact.append(_F(PARA='OPTION' ,LISTE_K='TOUT' ))
323 mcfact.append(_F(PARA='DIMENSION' ,LISTE_I=(dimh,) ))
324 mcfact.append(_F(PARA='NUME_ORDRE_I',LISTE_I=nume_i1 ))
325 mcfact.append(_F(PARA='NUME_ORDRE_J',LISTE_I=nume_j1 ))
326 mcfact.append(_F(PARA='FONCTION_C' ,LISTE_K=l_fc ))
327 self.DeclareOut('tab_inte',self.sd)
328 tab_inte=CREA_TABLE(LISTE=mcfact,
330 TYPE_TABLE='TABLE_FONCTION')
333 #-- Calcul des transferts
335 if len(TRANSFERT) != 0 :
341 #-- test sur les entrees pour les references --#
342 if type(l_H[0][1]['REFER'])==int :
344 refer.append(l_H[0][1]['REFER'])
345 elif type(l_H[0][1]['REFER'])==tuple :
346 refer=list(l_H[0][1]['REFER'])
349 dimh = len(refer)*(len(list_ord)-len(refer))
350 for k1 in range(len(refer)) :
351 for l1 in range(len(list_ord)) :
352 if refer[k1] == list_ord[l1] : ind_refer.append(l1);
354 #-- H1 : interspectre / autospectre
355 #-- H2 : autospectre / interspectre
356 #-- CO : coherence entre H1 et H2.
358 if l_H[0][1]['ESTIM']!='HV' :
359 for i1 in range(len(refer)) :
360 for j1 in range(len(list_ord)) :
361 if refer[i1] != list_ord[j1] :
362 mes_i1=[num_mes[k1] for k1 in ind_ord[ind_refer[i1]]] #-- mesures des efforts
363 mes_j1=[num_mes[k1] for k1 in ind_ord[j1]] #-- mesures des reponses
365 #-- recuperation des indices des mesures a predre en compte pour les spectres
366 for k1 in range(len(mes_i1)) :
367 if mes_i1[k1] in mes_j1 :
368 ind_mes.append([ind_ord[i1][k1],ind_ord[j1][mes_j1.index(mes_i1[k1])]])
374 if len(ind_mes) > 0 :
375 for l1 in range(len(ind_mes)) :
376 Guu_t=Numeric.multiply(Numeric.conjugate(fft[ind_mes[l1][0]]),fft[ind_mes[l1][0]])
377 Guu=Numeric.add(Guu,Guu_t)
378 Gyu_t=Numeric.multiply(Numeric.conjugate(fft[ind_mes[l1][1]]),fft[ind_mes[l1][0]])
379 Gyu=Numeric.add(Gyu,Gyu_t)
380 Gyy_t=Numeric.multiply(Numeric.conjugate(fft[ind_mes[l1][1]]),fft[ind_mes[l1][1]])
381 Gyy=Numeric.add(Gyy,Gyy_t)
383 if l_H[0][1]['ESTIM']=='H1' :
384 frf=Numeric.divide(Numeric.conjugate(Gyu),Guu);
386 elif l_H[0][1]['ESTIM']=='H2' :
387 frf=Numeric.divide(Gyy,Gyu);
389 elif l_H[0][1]['ESTIM']=='CO' :
390 H1=Numeric.divide(Numeric.conjugate(Gyu),Guu);
391 H2=Numeric.divide(Gyy,Gyu);
392 frf=Numeric.divide(H1,H2);
398 for k1 in range(int(Numeric.floor(l_ech/2))) :
399 frf_r=frf_r+[frq[k1],frf[k1].real,frf[k1].imag]
401 _fonc = DEFI_FONCTION(NOM_PARA='FREQ',VALE_C=frf_r,);
402 l_fc.append(_fonc.nom)
403 nume_i1.append(refer[i1])
404 nume_j1.append(list_ord[j1])
406 #-- On remplit la table_fonction avec tout ce qui va bien
409 mcfact.append(_F(PARA='NOM_CHAM' ,LISTE_K=nom_frf ))
410 mcfact.append(_F(PARA='OPTION' ,LISTE_K='TOUT' ))
411 mcfact.append(_F(PARA='DIMENSION' ,LISTE_I=(dimh,) ))
412 mcfact.append(_F(PARA='NUME_ORDRE_I',LISTE_I=nume_i1 ))
413 mcfact.append(_F(PARA='NUME_ORDRE_J',LISTE_I=nume_j1 ))
414 mcfact.append(_F(PARA='FONCTION_C' ,LISTE_K=l_fc ))
415 self.DeclareOut('tab_inte',self.sd)
416 tab_inte=CREA_TABLE(LISTE=mcfact,
418 TYPE_TABLE='TABLE_FONCTION')