ManuelC Posted September 12, 2013 at 05:09 PM Report #524360 Posted September 12, 2013 at 05:09 PM (edited) Boa tarde, desde já obrigado pela atenção. Não sei se alguém me pode ajudar. Vou descrever o que pretendo que o meu código faça em cada intervalo do loop que em seguida descrevo: PRIMEIRO PAÇO DO LOOP: 1 - Correr um programa externo; 2 - Abrir um dos ficheiros de texto do output desse programa (tsr_seg6.txt) Exemplo do ficheiro tsr_seg6.txt ( os valores estão separados por espaços): --------------------------------------------------------------------------------------------------------------------- CE-QUAL-W2 Lagoa das Furnas - 1 Ramo Default hydraulic coefficients Model run at 16:51:57 on 09/12/13 JDAY DLT PO4 1 0.07 0.02 2 0.06 0.03 3 0.05 0.01 3 – Copiar o primeiro valor que se encontra na coluna PO4 (0.02) 4 – Abrir um outro ficheiro do modelo (ctr_tr3.npt) Exemplo do ficheiro ctr_tr3.npt (os valores estão separados por espaços): --------------------------------------------------------------------------------------------------------------------- JDAY DLT PO4 1 0.08 0.01 2 0.05 0.02 3 0.01 0.05 4 – substituir o primeiro valor que se encontra na coluna PO4 pelo valor obtido no ficheiro (tsr_seg6.txt). 5- voltar a correr o modelo 6 – No paço seguinte do loop faço o mesmo mas desta vez é o segundo valor do ficheiro tsr_seg6.txt que vai substituir o segundo valor do ficheiro ctr_tr3.npt . Volto a correr o modelo… 7 - No paço seguinte do loop faço o mesmo mas desta vez é o terceiro valor do ficheiro tsr_seg6.txt que vai substituir o terceiro valor do ficheiro ctr_tr3.npt Volto a correr o modelo… Tenho que fazer isto 20000 vezes…. Escrevi o seguinte código em Python que não funciona porque não consigo substituir os valores no ficheiro ctr_tr3.npt em cada intervalo do loop. import numpy as np import sys, string, os import shutil N=5 for i in xrange(N): os.chdir( 'c:\\Users\\Hidraulica\\Desktop\\w2furnas' ) os.system( ""C:\\Users\\Hidraulica\\Desktop\\w2furnas\\w2.exe"' ) shutil.move('tsr_1_seg6.opt', 'tsr_1_seg6.txt') data = np.genfromtxt('c:\\Users\\Hidraulica\\Desktop\\w2furnas\\tsr_1_seg6.txt', skip_header=11, names=True) input=np.array(data['PO4']) trib =np.genfromtxt('c:\\Users\\Hidraulica\\Desktop\\w2furnas\\ctr_tr3.npt', skip_header=2, names=True) out=np.array(trib['PO4']) out[i]= input[i]*0.75 with open('c:\\Users\\Hidraulica\\Desktop\\w2furnas\\ctr_tr3.npt','w') as fw: fw.write(' '.join(out)) Obrigado Manuel Edited September 12, 2013 at 06:26 PM by ManuelC GeSHi
Pedro C. Posted September 12, 2013 at 10:22 PM Report #524399 Posted September 12, 2013 at 10:22 PM Olá Manuel, Geralmente quando a tarefa se torna dantesca vale a pena separar tudo em funções pequenas bem controláveis. Os passos que me parecem essenciais são: 1) Correr programa 2) Recuperar o valor de um ficheiro 3) Escreve-lo noutro (e recomeça o ciclo) Penso que não precisas de todas as bibliotecas que estás a importar e por um motivo que não compreendo estás a multiplicar 0.75 pelo teu array. De qualquer maneira seguindo os passos dados acima e lendo e escrevendo ficheiros à maneira antiga terás qualquer coisa como isto. import numpy as np import os def corre_processo(wdir,path): os.chdir(wdir) # ESTABELECO A DIRECTORIA DE TRABALHO os.system(path) # CORRO O PROCESSO EXTERIOR return True def ler_ficheiro(path,header_number=5): fid = open(path,'r') # ESTOU A ABRIR O FICHEIRO PARA LEITURA header = [] # VARIAVEL QUE GUARDA O HEADER for i in xrange(header_number): header.append(fid.readline()) # ESTOU A PASSAR PARA UMA LISTA data = np.loadtxt(fid) # ESTOU A PASSAR A MATRIZ PARA UMA VARIAVEL fid.close() # FECHO O FICHEIRO return header,data def escrever_ficheiro(path,header,data): fid = open(path,'w') # ABRO O FICHEIRO PARA ESCRITA (w) for i in xrange(len(header)): fid.write(header[i]) # EsCREVO O HEADER np.savetxt(fid,data,fmt='%10.3f') # ESTE FMT SIGNIFICA 10 CARACTERES COM 3 CASAS DECIMAIS fid.close() # FECHO O FICHEIRO return True def recuperar_valor(path,index,column=2,header_number=5): header,data = ler_ficheiro(path,header_number) return data[index,column] def troca_valor(value,index,path,column=2,header_number=5): """ NAO E UMA OPERACAO VULGAR TROCAR UM VALOR NO FICHEIRO. NO TEU CASO (ASCII ou TEXTO) E PRECISO LER O FICHEIRO NA TOTALIDADE PARA VARIAVEIS, TROCAR O QUE TENS A TROCAR E VOLTAR A ESCREVER PARA A MESMA LOCALIZACAO. """ header,data = ler_ficheiro(path,header_number) # LEIO O FICHEIRO data[index,column] = value # TROCO O VALOR NO INDEX PRETENDIDO escrever_ficheiro(path,header,data) # ESCREVO O FICHEIRO NO MESMO CAMINHO return True def ciclo_principal(numero,wdir,ipath,opath,exepath,column=2,header_number=5): """ SEGUINDO O PROCEDIMENTO PEDIDO POR TI... """ for i in xrange(numero): corre_processo(wdir,wdir+exepath) # 1 - Correr um programa externo; value = recuperar_valor(wdir+ipath,i,column,header_number) # 2,3,4 -3 – Copiar o primeiro... troca_valor(value,i,wdir+opath,column,header_number) # 4 – substituir o primeiro valor que... print 'terminado CICLO ',i # ESTOU SO A AVISAR O UTILIZADOR QUE TERMINOU A VOLTA print 'TERMINADO' # ESTOU A AVISAR QUE O PROGRAMA TERMINOU return True numero = 5 # numero de ciclos (loops que pretendes) wdir = 'c:\\Users\\Hidraulica\\Desktop\\' # directoria de trabalho (onde tudo se processa) ipath = 'tsr_seg6.txt' # ficheiro de onde se retira valores opath = 'ctr_tr3.npt' # ficheiro onde se troca valores exepath = 'w2.exe' # ficheiro do executavel column = 2 # coluna onde se passam as trocas (python comeca em zero) header_number = 5 # tamanho do header ciclo_principal(numero,wdir,ipath,opath,exepath,column,header_number) # CORRER PROGRAMA Penso que os comentários devem chegar para se compreender o código na totalidade. Não o testei mas à partida deve funcionar. Se não compreenderes alguma coisa avisa. Boa sorte. Ah, uma coisa que é importante é a formatação dos ficheiro. Estou a usar um comando do numpy chamado savetxt que basicamente escreve números como os tem na variável para um ficheiro. No teu caso lê as três colunas para uma matrix "n por 3" e depois salva a matriz da mesma maneira. Por defeito penso que isto é feito como nomenclatura cientifica. Para evitar isto eu dei-lhe uma formatação especifica (o parâmetro "fmt"). Para mexeres com o "fmt" basta pensares na numeração que estás à espera e quantos caracteres (inclusive o ponto de separação decimal) vais precisar por cada numero. Assim se precisares de 10 caracteres, no máximo, e uma precisão de 3 casas decimais metes '%10.3f' e o numero 0.2343423543, por exemplo apareceria: .....0.234 (o espaço em branco antes do número, que represento aqui como pontos) é importante porque aparece também no ficheiro visto que pedimos 10 caracteres mas o número em causa só tem 5). Isto ajuda a que os teus ficheiro se mantenham organizados. Qualquer linguagem conseguirá lidar com diferentes tipos de dados. Agora se precisares mesmo que a primeira coluna seja de inteiros e as outras decimais (talvez por causa do executável que estás a correr) tens de começar a fabricar as tuas próprias funções de escrita (eu pelo menos não conheço nenhuma que faça já isto). A título de exemplo se eu no array numpy "data" tivesse uma matriz com 5 linhas e 3 colunas poderia escrever desta maneira: for i in xrange(5): fid.write('%i %10.3f %10.3f'%(data[i,0],data[i,1],data[i,2])) E assim estaria a precisar à coluna a maneira como queria o meu ficheiro formatado.
ManuelC Posted September 13, 2013 at 09:18 AM Author Report #524416 Posted September 13, 2013 at 09:18 AM Muito obrigado, pela ajuda. Consigo perceber o teu código. Vou usá-lo daqui em diante como um exemplo, para tudo o que tiver que fazer em python. Sem querer parecer abusador, há duas questões que ainda não sei bem como resolver. 1- o ficheiro 'tsr_seg6.txt' é um ficheiro que se encontra inicialmente como 'tsr_seg6.opt'. é gerado pelo modelo cada vez que este corre. Não tenho que lhe alterar a extensão?. Por isso utilizei: shutil.move('tsr_1_seg6.opt', 'tsr_1_seg6.txt'). 2- tenho que multiplicar cada valor que copio por 0.75. Pode ser aqui? data[index,column] = value *0.75 Obrigado mais uma vez. Manuel
icemonster2 Posted September 13, 2013 at 11:40 AM Report #524435 Posted September 13, 2013 at 11:40 AM 1- o ficheiro 'tsr_seg6.txt' é um ficheiro que se encontra inicialmente como 'tsr_seg6.opt'. é gerado pelo modelo cada vez que este corre. Não tenho que lhe alterar a extensão?. Por isso utilizei: shutil.move('tsr_1_seg6.opt', 'tsr_1_seg6.txt'). Não seria mais facil abrires o ficheiro.opt normalmente? A informação é a mesma. Nesse caso estar com a extensão .txt ou .opt é a mesma coisa por isso se não precisares de ter o ficheiro como texto, podes fazer isso
ManuelC Posted September 13, 2013 at 01:34 PM Author Report #524459 Posted September 13, 2013 at 01:34 PM (edited) Depois de todo o trabalho que tive e acima de tudo que tu tiveste não vou desistir de colocar isto a funcionar. Ao correr o código obtenho o seguinte erro: data = np.loadtxt(fid) # ESTOU A PASSAR A MATRIZ PARA UMA VARIAVEL File "C:\Python27\lib\site-packages\numpy\lib\npyio.py", line 796, in loadtxt items = [conv(val) for (conv, val) in zip(converters, vals)] ValueError: could not convert string to float: Lagoa O ficheiro tsr_seg6.opt tem 11 linhas com frases que não interessam antes de aparecerem os headers de cada coluna. Podes ajudar-me com isto? Não percebo com é que posso alterar a função ler_ficheiro...para que esta, tenho isto em consideração... Exemplo do ficheiro tsr_seg6.opt ------------------------------------------------------------------------------ Version 3.6 CE-QUAL-W2 Lagoa das Furnas - 1 Ramo Default hydraulic coefficients Default light absorption/extinction coeffients Lagoa das Furnas Simulação ANO 2008 GDHI, Setembro de 2009 Model run at 13:33:37 on 09/13/13 JDAY DLT PO4 1 0.07 0.02 2 0.06 0.03 3 0.05 0.01 --------------------------------------------------------------------- Obrigado Edited September 13, 2013 at 01:37 PM by ManuelC
Pedro C. Posted September 13, 2013 at 01:38 PM Report #524461 Posted September 13, 2013 at 01:38 PM (edited) Sim, é nessa linha de código o sitio onde deve ser feita a multiplicação. E tal como disse o icemonster2 os ficheiros de texto (ASCII) não têm, geralmente, associação com o nome do próprio ficheiro ao qual pertence a extensão. A extensão serve para processos externos ao ficheiro como por exemplo o windows saber, por defeito, que deve abrir todos os ficheiros terminados em .docx com o word. Ou então que todos os ficheiros terminados em .exe são processos executáveis sem necessidade de outro software (haja parcimónia na interpretação desta afirmação:)). Podes até tentar enganar estes programas alterando a extensão dos teus ficheiros e por vezes até vão ocorrer extensões que são comuns a mais de um software e um deles não vai conseguir abrir o ficheiro porque não tem o formato necessário. Um exemplo disto é a extensão .MOD. É uma extensão que dá para um ficheiro de música no entanto tinha outro software aqui que lia esses ficheiros como informação de um modelo matemático (MODelo). Um procurava um formato ascii outro binário. Ambos pretendiam abrir o ficheiro e o mais chato é que era o errado que estava predefinido para abrir essa extensão com o duplo click do rato. São as linhas de cabeçalho ou header. Um dos parâmetros do código é "header_number" em que meti 5 porque era o que aparecia no exemplo do teu primeiro post. Basicamente é o número de linhas do teu ficheiro que queres guardar para escrever novamente. Agora esse header_number está a ser utilizados para tanto o ficheiro tsr_seg6.opt como para o ctr_tr3.npt. Se ambos tiverem o mesmo número de linhas de cabeçalho basta mudar o parâmetro inicial. Caso contrário tens de mexer no código. Nomeadamente aqui: def ciclo_principal(numero,wdir,ipath,opath,exepath,column=2,header_number=11,header_number_2=5): # FIZ UPDATE """ SEGUINDO O PROCEDIMENTO PEDIDO POR TI... """ for i in xrange(numero): corre_processo(wdir,wdir+exepath) value = recuperar_valor(wdir+ipath,i,column,header_number) troca_valor(value,i,wdir+opath,column,header_number_2) # FIZ UPDATE print 'terminado CICLO ',i print 'TERMINADO' return True numero = 5 wdir = 'c:\\Users\\Hidraulica\\Desktop\\' ipath = 'tsr_seg6.txt' opath = 'ctr_tr3.npt' exepath = 'w2.exe' column = 2 header_number = 11 # tamanho do header do ficheiro de input (tsr_seg6.opt) header_number_2 = 5 # tamanho do header do ficheiro de troca de valores (ctr_tr3.npt) FIZ UPDATE ciclo_principal(numero,wdir,ipath,opath,exepath,column,header_number,header_number_2) # FIZ UPDATE Está indicado no código as linhas onde fiz um update. Na prática temos uma variável nova de entrada chamada "header_number_2" que é o número de linhas de cabeçalho do ficheiro "ctr". A variável "header_number" agora só dá informação do número de linha para o ficheiro "tsr". Actualizei: 1) a linha onde está criada a variável (e onde tens de meter o valor correcto). 2) a linha de chamada da função ciclo_principal (onde meti mais este novo parâmetro) 3) a linha de inicio da função ciclo_principal (onde tenho de meter mais o novo parâmetro de entrada) 4) a linha da chamada da função troca_valor (dentro do ciclo_principal) onde tenho de dizer que a variável de tamanho de cabeçalho passou a ser "header_number_2". Edited September 13, 2013 at 01:52 PM by Pedro C.
ManuelC Posted September 13, 2013 at 03:30 PM Author Report #524491 Posted September 13, 2013 at 03:30 PM (edited) Obrigado pela ajuda, está perfeito. Nunca aprendi tanto em tão pouco tempo. Com os melhores cumprimentos Manuel Almeida Edited September 13, 2013 at 04:43 PM by ManuelC
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now