# $Id: Utils.pm,v 1.2 2004/11/24 02:28:00 cmungall Exp $ # # This GO module is maintained by Chris Mungall # # see also - http://www.geneontology.org # - http://www.godatabase.org/dev # # You may distribute this module under the same terms as perl itself package GO::Utils; use Exporter; @ISA = qw(Exporter); @EXPORT_OK = qw(rearrange remove_duplicates merge_hashes get_method_ref get_param pset2hash dd spell_greek max check_obj_graph); use strict; use Carp; use Data::Dumper; =head2 rearrange() Usage : n/a Function : Rearranges named parameters to requested order. Returns : @params - an array of parameters in the requested order. Argument : $order : a reference to an array which describes the desired order of the named parameters. @param : an array of parameters, either as a list (in which case the function simply returns the list), or as an associative array (in which case the function sorts the values according to @{$order} and returns that new array. Exceptions : carps if a non-recognised parameter is sent =cut sub rearrange { # This function was taken from CGI.pm, written by Dr. Lincoln # Stein, and adapted for use in Bio::Seq by Richard Resnick. # ...then Chris Mungall came along and adapted it for BDGP my($order,@param) = @_; # If there are no parameters, we simply wish to return # an undef array which is the size of the @{$order} array. return (undef) x $#{$order} unless @param; # If we've got parameters, we need to check to see whether # they are named or simply listed. If they are listed, we # can just return them. return @param unless (defined($param[0]) && $param[0]=~/^-/); # Now we've got to do some work on the named parameters. # The next few lines strip out the '-' characters which # preceed the keys, and capitalizes them. my $i; for ($i=0;$i<@param;$i+=2) { if (!defined($param[$i])) { carp("Hmmm in $i ".join(";", @param)." == ".join(";",@$order)."\n"); } else { $param[$i]=~s/^\-//; $param[$i]=~tr/a-z/A-Z/; } } # Now we'll convert the @params variable into an associative array. my(%param) = @param; my(@return_array); # What we intend to do is loop through the @{$order} variable, # and for each value, we use that as a key into our associative # array, pushing the value at that key onto our return array. my($key); foreach $key (@{$order}) { $key=~tr/a-z/A-Z/; my($value) = $param{$key}; delete $param{$key}; push(@return_array,$value); } # catch user misspellings resulting in unrecognized names my(@restkeys) = keys %param; if (scalar(@restkeys) > 0) { carp("@restkeys not processed in rearrange(), did you use a non-recognized parameter name ? "); } return @return_array; } =head2 get_param() Usage : get_param('name',(-att1=>'ben',-name=>'the_name')) Function : Fetches a named parameter. Returns : The value of the requested parameter. Argument : $name : The name of the the parameter desired @param : an array of parameters, as an associative array Exceptions : carps if a non-recognised parameter is sent Based on rearrange(), which is originally from CGI.pm by Lincoln Stein and BioPerl by Richard Resnick. See rearrange() for details. =cut sub get_param { # This function was taken from CGI.pm, written by Dr. Lincoln # Stein, and adapted for use in Bio::Seq by Richard Resnick. # ...then Chris Mungall came along and adapted it for BDGP # ... and ben berman added his 2 cents. my($name,@param) = @_; # If there are no parameters, we simply wish to return # false. return '' unless @param; # If we've got parameters, we need to check to see whether # they are named or simply listed. If they are listed, we # can't return anything. return '' unless (defined($param[0]) && $param[0]=~/^-/); # Now we've got to do some work on the named parameters. # The next few lines strip out the '-' characters which # preceed the keys, and capitalizes them. my $i; for ($i=0;$i<@param;$i+=2) { $param[$i]=~s/^\-//; $param[$i] = uc($param[$i]); } # Now we'll convert the @params variable into an associative array. my(%param) = @param; # We capitalize the key, and use it as a key into our # associative array my $key = uc($name); my $val = $param{$key}; return $val; } =head2 remove_duplicates remove duplicate items from an array usage: remove_duplicates(\@arr) affects the array passed in, and returns the modified array =cut sub remove_duplicates { my $arr_r = shift; my @arr = @{$arr_r}; my %h = (); my $el; foreach $el (@arr) { $h{$el} = 1; } my @new_arr = (); foreach $el (keys %h) { push (@new_arr, $el); } @{$arr_r} = @new_arr; @new_arr; } =head1 merge_hashes joins two hashes together usage: merge_hashes(\%h1, \%h2); %h1 will now contain the key/val pairs of %h2 as well. if there are key conflicts, %h2 values will take precedence. =cut sub merge_hashes { my ($h1, $h2) = @_; map { $h1->{$_} = $h2->{$_}; } keys %{$h2}; return $h1; } =head1 get_method_ref returns a pointer to a particular objects method e.g. my $length_f = get_method_ref($seq, 'length'); $len = &$length_f(); =cut sub get_method_ref { my $self = shift; my $method = shift; return sub {return $self->$method(@_)}; } =head2 pset2hash Usage - my $h = pset2hash([{name=>"id", value=>"56"}, {name=>"name", value=>"jim"}]); Returns - hashref Args - arrayref of name/value keyed hashrefs =cut sub pset2hash { my $pset = shift; my $h = {}; # printf STDERR "REF=%s;\n", ref($pset); if (ref($pset) eq "ARRAY") { map {$h->{$_->{name}} = $_->{value}} @$pset; } elsif (ref($pset) eq "HASH") { $h = $pset; } else { $h = $pset; } return $h; } sub dd { my $obj = shift; my $d= Data::Dumper->new(['obj',$obj]); print $d->Dump; } =head2 spell_greek takes a word as a parameter and spells out any greek symbols encoded within (eg s/&agr;/alpha/g) =cut sub spell_greek { my $name = shift; $name =~ s/&agr\;/alpha/g; $name =~ s/&Agr\;/Alpha/g; $name =~ s/&bgr\;/beta/g; $name =~ s/&Bgr\;/Beta/g; $name =~ s/&ggr\;/gamma/g; $name =~ s/&Ggr\;/Gamma/g; $name =~ s/&dgr\;/delta/g; $name =~ s/&Dgr\;/Delta/g; $name =~ s/&egr\;/epsilon/g; $name =~ s/&Egr\;/Epsilon/g; $name =~ s/&zgr\;/zeta/g; $name =~ s/&Zgr\;/Zeta/g; $name =~ s/&eegr\;/eta/g; $name =~ s/&EEgr\;/Eta/g; $name =~ s/&thgr\;/theta/g; $name =~ s/&THgr\;/Theta/g; $name =~ s/&igr\;/iota/g; $name =~ s/&Igr\;/Iota/g; $name =~ s/&kgr\;/kappa/g; $name =~ s/&Kgr\;/Kappa/g; $name =~ s/&lgr\;/lambda/g; $name =~ s/&Lgr\;/Lambda/g; $name =~ s/&mgr\;/mu/g; $name =~ s/&Mgr\;/Mu/g; $name =~ s/&ngr\;/nu/g; $name =~ s/&Ngr\;/Nu/g; $name =~ s/&xgr\;/xi/g; $name =~ s/&Xgr\;/Xi/g; $name =~ s/&ogr\;/omicron/g; $name =~ s/&Ogr\;/Omicron/g; $name =~ s/&pgr\;/pi/g; $name =~ s/&Pgr\;/Pi/g; $name =~ s/&rgr\;/rho/g; $name =~ s/&Rgr\;/Rho/g; $name =~ s/&sgr\;/sigma/g; $name =~ s/&Sgr\;/Sigma/g; $name =~ s/&tgr\;/tau/g; $name =~ s/&Tgr\;/Tau/g; $name =~ s/&ugr\;/upsilon/g; $name =~ s/&Ugr\;/Upsilon/g; $name =~ s/&phgr\;/phi/g; $name =~ s/&PHgr\;/Phi/g; $name =~ s/&khgr\;/chi/g; $name =~ s/&KHgr\;/Chi/g; $name =~ s/&psgr\;/psi/g; $name =~ s/&PSgr\;/Psi/g; $name =~ s/&ohgr\;/omega/g; $name =~ s/&OHgr\;/Omega/g; $name =~ s//\[/g; $name =~ s/<\/up>/\]/g; $name =~ s//\[\[/g; $name =~ s/<\/down>/\]\]/g; return $name; } =head2 check_obj_graph Usage - Returns - true if cycle detected Args - any object =cut sub check_obj_graph { my $object = shift; my $h = {}; my $cnt = 1; my @nodes = ({obj=>$object,path=>[]}); my @path = (); my $cycle = 0; while (!$cycle && @nodes) { my $node = shift @nodes; my $obj = $node->{obj}; my $id = sprintf("%s", $node->{obj}); if (ref($obj) && $id !~ /GLOB/) { if (!$h->{$id}) { $h->{$id} = $cnt; $cnt++; } # check for cycles if (grep {my $idelt = sprintf("%s", $_); $idelt eq $id} @{$node->{path}}) { $cycle = $node; } printf "* OB:%5s %20s [%s]\n", $h->{$id}, $obj, join(", ", map {$h->{$_}} @{$node->{path}}); my @newobjs = (); if (ref($obj) eq "ARRAY") { @newobjs = @$obj; } ## if (ref($obj) eq "HASH") { elsif (ref($obj) eq "GLOB") { } else { @newobjs = values %$obj; } map { my @newpath = (@{$node->{path}}, $obj); my $newnode = {obj=>$_, path=>\@newpath}; push(@nodes, $newnode); } @newobjs; } } return $cycle; } sub max { my @items = @_; my $max; my $item; foreach $item (@items) { if (!defined($max)) { $max = $item; } else { $max = $item if ($item > $max); } } return $max; } 1;