Wednesday, June 6, 2012

Searching Pubmed Using Regular Expression Based Pattern Matching



This is a script that I wrote a number of years ago that provides a way of searching Pubmed abstracts using regular expression based pattern matching and, hence, it provides a way to pull out mutation data and other types of biomedical data that can be fit to a text pattern but not easily represented with keywords.  Publications describing some sample bioinformatics usages of the script for mining mutation data, gathering links to biomedical resources, and profiling developmental factors that play a role in the inner ear can be found in the links below.  I am reposting this code here because it seems the original host (bioinformatics.org) no longer makes a copy of the script available and I have recently received a number of requests for copies of the script. 

Sample Publications:


 
Code: 
 
#!/usr/bin/perl

# PREP (Perl RegExps for Pubmed) is a script that allows the use of 
# Perl regexs in the searching of Pubmed records, providing the ability to search 
# records for textual patterns as well as keywords

# Copyright 2005- Christopher M. Frenz
# This script is free sofware it may be used, copied, redistributed, and/or modified
# under the terms laid forth in the Perl Artisic License 

# Please cite this script in any publication in which literature cited within the
# publication was located using the PREP.pl script.  

# Usage: perl PREPv1-0.pl PubmedQueryTerms

# Usage of this script requires the LWP and XML::LibXML modules are installed
use LWP;
use XML::LibXML; #Version 1.58 used for development and testing

# Change the variable below to set the text pattern that Perl 
# will seek to match in the returned results
my $regex='[ARNDCEQGHILKMFPSTWYV]\d+[ARNDCEQGHILKMFPSTWYV]';

my $request;
my $response;
my $query;

# Concatenates arguments passed to script to form Pubmed query
$query=join(" ", @ARGV);

# Creates the URL to search Pubmed
my $baseurl="http://www.ncbi.nlm.nih.gov/entrez/eutils/esearch.fcgi?";
my $url=$baseurl . "db=Pubmed&retmax=1&usehistory=y&term=" . $query;


# Searches Pubmed and Returns the number of results
# as well as the session information needed for results retrieval
$request=LWP::UserAgent->new();
$response=$request->get($url);
my $results= $response->content;
die unless $response->is_success;
print "PubMed Search Results \n";
$results=~/<Count>(\d+)<\/Count>/;
   my $NumAbstracts=$1;
$results=~/<QueryKey>(\d+)<\/QueryKey>/;
   my $QueryKey=$1;
$results=~/<WebEnv>(.*?)<\/WebEnv>/;
   my $WebEnv=$1;
print "$NumAbstracts are Available \n";
print "Query Key= $QueryKey \n";
print "WebEnv= $WebEnv \n";

# Opens a file for output
open(OFile, ">PREPout.html");

my $parser=XML::LibXML->new;

my $retmax=500; #Number of records to be retrieved per request-Max 500
my $retstart=0; #Record number to start retreival from

# Creates the URL needed to retrieve results
$baseurl="http://www.ncbi.nlm.nih.gov/entrez/eutils/efetch.fcgi?";
my $url2="http://www.ncbi.nlm.nih.gov/entrez/query.fcgi?cmd=Retrieve&db=pubmed&dopt=Abstract&list_uids=";

my $Count=0;
# Retreives results in XML format
for($retstart=0;$retstart<=$NumAbstracts;$retstart+=$retmax){
   print "Processing record # $retstart \n";
   $url=$baseurl . "rettype=abstract&retmode=xml&retstart=$retstart&retmax=$retmax&db=Pubmed&query_key=$QueryKey&WebEnv=$WebEnv";

   $response=$request->get($url);
   $results=$response->content;
   die unless $response->is_success;

   # Uses a DOM based XML parser to process returned results
   my $domtree=$parser->parse_string($results);
   @Records=$domtree->getElementsByTagName("PubmedArticle"); 
   my $i=0;
   foreach(@Records){
# Extracts element data for regex processing and output formatting
      $titles=$Records[$i]->getElementsByTagName("ArticleTitle");
      $journals=$Records[$i]->getElementsByTagName("MedlineTA");
      $volumes=$Records[$i]->getElementsByTagName("Volume");
      $pgnums=$Records[$i]->getElementsByTagName("MedlinePgn");
      $abstracts=$Records[$i]->getElementsByTagName("AbstractText");
      $IDS=$Records[$i]->getElementsByTagName("PMID");


       # Processes title and abstract for pattern match and if a match occurs
       # data is written to output
       if($titles=~/($regex)/ or $abstracts=~/($regex)/){
           print OFile "<h1>Pattern Match: $1 </h1>\n";
           print OFile "<h3><a href=\"$url2$IDS\">$titles </a></h3> \n";
           print OFile "<p>$journals $volumes, $pgnums </p>\n";
           print OFile "<p>$abstracts </p>\n\n";
           $Count=$Count+1;
       }
       $i=$i+1;
   }
}
close OFile;
print "$Count records matched the pattern";

Tuesday, June 5, 2012

Improving the Image of Perl (Perl Marketing)


One of the comments to a posting I made about Scientific Computing in Perl raised the important question “If you'd like to have more people use Perl for scientific computation, it might be a good idea to think about and discuss what might have caused the shift of some people towards Python?”  I think this is a great question and I think it applies to more than just the scientific computing aspects of Perl, but Perl in general.  I think Perl has an image problem and because of this it is no longer trendy to use Perl.  If you talk to anyone that is not a Perl programmer about Perl, you tend to hear the same unfounded complaints over and over – e.g. Perl has a hard to understand and maintain syntax, OOP in Perl seems like an afterthought, etc.  Many such comments are unfounded or have long been addressed, but awareness of this does not seem to reach those that are not already working with Perl.  In many cases, I wouldn’t even be surprised if those making the complaints didn’t even have any true firsthand experience with Perl. 

While it is certainly possible to write some highly obfuscated Perl code, this is not the way it has to be.  A Perl programmer or corporation that employs them could easily make use of modules like Perl::Tidy and Perl::Critic to help maintain readability as well as having coding standards in place.  In fact many in the Perl community would actually strongly support such practices.   In terms of OOP support Perl now has Moose, which provides a more modern object system for Perl applications.  Perl has also produced a number of modern Web development frameworks, such as Dancer and Mojolicious.  Perl is even being used for “Big Data” analytics problems (http://blogs.perl.org/users/jt_smith/2012/05/perl-for-big-data.html).  Perl has been anything but a stagnant language and clearly still has a strong and innovative community supporting it.  One just has to look at a Perl news aggregation like the Perl Weekly, to see all of the interesting things members of the Perl community are working on and discussing. 



This therefore raises the question of how we can go about improving the marketing of Perl, to make the advancements and growing utility of Perl more widely known to those outside of the Perl community.  Here are some possibilities to consider:

1)     Writing articles, blog posts, comments, etc that highlight the utility of Perl and the recent advancements of Perl.  In particular I think articles in programming, Linux, and open source publications would be the most effective, since these are read by more than those with a vested interest in Perl. 
2)     When coming across an article or blog post that contains a discussion about something really interesting in Perl take the time to link to it, “Like” it, “+1” it, post to reddit, Hacker News, etc.  This could help to further generate a buzz about some of the interesting things the Perl community is working on. 
3)     Anybody remember Perlcast (http://perlcast.com/)?  It might be interesting to revive something like this as another way of spreading Perl news, particularly if it could be incorporated into one or more sites that promote a large number of technology podcasts like IT Conversations as this would get the podcasts in front of even more people.  It was a long time ago now, but if anyone is interested here is a link to my Perlcast interview - http://www.perlcast.com/audio/Perlcast_Interview_012_Frenz.mp3
 
4)     Many cities have Perl Mongers groups that give Perl related talks and tutorials.  Encourage those in your group to video such talks and post them online. 
5)     Highlight major projects, programs, and Websites that are built with Perl.  Slashdot, DuckDuckGo, Blekko, etc. 
6)     Perl outreach – volunteer to give a free lecture or class(es) on Perl at a local college, high school, library, etc.  The long-term future of Perl probably relies more on its popularity with and use by the next generation of programmers more so than it does with established players. 
7)     I’m sure there are plenty more, but these would provide a good starting point. 

Kobo has over 2 million ebooks to choose from!

Monday, June 4, 2012

Scientific Computing in Perl


I come from a scientific computing background (computational biology) and as such have often had to perform numerical computing tasks in numerous programming languages ranging from tried and true stalwarts like Fortran and C to languages like MATLAB.  A large amount of the scientific computing work I have done has also been done in Perl which has a long and rich history in the field of bioinformatics.  Recently, however, there seems to be a shift in the trend of people entering computational biology and bioinformatics to tend towards learning and using Python instead of Perl, citing the availability of libraries such as SciPy (for numerical computing) and interfaces such as RPy (for statistical computing with R).  This post is not meant to start a flame war with any fans of Python or Python’s scientific computing capabilities, as the Python community has done some great work in the area of scientific computing and has even produced some tools I have made extensive use of, such as Pymol (http://www.pymol.org/).  In fact I actually think competition is always a good thing.  Rather, I intend to use this post to raise some awareness of some of the Perl modules that can be of great benefit to anyone considering using Perl for scientific computing purposes. 

Perl Data Language (PDL) – allows Perl to manipulate large n-dimensional arrays (similar to MATLAB, NumPy, etc) in a quick and efficient manner.  The PDL namespace on CPAN contains many modules that should be of interest to scientific programmers including interfaces for numerical computing functions found in the GNU Scientific Library (http://www.gnu.org/software/gsl/).  More information on PDL can be found at http://pdl.perl.org/.

The Statistics namespace on CPAN – This namespace includes many Perl modules that allow the computation of numerous statistical analyses, ranging from basic descriptive statistics (Statistics::Descriptive) to more sophisticated analyses like multivariate regression (e.g.  Statistics::Regression).  There is even a module that allows your Perl code to interface with the statistical computing language R (Statistics::R). 

The Math namespace on CPAN – This namespace includes all kinds of advanced math functions that can be easily integrated into a Perl application.  While there are too many to mention in such a short synopsis, modules located here will provide support for dealing with areas of math such as trigonometry (Math::Trig) and complex numbers (Math::Complex) as well as provide access to algorithms for solving many types of math problems, such as solving for the roots of polynomial equations (Math::Polynomial::Solve). 

BioPerl – while not as generic to scientific computing as some of the ones mentioned above, BioPerl is a large and widely used collection of Perl modules for performing bioinformatics tasks.  More information on BioPerl can be found at http://www.bioperl.org/wiki/Main_Page. 

Perl’s Inline capability – the ability to integrate code from other languages into your Perl application (particularly inline C) can help to give your applications the flexibility and ease of use of Perl while allowing you to optimize certain parts of your application to improve performance.  

Of course there are many other modules as well that could be of great use for many scientific applications, as there are also modules that deal with data mining techniques, machine learning, and numerous other aspects of data analysis.  The intent, however, was to demonstrate that Perl does have a rich set of tools available to it for use in the development of scientific computing applications and that Perl should not be quickly dismissed in favor of Python.  I think for anyone entering the fields of computational biology or bioinformatics, Perl is still a language worth learning and still my preferred language for bioinformatics tasks.  Even if you decide in favor of Python for your new projects, you should be aware that many existing projects are written in Perl, and you may well have to maintain, modify, or interface with such codebases, where knowledge of Perl will only be to your advantage. 

Kobo has over 2 million ebooks to choose from!

Wednesday, May 30, 2012

Computing Descriptive Statistics with Perl


For anyone that does any type of data analysis work, the computing of basic descriptive statistics is often essential.  As with most things, Perl has a CPAN module available that actually makes the computation of basic statistical values quite straightforward.  In this short script we will take a look at the CPAN module Statistics::Descriptive (http://search.cpan.org/dist/Statistics-Descriptive/lib/Statistics/Descriptive.pm) and use it to perform some basic statistical analysis of a numeric data set.  The data set in the script will consist of 100 randomly generated integers in the range of 50 to 150.  The mean, median, mode, standard deviation, minimum, and maximum values of the data set will then be computed.  

 #!usr/bin/perl

# Copyright 2012- Christopher M. Frenz
# This script is free software - it may be used, copied, redistributed, and/or modified
# under the terms laid forth in the Perl Artistic License

use Statistics::Descriptive;
use strict;
use warnings;

#generate 100 random numbers between 50 and 150
my $range=101;
my $minimum=50;
my @randnums = map { int(rand($range)+$minimum) } ( 1..100 );

#prints the random numbers
#to prove the random number generation worked
foreach my $randnum (@randnums){
    print "$randnum\n";
}

#computes basic statistics on data
my $stat=Statistics::Descriptive::Full->new();
$stat->add_data(@randnums);
my $mean=$stat->mean();
print "The mean is: $mean\n";
my $median=$stat->median();
print "The median is: $median\n";
my $mode=$stat->mode();
print "The mode is: $mode\n";
my $sd=$stat->standard_deviation();
print "The standard deviation is: $sd\n";
my $min=$stat->min();
print "The minimum is: $min\n";
my $max=$stat->max();
print "The maximum is: $max\n";

Monday, May 28, 2012

Creative Commons Licensed Perl Tutorials


While this site is still relatively new and as a result still light on content, I intend to develop it into an increasingly useful resource for people to learn about various topics pertaining to software development, with a particular emphasis on Perl of course.  This idea is somewhat evident in some of the posts that I have already made available on the site, such as those pertaining to Input Validation and Escaping Data, which are topics that experienced programmers should already be familiar with in much more depth than my posts cover.  As time progresses, in addition to posting interesting Perl scripts, I intend to keep posting educational content as well.  To facilitate the educational value of this site all Perl code that I have authored and posted on the site is available under the Perl artistic license and all accompanying text that I have authored is made available under the Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License.  These terms will apply to all currently posted work as well as all future work posted to this site and means that anyone can feel free to use the content of this site, or derivatives of it, for any non-commercial purpose as long as they credit the source of the content (a link would be even better).  So for any professors or technical trainers out there, feel free to use any of the content you find beneficial to further the education of your students. 

Creative Commons License

Friday, May 25, 2012

Password Storage with Salted Hashes


Password storage is a hugely important issue for any application that makes use of passwords as an authentication mechanism.  One of the primary rules of password storage is that passwords should never be stored in plain text, but should instead be stored in a hashed form.  Hashes are one way cryptographic functions that provide a unique output for every input, and, as such, as long as the user always types in the correct password, the hash of the password should always result in the same value.  Any difference in the supplied password will result in a different hash value.  Thus as long as the hash of the typed in password matches the stored hash value, it can be concluded that the proper password was entered and the user can be given the appropriate access to the system.  The one way nature of hash functions works to improve security, because theoretically it should not be possible to determine the password value used to create the hash (e.g. without resorting to techniques like brute forcing, rainbow tables, etc). 

The security of stored passwords can be even further improved by using a strong hash function such as SHA-512 over older hash functions like MD-5 or SHA-1.  Moreover, salting hashes can provide a further means improving the security of stored passwords, as salts can work to nullify the usefulness of rainbow table based attacks.  A salt is a set of random bits that is also provided as input to the hash function.  Ideally each user of your application should have a unique salt applied to his password hash function.  In Perl, this is actually quite easy to achieve with the Crypt::Salted Hash module (http://search.cpan.org/~esskar/Crypt-SaltedHash-0.06/lib/Crypt/SaltedHash.pm).  Let’s consider the following snippet of Perl code which uses the module to create the salted SHA-512 hash of the supplied password.  

#!usr/bin/perl

use Crypt::SaltedHash;
use strict;
use warnings;

my $password='password';

#creating the salted hash
my $crypt=Crypt::SaltedHash->new(algorithm=>'SHA-512');
$crypt->add($password);
my $shash=$crypt->generate();
my $salt=$crypt->salt_hex();

print "Salted Hash= $shash\n";
print "Salt= $salt\n";

 
The module automatically generates a random salt value when it generates the hash, and this can be verified by running the same code multiple times and seeing the different salts and salted hash values generated. 

The same module can also be used to verify that the proper password was entered, by comparing the supplied password with the stored salted hash as seen below.  If the password is found to be the same as the one used to create the salted hash, the validate method will return a value of “1”.

#verifying the salted hash
my $crypt2=Crypt::SaltedHash->new(algorithm=>'SHA-512');
my $verified=$crypt2->validate($shash, $password);
if($verified==1){
    print "This is the correct password\n\n";
}
else{print "This is the wrong password\n\n";}
 
To show what would happen if an incorrect password was supplied, consider the following code snippet.  Note how the “This is the wrong password” message is printed.  

#showing what would happen if the password was wrong
$password='passw0rd';
my $verified=$crypt2->validate($shash, $password);
print "$verified\n";
if($verified==1){
    print "This is the correct password\n\n";
}
else{print "This is the wrong password\n\n";}

Kobo has over 2 million ebooks to choose from!

Wednesday, May 23, 2012

Copy Windows Event Logs into an SQLite Database


For anyone that has to administer, troubleshoot, or audit Windows systems, the records stored in the Windows Event Log can be a treasure trove of information.  The one potential problem is that there are often many thousands of entries in such logs which can often make finding information of interest a challenge.  The Perl script below makes use of the Win32::EventLog module as a means of offloading the records stored in the Event Log to an SQLite database, which can later be searched for pertinent information.  The script is as follows:

 #!usr/bin/perl

# Copyright 2012- Christopher M. Frenz
# This script is free software - it may be used, copied, redistributed, and/or modified
# under the terms laid forth in the Perl Artistic License
  
use DBI;
use Win32::EventLog; #v0.076 used for development
use strict;
use warnings;

my $server="\\\\192.168.1.2"; #put UNC name or IP address here

#creates/opens SQLite DB
my $dbh = DBI->connect("dbi:SQLite:dbname=EventLogData.sql","","");

#Removes Table Data if it already exists and creates new Table Data
$dbh->do("DROP TABLE Data");
$dbh->do( "CREATE TABLE Data (Record INTEGER PRIMARY KEY, EventLog,Server,Time,Source,Message,EventID);" );

my %type = (1 => "ERROR",
2 => "WARNING",
4 => "INFORMATION",
8 => "AUDIT_SUCCESS",
16 => "AUDIT_FAILURE");


$Win32::EventLog::GetMessageText = 1;
my $i=0;
#processes System, Appication, and Security Logs
#inserts each event log record into SQLite DB
for my $eventlog ("System", "Application", "Security") {
   my $handle = new Win32::EventLog($eventlog, $server)
   or die "Unable to open system log:$^En";
   $handle->GetNumber(my $recs)
        or die "Can't get number of EventLog records\n";
   $handle->GetOldest(my $base)
        or die "Can't get number of oldest EventLog record\n";
   my $j=0;
   while ($j < $recs) {
        $handle->Read(EVENTLOG_FORWARDS_READ|EVENTLOG_SEEK_READ,
                                  $base+$j,
                                  my $hashRef)
                or die "Can't read EventLog entry #$j\n";
                Win32::EventLog::GetMessageText($hashRef);
                my $time=scalar localtime($hashRef->{TimeGenerated});
                my $source=$type{$hashRef->{EventType}};
                my $message=$hashRef->{Message};
                my $eventID=($hashRef->{EventID}& 0xffff);
                my $sql= 'INSERT INTO Data(Record, EventLog,Server,Time,Source,Message,EventID) VALUES (?,?,?,?,?,?,?)';
                my $insert=$dbh->prepare($sql);
                $insert->execute($i,$eventlog, $server,$time,$source,$message,$eventID);
        $j++;
        $i++;

}}

$dbh->disconnect();

To examine the output of the script, I would recommend the SQLite Database Browser (http://sqlitebrowser.sourceforge.net/) which provides a nice GUI interface for visually inspecting the contents of a SQLite database.  A screenshot showing a sample database created by the script can be seen below: