[Rio-pm] Comparação de arquivos

Aureliano Guedes guedes_1000 em hotmail.com
Quinta Novembro 22 14:35:02 PST 2012


Opa, obrigado pela ajuda e pelas preciosas dicas.

- Não achei uma função no List::MoreUtils que fizesse o mesmo que o dups do Array::Uniq, tem alguma função no List::MoreUtils que crie um terceiro array apenas com itens que outros dois ou mais arrays tem em igual?

- Particularmente não vi vantagem em usar o Path::Class, para meu caso qual seria a vantagem?

- Quanto a criar um modulo fazendo o que as subs fazem, depois vou pensar nessa hipotese, mais um modulo para o BioPerl não faz mal.

- Quanto ao que você falou no item 11:

- Continuei usando barewords pois não deu certo usando strings, por algum motivo que não sei por que? (Afinal qual o problema das barewords?)

"11) No seu código você abre os arquivos 'hybrid.txt' e 'miranda.txt'
duas vezes para leitura. Isso normalmente significa que você poderia
ter colocado tudo numa estrutura de fácil acesso e manipulação, e lido
o arquivo apenas uma vez (operações de E/S costumam ser bem mais
pesadas do que manipulação em memória). Dica: sempre que tiver mais de
um while() ou foreach() varrendo a mesma estrutura para ler dados, é
bem possível que você possa otimizar e deixar mais claro seu algoritmo
fazendo a varredura apenas uma vez."

Isso me preocupou, veja bem, não consegui pensar em uma forma de varrer o arquivo fazendo o que preciso apenas em um laço.
parsin_h e parsin_m extraem um valor que são gravados em array, @inh e @inm respectivamente, depois um terceiro array (@in) é criado apenas com os valores que @inh e @inm tem em comum.
Os valores de @in são a referencia de "o que" eu quero extrair dos arquivos hybrid.txt e miranda.txt.

Realmente o excesso de operações I/O pesam mas infelizmente não estou conseguindo fugir disso, e desempenho na bioinformatica é importante.
Pesso ajuda para solucionar esse mistério tambem.

Outro problema é que o output esta feio e ainda o $/ esta sendo omitido.

link do script com as devidas alterações -> http://pastebin.com/DNuiLUHG
link do miranda.txt ->http://pastebin.com/qiYavtUe 
link do hybrid.txt -> http://pastebin.com/9v6WFUT7

Agora para exclarecer os arquivos:

Miranda pode ter dois formatos:

Read Sequence:hsa-miR-4448 MIMAT0018967 Homo sapiens miR-4448(20 nt)
Read Sequence:01010101 (582 nt)
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
Performing Scan: hsa-miR-4448 vs 01010101
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
Score for this Scan:
No Hits Found above Threshold
Complete

ou

Read Sequence:hsa-miR-4701-3p MIMAT0019799 Homo sapiens miR-4701-3p(20 nt)
Read Sequence:01010101 (582 nt)
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
Performing Scan: hsa-miR-4701-3p vs 01010101
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=

   Forward:    Score: 140.000000  Q:2 to 9  R:205 to 224 Align Len (7) (100.00%) (100.00%)

   Query:    3' ugugguguggguAGUGGGUa 5'
                            ||||||| 
   Ref:      5' ccatgggggagcTCACCCAc 3'

   Energy:  -12.410000 kCal/Mol

Scores for this hit:
>hsa-miR-4701-3p    01010101    140.00    -12.41    2 9    205 224    7    100.00%    100.00%

Score for this Scan:
Seq1,Seq2,Tot Score,Tot Energy,Max Score,Max Energy,Strand,Len1,Len2,Positions
>>hsa-miR-4701-3p    01010101    140.00    -12.41    140.00    -12.41    1524    20    582     205
Complete

A diferença é que em um não houve analise e em outro houve, o valor que esta em negrito é o que eu estou procurando.

Hybrid so tem o seguinte formato:

target: 01010101
length: 581
miRNA : hsa-miR-15a
length: 22

mfe: -24.4 kcal/mol
p-value: 0.334111

position  244
target 5' C    UCUCCUGUGGUCUCU     G           U 3'
           CACA               GACCA    GUGCUGUU    
           GUGU               UUGGU    CACGACGA    
miRNA  3'                          AAUA        U 5'

E o valor que me importa é o que esta em negrito.

From: bruno.buss em gmail.com
Date: Wed, 21 Nov 2012 14:21:18 -0200
To: rio-pm em pm.org
Subject: Re: [Rio-pm] Comparação de arquivos

breno++

2012/11/21 breno <breno em rio.pm.org>


Oi Aureliano,



acho que o que o Tiago quis dizer é "o que deveria estar acontecendo

mas não está, e o que está acontecendo em vez disso?"



Assumindo que não há problema na lógica e o que está tentando resolver

são os warnings que colou no final do paste, a resposta está na

recomendação número 5 abaixo.



Agora, algumas dicas gerais sobre o código que você colou:



1) a solução canônica para manipulação de listas são os módulos

List::Util, List::MoreUtils e List::AllUtils (que agrega as funções de

ambos). No List::MoreUtils (e, consequentemente, no List::AllUtils) há

a função uniq() que faz o mesmo que o Array::Uniq. Então, a menos que

você tenha um excelente motivo para usar o Array::Uniq, recomendo

trocar para o List::MoreUtils.





2) Evite open() com apenas dois argumentos. Evite open() com barewords

em vez de variáveis. Por mais que você saiba o que está fazendo,

procure sempre manter a sintaxe:



open my $fh, '<', $nome_do_arquivo

   or die "erro abrindo arquivo $nome_do_arquivo para leitura: $!";



para leitura, ou:



open my $fh, '>' $nome_do_arquivo

  or die "erro abrindo arquivo $nome_do_arquivo para escrita: $!";



Se quiser omitir o "or die..." basta colocar "use autodie;" no início

do seu programa.



Mais ainda, pode usar módulos como Path::Class que já manipulam o

arquivo para você:



  use Path::Class;



  my $fh = file( 'meuarquivo.txt' )->openr();  # ou openw() para escrever



Veja mais detalhes em https://metacpan.org/module/Path::Class::File





3) Ao colar um exemplo, certifique-se que ele está limpo. A linha 75,

por exemplo, tenta abrir um arquivo para escrita:



open SL, ">:raw", "sl.txt" or die $!;



mas não faz nada com ele.





4) Evite usar termos como new() e $self quando seu código não for

orientado a objetos. Essas não são palavras reservadas em Perl, mas

convenciona-se que new() constrói objetos e $self os referencia. Usar

esses nomes com outros objetivos confunde :)





5) Evite "ações à distância"

(https://en.wikipedia.org/wiki/Action_at_a_distance_%28computer_programming%29).

A variável especial $_, por exemplo, é global quando seu código espera

que ela seja local. Repare que você está consumindo seus dados usando

$_ implicitamente em 3 momentos distintos e concorrentes:



  foreach (@in) {    # $_ definido como o valor atual em @in



     print find_m($_), find_h($_);

  }



  sub find_m {

     my $self = shift;

     while (<INM2>) {  # $_ redefinido, agora para a linha atual

        ...

     }

     # ao final do bloco, $_ estará como undef (pois o arquivo acabou)

  }



idem para a sub find_h.



A solução? Bom, a partir do Perl 5.10 (lançado a quase 5 anos atrás) é

possível usar uma versão léxica do $_ ao declará-lo no bloco com 'my'.

É possível também restaurar o valor global de $_ no escopo atual

usando 'our $_', mas não é isso o que você quer. Para deixar seu

código claro e evitar efeitos colaterais, sugiro sempre "dar nomes aos

bois" e nomear suas variáveis de loop. Por exemplo, trocar:



   foreach (@in)



por



  foreach my $elemento (@in)



já teria resolvido seu problema (assumindo, claro, que agora você

estaria passando "$elemento" para as funções, em vez de "$_").

Recomendo mudar também no while() dentro das subs.



Outro problema de 'action at a distance' no seu código, menos grave

mas ainda assim importante, é que você está usando nas funções find_m

e find_h handles abertos em outro bloco, referenciados pela mesma

bareword. Fiquei sem entender se a sua lógica considera o consumo

linear do arquivo (para cada ocorrencia em @in, os arquivos hybrid.txt

e miranda.txt estarão mais próximos do final) ou se isso é um bug.





6) Não utilize 'our' quando não precisar - e você não precisa nesse

exemplo. Para saber mais sobre origem e diferenças entre my, our,

local e etc, recomendo a palestra do Util =>

http://youtu.be/Ton-5tvDQiE





7) Não utilize variáveis globais quando não precisar - e você não

precisa nesse exemplo.





8) Não agrupe elementos em expressões regulares se não for utilizar.

Nas regexes das subs parsin_m() e find_m() você tem dois grupos

(parenteses () dentro da regex) e só usa o $1.





9) Não manipule $/ diretamente. Se realmente precisar, faça "local $/

= ..." dentro do bloco.





10) Se as saídas de 'hybrid' e 'miranda' são sempre nesse formato,

crie um parser separadamente para elas e utilize em seu código. Deixa

tudo mais limpo e de quebra você ainda pode colocar no CPAN e ajudar

outras pessoas :)





11) No seu código você abre os arquivos 'hybrid.txt' e 'miranda.txt'

duas vezes para leitura. Isso normalmente significa que você poderia

ter colocado tudo numa estrutura de fácil acesso e manipulação, e lido

o arquivo apenas uma vez (operações de E/S costumam ser bem mais

pesadas do que manipulação em memória). Dica: sempre que tiver mais de

um while() ou foreach() varrendo a mesma estrutura para ler dados, é

bem possível que você possa otimizar e deixar mais claro seu algoritmo

fazendo a varredura apenas uma vez.





12) Sempre que o seu programa estiver fazendo algo estranho, tente

diminuir ao máximo a superfície de erro, e inspecionar o valor das

variáveis. No seu caso, por exemplo, o interpretador disse que o

problema estava quando a sua linha de print chamava as funções:



   print OUT ("#" x 20 , find_m($_) , "\n" , find_h($_) , "#" x 20 , "\n");



então o primeiro passo seria desmembrar, retirando tudo que é inútil (

'#' x 20 ) e colocando cada chamada em uma linha diferente, para

tentar isolar o erro. Outra, claro, é imprimir direto na tela em vez

de em arquivo:



   print find_m($_);

   print "\n";

   print find_h($_);



Se a sua variável for uma estrutura maior em vez de apenas uma string,

soluções como o Data::Printer podem te ajudar também.





Espero ter ajudado!



[]s



-b

_______________________________________________

Rio-pm mailing list

Rio-pm em pm.org

http://mail.pm.org/mailman/listinfo/rio-pm



-- 
Bruno C. Buss
http://www.brunobuss.net


_______________________________________________
Rio-pm mailing list
Rio-pm em pm.org
http://mail.pm.org/mailman/listinfo/rio-pm 		 	   		  
-------------- Próxima Parte ----------
Um anexo em HTML foi limpo...
URL: <http://mail.pm.org/pipermail/rio-pm/attachments/20121122/84fd077f/attachment-0001.html>


Mais detalhes sobre a lista de discussão Rio-pm