#@ MODIF lire_fonction_ops Macro  DATE 26/05/2005   AUTEUR MCOURTOI M.COURTOIS 
# -*- coding: iso-8859-1 -*-
#            CONFIGURATION MANAGEMENT OF EDF VERSION
# ======================================================================
# COPYRIGHT (C) 1991 - 2004  EDF R&D                  WWW.CODE-ASTER.ORG
# THIS PROGRAM IS FREE SOFTWARE; YOU CAN REDISTRIBUTE IT AND/OR MODIFY  
# IT UNDER THE TERMS OF THE GNU GENERAL PUBLIC LICENSE AS PUBLISHED BY  
# THE FREE SOFTWARE FOUNDATION; EITHER VERSION 2 OF THE LICENSE, OR     
# (AT YOUR OPTION) ANY LATER VERSION.                                                  
#                                                                       
# THIS PROGRAM IS DISTRIBUTED IN THE HOPE THAT IT WILL BE USEFUL, BUT   
# WITHOUT ANY WARRANTY; WITHOUT EVEN THE IMPLIED WARRANTY OF            
# MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. SEE THE GNU      
# GENERAL PUBLIC LICENSE FOR MORE DETAILS.                              
#                                                                       
# YOU SHOULD HAVE RECEIVED A COPY OF THE GNU GENERAL PUBLIC LICENSE     
# ALONG WITH THIS PROGRAM; IF NOT, WRITE TO EDF R&D CODE_ASTER,         
#    1 AVENUE DU GENERAL DE GAULLE, 92141 CLAMART CEDEX, FRANCE.        
# ======================================================================

import os.path, Numeric

# ------------------------------------------------------------------------------
def lire_blocs(nomfich, SEPAR):
   """Retourne la liste des blocs
   """
   def info(ib, nlig, ncol):
      """Affiche les infos d'un bloc"""
      print "   . Bloc %2d : %6d lignes, %6d colonnes" % (ib, nlig, ncol)
   print "  Lecture des blocs du fichier '%s'" % nomfich
   fich=open(nomfich, 'r')
   ier=0
   message = ''
   if SEPAR=='None' : SEPAR=None
   blocs  = []
   lignes = []
   llen=0
   il=0
   for line in fich:
      il+=1
      try:
         if line.strip()=='':
            raise ValueError
         splin = line.split(SEPAR)
         lignes.append(map(float, splin))
         if llen==0:
            llen=len(splin)
         elif len(splin)<>llen:
            ier+=1
            message='Ligne %d : %d champs au lieu de %d attendus' % (il,len(splin),llen)
            return ier, message, []
      except ValueError:
         if lignes==[]:
            pass  # dans ce cas, on a plusieurs lignes délimitant 2 fonctions
         else:
            blocs.append(Numeric.array(lignes))
            info(len(blocs), len(lignes), llen)
            lignes=[]
            llen=0
   fich.close()
   if lignes!=[] :
      blocs.append(Numeric.array(lignes))
      info(len(blocs), len(lignes), llen)
   return ier, message, blocs

# ------------------------------------------------------------------------------
def liste_double(nomfich,INDIC_PARA,INDIC_RESU,SEPAR):
  """Méthode de construction du VALE pour le format libre
  format LIBRE
  Les lignes contenant autre chose que des séquences de nombres
  réels et de séparateurs sont considérées comme délimitant deux
  fonctions différentes. Cette situation correspond à l exception
  ValueError levée par le map de float. Le deuxieme indice de
  INDIC_PARA et INDIC_RESU est l indice permettant de pointer sur la
  fonction voulue, au sens de ce découpage.
  """
  from Utilitai.transpose import transpose
  ier, message, blocs = lire_blocs(nomfich, SEPAR)
  if ier<>0:
     return ier,message,[]

  # vérifications de cohérences lignes et colonnes
  nb_blocs = len(blocs)
  bloc_para = INDIC_PARA[0]
  col_para  = INDIC_PARA[1]
  bloc_resu = INDIC_RESU[0]
  col_resu  = INDIC_RESU[1]
  msg=[]
  if bloc_para>nb_blocs :
     ier+=1
     msg.append("Il y a %d blocs or INDIC_PARA=(%d, .)" % (nb_blocs, bloc_para))
  if bloc_resu>nb_blocs:
     ier+=1
     msg.append("Il y a %d blocs or INDIC_RESU=(%d, .)" % (nb_blocs, bloc_resu))
  if ier<>0:
     return ier, '\n'.join(msg), []

  if col_para>len(blocs[bloc_para-1][0]):
     ier+=1
     msg.append("Le bloc %d comporte %d colonnes or INDIC_PARA=(., %d)" % \
         (bloc_para, len(blocs[bloc_para-1][0]), col_para))
  if col_resu>len(blocs[bloc_resu-1][0]) :
     ier+=1
     msg.append("Le bloc %d comporte %d colonnes or INDIC_RESU=(., %d)" % \
         (bloc_resu, len(blocs[bloc_resu-1][0]), col_resu))
  if ier<>0:
     return ier, '\n'.join(msg), []

  # construction du VALE de la fonction par recherche des indices
  # de colonnes et de fonctions dans le tableau blocs
  vale_para = blocs[bloc_para-1][:,col_para-1]
  vale_resu = blocs[bloc_resu-1][:,col_resu-1]
  if len(vale_para)!=len(vale_resu) :
     ier+=1
     print 'VALE_PARA =', vale_para
     print 'VALE_RESU =', vale_resu
     message="""Les deux colonnes extraites n'ont pas la meme longueur
         %d lignes pour PARA
         %d lignes pour RESU""" % (len(vale_para), len(vale_resu))
  if ier<>0:
     return ier,message,[]

  laux=transpose([vale_para, vale_resu])
  liste_vale=[]
  for v in laux: liste_vale.extend(v)
  return ier,'',liste_vale

# ------------------------------------------------------------------------------
def liste_simple(nomfich,INDIC_PARA,SEPAR):
  """recherche d'une liste simple
  """
  ier, message, blocs = lire_blocs(nomfich, SEPAR)

  # vérifications de cohérences lignes et colonnes
  nb_blocs = len(blocs)
  bloc_para = INDIC_PARA[0]
  col_para  = INDIC_PARA[1]
  msg=[]
  if bloc_para>nb_blocs :
     ier+=1
     msg.append("Il y a %d blocs or INDIC_PARA=(%d, .)" % (nb_blocs, bloc_para))
  if col_para>len(blocs[bloc_para-1][0]):
     ier+=1
     msg.append("Le bloc %d comporte %d colonnes or INDIC_PARA=(., %d)" % \
         (bloc_para, len(blocs[bloc_para-1][0]), col_para))
  if ier<>0:
     return ier, '\n'.join(msg), []

  # construction du VALE de la fonction par recherche des indices
  # de colonnes et de fonctions dans le tableau l_fonc
  vale_1=blocs[bloc_para-1][:,col_para-1]
  return ier,'',vale_1.tolist()

# ------------------------------------------------------------------------------
def lire_fonction_ops(self,FORMAT,TYPE,SEPAR,INDIC_PARA,UNITE,
                      NOM_PARA,NOM_RESU,INTERPOL,PROL_DROITE,
                      PROL_GAUCHE,VERIF,INFO,TITRE,**args):
  """Méthode corps de la macro
  """
  from Accas import _F
  from Utilitai.Utmess     import UTMESS
  from Utilitai.UniteAster import UniteAster

  ier=0
  # La macro compte pour 1 dans la numerotation des commandes
  self.set_icmd(1)

  # On recopie le mot cle defi_fonction pour le proteger
  if TYPE=='NAPPE' :
     mc_DEFI_FONCTION=args['DEFI_FONCTION']

  # On importe les definitions des commandes a utiliser dans la macro
  DEFI_FONCTION  =self.get_cmd('DEFI_FONCTION')
  DEFI_NAPPE     =self.get_cmd('DEFI_NAPPE')

  nompro='LIRE_FONCTION'

  # Lecture de la fonction dans un fichier d unité logique UNITE
  UL = UniteAster()
  nomfich=UL.Nom(UNITE)
  if not os.path.isfile(nomfich):
     UTMESS('F', nompro, "le fichier '%s' est introuvable" % nomfich)

  # fonction(_c) ou nappe en sortie
  self.DeclareOut('ut_fonc',self.sd)

  if   TYPE=='FONCTION':
    # mise en forme de la liste de valeurs suivant le format choisi :
    ier,message,liste_vale=liste_double(nomfich,INDIC_PARA,args['INDIC_RESU'],SEPAR)
    if ier!=0:  UTMESS('F', nompro, message)

    # création de la fonction ASTER :
    ut_fonc=DEFI_FONCTION( NOM_PARA   =NOM_PARA,
                           NOM_RESU   =NOM_RESU,
                           PROL_DROITE=PROL_DROITE,
                           PROL_GAUCHE=PROL_GAUCHE,
                           INTERPOL   =INTERPOL,
                           INFO       =INFO,
                           TITRE      =TITRE,
                           VERIF      =VERIF,
                           VALE       =liste_vale,)

  elif TYPE=='FONCTION_C':
    # mise en forme de la liste de valeurs suivant le format choisi :
    if 'INDIC_REEL' in args :
                              indic1=args['INDIC_REEL']
                              indic2=args['INDIC_IMAG']
    if 'INDIC_MODU' in args :
                              indic1=args['INDIC_MODU']
                              indic2=args['INDIC_PHAS']
    ier,message,liste_vale_r=liste_double(nomfich,INDIC_PARA,indic1,SEPAR)
    if ier!=0:  UTMESS('F', nompro, message)

    ier,message,liste_vale_i=liste_double(nomfich,INDIC_PARA,indic2,SEPAR)
    if ier!=0:  UTMESS('F', nompro, message)

    liste=[]
    if   'INDIC_REEL' in args :
      for i in range(len(liste_vale_r)/2) :
        liste.extend([liste_vale_r[2*i],liste_vale_r[2*i+1],liste_vale_i[2*i+1]])
    elif 'INDIC_MODU' in args :
      for i in range(len(liste_vale_r)/2) :
        module=liste_vale_r[2*i+1]
        phase =liste_vale_i[2*i+1]
        liste.extend([liste_vale_r[2*i],module*cos(phase),module*sin(phase)])

    # création de la fonction ASTER :
    ut_fonc=DEFI_FONCTION( NOM_PARA    =NOM_PARA,
                           NOM_RESU    =NOM_RESU,
                           PROL_DROITE =PROL_DROITE,
                           PROL_GAUCHE =PROL_GAUCHE,
                           INTERPOL    =INTERPOL,
                           INFO        =INFO,
                           TITRE       =TITRE,
                           VERIF       =VERIF,
                           VALE_C      =liste,)

  elif TYPE=='NAPPE':

    # création de la nappe ASTER :
    motscles={}
    motscles['DEFI_FONCTION']=[]
    for elem in mc_DEFI_FONCTION:
       ier,message,liste_vale=liste_double(nomfich,args['INDIC_ABSCISSE'],elem['INDIC_RESU'],SEPAR)
       if ier!=0:  UTMESS('F', nompro, message)

       motscles['DEFI_FONCTION'].append( _F( VALE       =liste_vale,
                                             INTERPOL   =args['INTERPOL_FONC'],
                                             PROL_DROITE=args['PROL_DROITE_FONC'],
                                             PROL_GAUCHE=args['PROL_GAUCHE_FONC'] ) )
    ier,message,liste_para=liste_simple(nomfich,INDIC_PARA,SEPAR)
    if ier!=0:  UTMESS('F', nompro, message)

    # création de la nappe
    ut_fonc=DEFI_NAPPE( PARA          =liste_para,
                        NOM_PARA      =NOM_PARA,
                        NOM_PARA_FONC =args['NOM_PARA_FONC'],
                        NOM_RESU      =NOM_RESU,
                        PROL_DROITE   =PROL_DROITE,
                        PROL_GAUCHE   =PROL_GAUCHE,
                        INTERPOL      =INTERPOL,
                        INFO          =INFO,
                        TITRE         =TITRE,
                        VERIF         =VERIF,
                        **motscles)
  # remet UNITE dans son état initial
  UL.EtatInit()
  return ier
