26 de noviembre de 2010

Interfaz SOAP de 3D-footprint

En las recientes Jornadas de Bioinformática 2010 (en Málaga) di una pequeña charla
sobre nuestra base de datos 3D-footprint, con el mismo título del artículo donde la publicamos en NAR "3D-footprint: a database for the structural analysis of protein-DNA complexes" (el  PDF del material presentado está disponible aquí, el vídeo  de la disección de interfaces proteína-DNA aquí).

Logo footprint de 2bam_AB

Tras la presentación me preguntaron si 3D-footprint tenía una interfaz de servicios web. La respuesta es afirmativa, en particular es una interfaz SOAP que se puede usar fácilmente desde Perl, como se muestra en el siguiente ejemplo:

 #!/usr/bin/perl -w  
   
 # prog 10 Bruno Contreras-Moreira  
 # web services client for 3D-footprint  
 # ejemplo basado en http://floresta.eead.csic.es/3dfootprint/tutorial.html#ws  
   
 use strict;  
 use SOAP::Lite;  
   
 my $URI  = 'http://floresta.eead.csic.es/footprint';  
 my $WSURL = 'http://floresta.eead.csic.es/3dpwm/scripts/server/ws.cgi';  
   
 my $soap = SOAP::Lite  
 -> uri($URI)  
 -> proxy($WSURL);  
   
 # 1) consulta de secuencia proteica (de un posible factor de transcripción)  
 my $secuencia =   
 "IYNLSRRFAQRGFSPREFRLTMTRGDIGNYLGLTVETISRLLGRFQKSGMLAVKGKYITIENNDALAQLAGHTRNVA";  
   
 my $result = $soap->protein_query($secuencia); # 1 param: 1(string) sequence  
   
 unless($result->fault){ print $result->result(); }   
 else{ print 'error: ' . join(', ',$result->faultcode,$result->faultstring); }  
   
 # los resultados muestran los posibles residuos de interfaz proteína-DNA  
 # en mayúsculas  
   
   
 # 2) consulta de motivo de DNA  
 my $motivo = 'tntga';  
 $result = $soap->motif_query($motivo,'local',1);   
 # 3 params: 1(string) motif in IUPAC|CONSENSUS|TRANSFAC format,   
 # 2(string) local|global,   
 # 3(float) evalue cutoff  
   
 unless($result->fault){ print $result->result(); }   
 else{ print 'error: ' . join(', ',$result->faultcode,$result->faultstring); }  
   
 # los resultados muestran complejos proteína-DNA cuyos motivos de DNA reconocidos  
 # se parecen a éste  

19 de noviembre de 2010

Escapar caracteres especiales en un texto antes de utilizar expresiones regulares

Hoy me he encontrado con un pequeño bug del script 'pfam_scan.pl' que sirve para buscar diferentes secuencias de proteínas en una base de datos de dominos de  Pfam (HMMs), todo ello usando la herramienta 'hmmscan' de HMMER3.

El error simplemente consistía en que una subrutina insertaba variables dentro de una expresión regular sin haber escapado los caracteres especiales previamente, con lo cual se insertaban directamente caracteres del tipo '(', '/', ... directamente dentro de la expresión regular y no funcionaba como era deseado.

Para evitarlo basta con escapar dichos caracteres especiales insertando el texto entre '\Q' y '\E' como bien nos ha sugerido Joaquín (más información en perlop):

 my $text_with_special_chars = 'abc$%()/def';  
 my $start_of_text_to_search = '$%';  
   
 $text_with_special_chars =~ /(\Q$start_of_text_to_search\E.+)/;  
   
 print $1; # $1 = '$%()/def'  

15 de noviembre de 2010

Mezclando datos en un solo archivo Excel

A menudo me ha tocado intercambiar datos con colegas en formato Excel y uno de los problemas que he padecido es el de tener que ir juntando a mano diferentes conjuntos de datos en diferentes hojas del mismo libro de cálculo. Una molestia añadida es la necesidad de importar archivos en formato texto, como columnas separadas por tabuladores, por ejemplo, en el mismo libro. Para automatizar este tipo de tareas y usar Excel/OpenOffice realmente sólo para el análisis de los datos, podemos echar mano por ejemplo del módulo Spreadsheet del CPAN. El mismo módulo puede servir además para leer y procesar datos directamente desde archivos Excel.

Volviendo al problema descrito arriba, supongamos por ejemplo que queremos unir en un sólo archivo excel tres archivos (datos1.xls, datos2.xls y datos3.tab) en uno solo que llamaremos todos_datos.xls . Pues bien, por medio del programa descrito debajo sería tan sencillo como ejecutar en el terminal:

 $ ./my_xls_merge.pl todos_datos.xls datos1.xls datos2.xls datos3.tab

Yo lo he probado en Linux y los archivos generados se leen perfectamente con el MS Excel, con la única pega de que se pierden las gráficas que hubiera ya en los archivos de entrada.

El código es el siguiente:

 #!/usr/bin/perl -w  
   
 # programa 9 my_xls_merge.pl   
 # programita para unir hojas de diferentes archivos .xls o .tab en un solo libro excel
 # OJO: conserva el valor de cada celda de una hoja de calculo, no las formulas,   
 # y se pierden los diagramas por ejemplo  
 # inspirado por http://www.perlmonks.org/?node_id=743574  
   
 use strict;  
 use Spreadsheet::ParseExcel;  
 use Spreadsheet::WriteExcel;   
 use File::Basename;  
   
 my $MAXLENGTHSHEETNAME = 31;  
   
 die "# usage: $0 <outfile.xls> <file1.xls> ... <fileN.xls>\n" if(scalar(@ARGV) < 2);  
   
 my @infiles = @ARGV;  
 my $outfile = shift(@infiles);  
   
 if(-e $outfile)  
 {  
    print "# a file named '$outfile' already exists, overwrite? (Y/N)\n";  
    my $overwrite = <STDIN>;  
    if($overwrite ne "Y\n"){ exit }  
    else{ unlink($outfile) }  
 }  
   
 # instantiate resulting excel object  
 my $outbook = Spreadsheet::WriteExcel->new($outfile) ||   
    die "# $0: cannot create '$outfile': $!";  
   
 for my $file (@infiles)   
 {  
    if(!-e $file)  
    {  
       print "# skipping non-existing file '$file'\n";  
       next;  
    }  
   
    # remove path   
    my ($filename,$copysheet_name) = (fileparse($file));   
      
    my $excel = Spreadsheet::ParseExcel::Workbook->Parse($file);  
    if(defined($excel->{'File'})) # excel format infiles  
    {  
       foreach my $sheet (@{$excel->{Worksheet}})   
       {   
          $copysheet_name = $sheet->{'Name'} . '-' . $filename;  
          if(length($copysheet_name) > $MAXLENGTHSHEETNAME)  
          {  
             print "# abbreviating $copysheet_name to ";  
             $copysheet_name = substr($copysheet_name,0,$MAXLENGTHSHEETNAME-3).'...';  
             print "$copysheet_name\n";  
          }  
         print "# adding '$file' sheet '$sheet->{'Name'}' ($copysheet_name)\n";  
   
        my $copysheet = $outbook->add_worksheet($copysheet_name);  
            
          $sheet->{'MaxRow'} ||= $sheet->{'MinRow'};  
          foreach my $row ($sheet->{'MinRow'} .. $sheet->{'MaxRow'})   
          {  
               my @rowdata = map { $sheet->{'Cells'}->[$row]->[$_]->{'Val'} }   
                      $sheet->{'MinCol'} .. $sheet->{'MaxCol'};  
          $copysheet->write($row,0,\@rowdata);   
          }  
       }  
    }  
    elsif($file =~ /\.tab/)# .tab infiles, seria trivial manejar .csv por ejemplo  
    {  
       $copysheet_name = $filename;  
       print "# adding '$file' no_sheet ($copysheet_name)\n";  
         
       my $copysheet = $outbook->add_worksheet($copysheet_name);  
         
       open(INTAB,$file) || die "# $0 : cannot read '$file': $!";  
       while(<INTAB>)  
       {  
          chomp($_);  
          my @tabdata = split(/\t/,$_);  
          $copysheet->write($.-1,0,\@tabdata);  
       }  
       close(INTAB);  
    }  
 }  
   
 $outbook->close();  
 print "# outfile: $outfile\n";   
   

Un saludo

9 de noviembre de 2010

Semana de la Ciencia 2010

Ayer comenzó la Semana de la Ciencia 2010, el mayor evento de comunicación social de la ciencia y la tecnología que se celebra en España, organizada por el Ministerio de Ciencia e Innovación.

Museos, Universidades, centros de investigación, parques tecnológicos o empresas organizan exposiciones, cursos, visitas, talleres, mesas redondas, excursiones o conferencias, acercando al público en general su quehacer diario, tanto sus aspectos más llamativos como los más desconocidos.

En concreto, la Agencia Estatal Consejo Superior de Investigaciones Científicas (CSIC) a la que pertenece nuestro centro de investigación, la Estación Experimental de Aula Dei (EEAD), organiza diversas actividades de divulgación en todo el país durante esta semana que se pueden consultar en su página web: http://www.semanadelaciencia.csic.es/

En concreto, en Aragón, una de las actividades más importantes se realiza en la Delegación del CSIC en Aragón del 2 al 10 de Noviembre.  Participan la Estación Experimental de Aula Dei, Instituto Pirenaico de Ecología, Instituto de Carboquímica, Instituto de Ciencias de Materiales de Aragón, y el Laboratorio de Investigación en Tecnologías de la Combustión. Cada participante dispone de un Stand con capacidad suficiente para preparación de experimentos atractivos, talleres didácticos, exposición de productos vistosos y utilización de demostradores para explicar conceptos de ciencia en los que se basan sus líneas de investigación.

8 de noviembre de 2010

Buscar un elemento en un array de perl

En Perl no tenemos la útil función "in_array()" que posee PHP, por lo cual cuando queremos saber si un array contiene un determinado elemento tenemos que escribir un poquito más de código.

Aunque buscando en google "perl array search element" obtenemos muchas soluciones a este problema, aquí presentaré 2 muy sencillas.

Para saber únicamente si un elemento está o no está en el array:

 # Search an element inside an array and return 1 or 0 if the element is present or not, example: in_array(\@my_array, $element);  
 sub in_array {  
      my ($array,$search_for) = @_;  
      my %items = map {$_ => 1} @$array; # create a hash out of the array values  
      my $exist = (exists($items{$search_for}))?1:0;  
      return $exist;
 }  

Si queremos además poder buscar expresiones regulares en todo el array y
conocer la o las posiciones de los resultados:

 # Search a regular expression inside an array and retrieve the positions of the hits, example: in_array(\@my_array, "/$expression/");  
 sub in_array {  
      my ($array,$search_for) = @_;  
      my @pos;  
      if ($search_for =~ /^\/.+\/$/){  
           $search_for =~ s/^\/|\/$//g;  
           @pos = grep { $_ =~ /$search_for/ } @{$array};  
      } else {  
           @pos = grep { $_ eq $search_for } @{$array};  
      }  
      (scalar @pos)?return (1,\@pos):return (0);  
 }  

Otra opción sería usar el módulo Tie::IxHash que permite crear hashes manteniendo el orden de los elementos y buscar los índices de los mismos:

 # Search a regular expression inside an array and retrieve the positions of the hits, example: in_array(\@my_array, "/$expression/");  
 sub in_array {  
      my ($array,$search_for) = @_;  
      my @pos;  
      if ($search_for =~ /^\/.+\/$/){  
           $search_for =~ s/^\/|\/$//g;  
           @pos = grep { $_ =~ /$search_for/ } @{$array};  
      } else {  
           @pos = grep { $_ eq $search_for } @{$array};  
      }  
      (scalar @pos)?return (1,\@pos):return (0);  
 }