[Bio] / Sprout / Sprout.pm Repository:
ViewVC logotype

Diff of /Sprout/Sprout.pm

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 1.82, Sat Sep 2 07:00:54 2006 UTC revision 1.97, Sun Feb 4 13:09:10 2007 UTC
# Line 131  Line 131 
131      # Add the option table and XML file name.      # Add the option table and XML file name.
132      $retVal->{_options} = $optionTable;      $retVal->{_options} = $optionTable;
133      $retVal->{_xmlName} = $xmlFileName;      $retVal->{_xmlName} = $xmlFileName;
134        # Set up space for the group file data.
135        $retVal->{groupHash} = undef;
136      # Return it.      # Return it.
137      return $retVal;      return $retVal;
138  }  }
# Line 340  Line 342 
342    
343  =head3 GeneMenu  =head3 GeneMenu
344    
345  C<< my $selectHtml = $sprout->GeneMenu(\%attributes, $filterString, \@params); >>  C<< my $selectHtml = $sprout->GeneMenu(\%attributes, $filterString, \@params, $selected); >>
346    
347  Return an HTML select menu of genomes. Each genome will be an option in the menu,  Return an HTML select menu of genomes. Each genome will be an option in the menu,
348  and will be displayed by name with the ID and a contig count attached. The selection  and will be displayed by name with the ID and a contig count attached. The selection
# Line 362  Line 364 
364  Reference to a list of values to be substituted in for the parameter marks in  Reference to a list of values to be substituted in for the parameter marks in
365  the filter string.  the filter string.
366    
367    =item selected (optional)
368    
369    ID of the genome to be initially selected.
370    
371    =item fast (optional)
372    
373    If specified and TRUE, the contig counts will be omitted to improve performance.
374    
375  =item RETURN  =item RETURN
376    
377  Returns an HTML select menu with the specified genomes as selectable options.  Returns an HTML select menu with the specified genomes as selectable options.
# Line 372  Line 382 
382    
383  sub GeneMenu {  sub GeneMenu {
384      # Get the parameters.      # Get the parameters.
385      my ($self, $attributes, $filterString, $params) = @_;      my ($self, $attributes, $filterString, $params, $selected, $fast) = @_;
386        my $slowMode = ! $fast;
387        # Default to nothing selected. This prevents an execution warning if "$selected"
388        # is undefined.
389        $selected = "" unless defined $selected;
390        Trace("Gene Menu called with slow mode \"$slowMode\" and selection \"$selected\".") if T(3);
391      # Start the menu.      # Start the menu.
392      my $retVal = "<select " .      my $retVal = "<select " .
393          join(" ", map { "$_=\"$attributes->{$_}\"" } keys %{$attributes}) .          join(" ", map { "$_=\"$attributes->{$_}\"" } keys %{$attributes}) .
# Line 389  Line 404 
404          # Get the data for this genome.          # Get the data for this genome.
405          my ($genomeID, $genus, $species, $strain) = @{$genomeData};          my ($genomeID, $genus, $species, $strain) = @{$genomeData};
406          # Get the contig count.          # Get the contig count.
407            my $contigInfo = "";
408            if ($slowMode) {
409          my $count = $self->ContigCount($genomeID);          my $count = $self->ContigCount($genomeID);
410          my $counting = ($count == 1 ? "contig" : "contigs");          my $counting = ($count == 1 ? "contig" : "contigs");
411                $contigInfo = "[$count $counting]";
412            }
413            # Find out if we're selected.
414            my $selectOption = ($selected eq $genomeID ? " selected" : "");
415          # Build the option tag.          # Build the option tag.
416          $retVal .= "<option value=\"$genomeID\">$genus $species $strain ($genomeID) [$count $counting]</option>\n";          $retVal .= "<option value=\"$genomeID\"$selectOption>$genus $species $strain ($genomeID)$contigInfo</option>\n";
         Trace("Option tag built for $genomeID: $genus $species $strain.") if T(3);  
417      }      }
418      # Close the SELECT tag.      # Close the SELECT tag.
419      $retVal .= "</select>\n";      $retVal .= "</select>\n";
420      # Return the result.      # Return the result.
421      return $retVal;      return $retVal;
422  }  }
423    
424  =head3 Build  =head3 Build
425    
426  C<< $sprout->Build(); >>  C<< $sprout->Build(); >>
# Line 634  Line 655 
655      return ($contigID, $start, $dir, $len);      return ($contigID, $start, $dir, $len);
656  }  }
657    
658    
659    
660  =head3 PointLocation  =head3 PointLocation
661    
662  C<< my $found = Sprout::PointLocation($location, $point); >>  C<< my $found = Sprout::PointLocation($location, $point); >>
# Line 898  Line 921 
921      my ($self, $genomeID) = @_;      my ($self, $genomeID) = @_;
922      # Declare the return variable.      # Declare the return variable.
923      my $retVal = {};      my $retVal = {};
924      # Query the genome's features and annotations. We'll put the oldest annotations      # Query the genome's features.
925      # first so that the last assignment to go into the hash will be the correct one.      my $query = $self->Get(['HasFeature', 'Feature'], "HasFeature(from-link) = ?",
     my $query = $self->Get(['HasFeature', 'IsTargetOfAnnotation', 'Annotation'],  
                            "HasFeature(from-link) = ? ORDER BY Annotation(time)",  
926                             [$genomeID]);                             [$genomeID]);
927      # Loop through the annotations.      # Loop through the features.
928      while (my $data = $query->Fetch) {      while (my $data = $query->Fetch) {
929          # Get the feature ID and annotation text.          # Get the feature ID and assignment.
930          my ($fid, $annotation) = $data->Values(['HasFeature(to-link)',          my ($fid, $assignment) = $data->Values(['Feature(id)', 'Feature(assignment)']);
931                                                  'Annotation(annotation)']);          if ($assignment) {
         # Check to see if this is an assignment. Note that the user really  
         # doesn't matter to us, other than we use it to determine whether or  
         # not this is an assignment.  
         my ($user, $assignment) = _ParseAssignment('fig', $annotation);  
         if ($user) {  
             # Here it's an assignment. We put it in the return hash, overwriting  
             # any older assignment that might be present.  
932              $retVal->{$fid} = $assignment;              $retVal->{$fid} = $assignment;
933          }          }
934      }      }
# Line 1276  Line 1290 
1290  Return the most recently-determined functional assignment of a particular feature.  Return the most recently-determined functional assignment of a particular feature.
1291    
1292  The functional assignment is handled differently depending on the type of feature. If  The functional assignment is handled differently depending on the type of feature. If
1293  the feature is identified by a FIG ID (begins with the string C<fig|>), then a functional  the feature is identified by a FIG ID (begins with the string C<fig|>), then the functional
1294  assignment is a type of annotation. The format of an assignment is described in  assignment is taken from the B<Feature> or C<Annotation> table, depending.
 L</ParseAssignment>. Its worth noting that we cannot filter on the content of the  
 annotation itself because it's a text field; however, this is not a big problem because  
 most features only have a small number of annotations.  
1295    
1296  Each user has an associated list of trusted users. The assignment returned will be the most  Each user has an associated list of trusted users. The assignment returned will be the most
1297  recent one by at least one of the trusted users. If no trusted user list is available, then  recent one by at least one of the trusted users. If no trusted user list is available, then
# Line 1299  Line 1310 
1310    
1311  =item userID (optional)  =item userID (optional)
1312    
1313  ID of the user whose function determination is desired. If omitted, only the latest  ID of the user whose function determination is desired. If omitted, the primary
1314  C<FIG> assignment will be returned.  functional assignment in the B<Feature> table will be returned.
1315    
1316  =item RETURN  =item RETURN
1317    
# Line 1317  Line 1328 
1328      my $retVal;      my $retVal;
1329      # Determine the ID type.      # Determine the ID type.
1330      if ($featureID =~ m/^fig\|/) {      if ($featureID =~ m/^fig\|/) {
1331          # Here we have a FIG feature ID. We must build the list of trusted          # Here we have a FIG feature ID.
1332          # users.          if (!$userID) {
1333                # Use the primary assignment.
1334                ($retVal) = $self->GetEntityValues('Feature', $featureID, ['Feature(assignment)']);
1335            } else {
1336                # We must build the list of trusted users.
1337          my %trusteeTable = ();          my %trusteeTable = ();
1338          # Check the user ID.          # Check the user ID.
1339          if (!$userID) {          if (!$userID) {
# Line 1361  Line 1376 
1376                  }                  }
1377              }              }
1378          }          }
1379            }
1380      } else {      } else {
1381          # Here we have a non-FIG feature ID. In this case the user ID does not          # Here we have a non-FIG feature ID. In this case the user ID does not
1382          # matter. We simply get the information from the External Alias Function          # matter. We simply get the information from the External Alias Function
# Line 1476  Line 1492 
1492      my %retVal = ();      my %retVal = ();
1493      # Loop through the incoming features.      # Loop through the incoming features.
1494      for my $featureID (@{$featureList}) {      for my $featureID (@{$featureList}) {
1495          # Create a query to get the feature's best hit.          # Ask the server for the feature's best hit.
1496          my $query = $self->Get(['IsBidirectionalBestHitOf'],          my @bbhData = FIGRules::BBHData($featureID);
                                "IsBidirectionalBestHitOf(from-link) = ? AND IsBidirectionalBestHitOf(genome) = ?",  
                                [$featureID, $genomeID]);  
1497          # Peel off the BBHs found.          # Peel off the BBHs found.
1498          my @found = ();          my @found = ();
1499          while (my $bbh = $query->Fetch) {          for my $bbh (@bbhData) {
1500              push @found, $bbh->Value('IsBidirectionalBestHitOf(to-link)');              my $fid = $bbh->[0];
1501                my $bbGenome = $self->GenomeOf($fid);
1502                if ($bbGenome eq $genomeID) {
1503                    push @found, $fid;
1504                }
1505          }          }
1506          $retVal{$featureID} = \@found;          $retVal{$featureID} = \@found;
1507      }      }
# Line 1497  Line 1515 
1515    
1516  Return a list of the similarities to the specified feature.  Return a list of the similarities to the specified feature.
1517    
1518  Sprout does not support real similarities, so this method just returns the bidirectional  This method just returns the bidirectional best hits for performance reasons.
 best hits.  
1519    
1520  =over 4  =over 4
1521    
# Line 1518  Line 1535 
1535      # Get the parameters.      # Get the parameters.
1536      my ($self, $featureID, $count) = @_;      my ($self, $featureID, $count) = @_;
1537      # Ask for the best hits.      # Ask for the best hits.
1538      my @lists = $self->GetAll(['IsBidirectionalBestHitOf'],      my @lists = FIGRules::BBHData($featureID);
                               "IsBidirectionalBestHitOf(from-link) = ? ORDER BY IsBidirectionalBestHitOf(score) DESC",  
                               [$featureID], ['IsBidirectionalBestHitOf(to-link)', 'IsBidirectionalBestHitOf(score)'],  
                               $count);  
1539      # Create the return value.      # Create the return value.
1540      my %retVal = ();      my %retVal = ();
1541      for my $tuple (@lists) {      for my $tuple (@lists) {
# Line 1531  Line 1545 
1545      return %retVal;      return %retVal;
1546  }  }
1547    
   
   
1548  =head3 IsComplete  =head3 IsComplete
1549    
1550  C<< my $flag = $sprout->IsComplete($genomeID); >>  C<< my $flag = $sprout->IsComplete($genomeID); >>
# Line 2664  Line 2676 
2676      return $retVal;      return $retVal;
2677  }  }
2678    
2679    =head3 PropertyID
2680    
2681    C<< my $id = $sprout->PropertyID($propName, $propValue); >>
2682    
2683    Return the ID of the specified property name and value pair, if the
2684    pair exists.
2685    
2686    =over 4
2687    
2688    =item propName
2689    
2690    Name of the desired property.
2691    
2692    =item propValue
2693    
2694    Value expected for the desired property.
2695    
2696    =item RETURN
2697    
2698    Returns the ID of the name/value pair, or C<undef> if the pair does not exist.
2699    
2700    =back
2701    
2702    =cut
2703    
2704    sub PropertyID {
2705        # Get the parameters.
2706        my ($self, $propName, $propValue) = @_;
2707        # Try to find the ID.
2708        my ($retVal) = $self->GetFlat(['Property'],
2709                                      "Property(property-name) = ? AND Property(property-value) = ?",
2710                                      [$propName, $propValue], 'Property(id)');
2711        # Return the result.
2712        return $retVal;
2713    }
2714    
2715  =head3 MergedAnnotations  =head3 MergedAnnotations
2716    
2717  C<< my @annotationList = $sprout->MergedAnnotations(\@list); >>  C<< my @annotationList = $sprout->MergedAnnotations(\@list); >>
# Line 2861  Line 2909 
2909      # Get the parameters.      # Get the parameters.
2910      my ($self, $featureID) = @_;      my ($self, $featureID) = @_;
2911      # Get the list of names.      # Get the list of names.
2912      my @retVal = $self->GetFlat(['ContainsFeature', 'HasSSCell'], "ContainsFeature(to-link) = ?",      my @retVal = $self->GetFlat(['HasRoleInSubsystem'], "HasRoleInSubsystem(from-link) = ?",
2913                                  [$featureID], 'HasSSCell(from-link)');                                  [$featureID], 'HasRoleInSubsystem(to-link)');
2914      # Return the result.      # Return the result, sorted.
2915      return @retVal;      return sort @retVal;
2916  }  }
2917    
2918  =head3 GenomeSubsystemData  =head3 GenomeSubsystemData
# Line 2962  Line 3010 
3010      # Get the parameters.      # Get the parameters.
3011      my ($self, $featureID, $function, $userID) = @_;      my ($self, $featureID, $function, $userID) = @_;
3012      # Get a list of the features that are BBHs of the incoming feature.      # Get a list of the features that are BBHs of the incoming feature.
3013      my @bbhFeatures = $self->GetFlat(['IsBidirectionalBestHitOf'],      my @bbhFeatures = map { $_->[0] } FIGRules::BBHData($featureID);
                                      "IsBidirectionalBestHitOf(from-link) = ?", [$featureID],  
                                      'IsBidirectionalBestHitOf(to-link)');  
3014      # Now we loop through the features, pulling out the ones that have the correct      # Now we loop through the features, pulling out the ones that have the correct
3015      # functional assignment.      # functional assignment.
3016      my @retVal = ();      my @retVal = ();
# Line 3100  Line 3146 
3146      # Loop through the input triples.      # Loop through the input triples.
3147      my $n = length $sequence;      my $n = length $sequence;
3148      for (my $i = 0; $i < $n; $i += 3) {      for (my $i = 0; $i < $n; $i += 3) {
3149          # Get the current triple from the sequence.          # Get the current triple from the sequence. Note we convert to
3150          my $triple = substr($sequence, $i, 3);          # upper case to insure a match.
3151            my $triple = uc substr($sequence, $i, 3);
3152          # Translate it using the table.          # Translate it using the table.
3153          my $protein = "X";          my $protein = "X";
3154          if (exists $table->{$triple}) { $protein = $table->{$triple}; }          if (exists $table->{$triple}) { $protein = $table->{$triple}; }
# Line 3134  Line 3181 
3181      return @retVal;      return @retVal;
3182  }  }
3183    
3184    =head3 BBHMatrix
3185    
3186    C<< my %bbhMap = $sprout->BBHMatrix($genomeID, $cutoff, @targets); >>
3187    
3188    Find all the bidirectional best hits for the features of a genome in a
3189    specified list of target genomes. The return value will be a hash mapping
3190    features in the original genome to their bidirectional best hits in the
3191    target genomes.
3192    
3193    =over 4
3194    
3195    =item genomeID
3196    
3197    ID of the genome whose features are to be examined for bidirectional best hits.
3198    
3199    =item cutoff
3200    
3201    A cutoff value. Only hits with a score lower than the cutoff will be returned.
3202    
3203    =item targets
3204    
3205    List of target genomes. Only pairs originating in the original
3206    genome and landing in one of the target genomes will be returned.
3207    
3208    =item RETURN
3209    
3210    Returns a hash mapping each feature in the original genome to a hash mapping its
3211    BBH pegs in the target genomes to their scores.
3212    
3213    =back
3214    
3215    =cut
3216    
3217    sub BBHMatrix {
3218        # Get the parameters.
3219        my ($self, $genomeID, $cutoff, @targets) = @_;
3220        # Declare the return variable.
3221        my %retVal = ();
3222        # Ask for the BBHs.
3223        my @bbhList = FIGRules::BatchBBHs("fig|$genomeID.%", $cutoff, @targets);
3224        # We now have a set of 4-tuples that we need to convert into a hash of hashes.
3225        for my $bbhData (@bbhList) {
3226            my ($peg1, $peg2, $score) = @{$bbhData};
3227            if (! exists $retVal{$peg1}) {
3228                $retVal{$peg1} = { $peg2 => $score };
3229            } else {
3230                $retVal{$peg1}->{$peg2} = $score;
3231            }
3232        }
3233        # Return the result.
3234        return %retVal;
3235    }
3236    
3237  =head3 LowBBHs  =head3 LowBBHs
3238    
3239  C<< my %bbhMap = $sprout->LowBBHs($featureID, $cutoff); >>  C<< my %bbhMap = $sprout->LowBBHs($featureID, $cutoff); >>
# Line 3165  Line 3265 
3265      my ($self, $featureID, $cutoff) = @_;      my ($self, $featureID, $cutoff) = @_;
3266      # Create the return hash.      # Create the return hash.
3267      my %retVal = ();      my %retVal = ();
3268      # Create a query to get the desired BBHs.      # Query for the desired BBHs.
3269      my @bbhList = $self->GetAll(['IsBidirectionalBestHitOf'],      my @bbhList = FIGRules::BBHData($featureID, $cutoff);
                                 'IsBidirectionalBestHitOf(sc) <= ? AND IsBidirectionalBestHitOf(from-link) = ?',  
                                 [$cutoff, $featureID],  
                                 ['IsBidirectionalBestHitOf(to-link)', 'IsBidirectionalBestHitOf(sc)']);  
3270      # Form the results into the return hash.      # Form the results into the return hash.
3271      for my $pair (@bbhList) {      for my $pair (@bbhList) {
3272          $retVal{$pair->[0]} = $pair->[1];          my $fid = $pair->[0];
3273            if ($self->Exists('Feature', $fid)) {
3274                $retVal{$fid} = $pair->[1];
3275            }
3276      }      }
3277      # Return the result.      # Return the result.
3278      return %retVal;      return %retVal;
# Line 3243  Line 3343 
3343      return $retVal;      return $retVal;
3344  }  }
3345    
3346    =head3 IsAllGenomes
3347    
3348    C<< my $flag = $sprout->IsAllGenomes(\@list, \@checkList); >>
3349    
3350    Return TRUE if all genomes in the second list are represented in the first list at
3351    least one. Otherwise, return FALSE. If the second list is omitted, the first list is
3352    compared to a list of all the genomes.
3353    
3354    =over 4
3355    
3356    =item list
3357    
3358    Reference to the list to be compared to the second list.
3359    
3360    =item checkList (optional)
3361    
3362    Reference to the comparison target list. Every genome ID in this list must occur at
3363    least once in the first list. If this parameter is omitted, a list of all the genomes
3364    is used.
3365    
3366    =item RETURN
3367    
3368    Returns TRUE if every item in the second list appears at least once in the
3369    first list, else FALSE.
3370    
3371    =back
3372    
3373    =cut
3374    
3375    sub IsAllGenomes {
3376        # Get the parameters.
3377        my ($self, $list, $checkList) = @_;
3378        # Supply the checklist if it was omitted.
3379        $checkList = [$self->Genomes()] if ! defined($checkList);
3380        # Create a hash of the original list.
3381        my %testList = map { $_ => 1 } @{$list};
3382        # Declare the return variable. We assume that the representation
3383        # is complete and stop at the first failure.
3384        my $retVal = 1;
3385        my $n = scalar @{$checkList};
3386        for (my $i = 0; $retVal && $i < $n; $i++) {
3387            if (! $testList{$checkList->[$i]}) {
3388                $retVal = 0;
3389            }
3390        }
3391        # Return the result.
3392        return $retVal;
3393    }
3394    
3395  =head3 GetGroups  =head3 GetGroups
3396    
3397  C<< my %groups = $sprout->GetGroups(\@groupList); >>  C<< my %groups = $sprout->GetGroups(\@groupList); >>
# Line 3264  Line 3413 
3413          # Here we have a group list. Loop through them individually,          # Here we have a group list. Loop through them individually,
3414          # getting a list of the relevant genomes.          # getting a list of the relevant genomes.
3415          for my $group (@{$groupList}) {          for my $group (@{$groupList}) {
3416              my @genomeIDs = $self->GetFlat(['Genome'], "Genome(group-name) = ?",              my @genomeIDs = $self->GetFlat(['Genome'], "Genome(primary-group) = ?",
3417                  [$group], "Genome(id)");                  [$group], "Genome(id)");
3418              $retVal{$group} = \@genomeIDs;              $retVal{$group} = \@genomeIDs;
3419          }          }
# Line 3272  Line 3421 
3421          # Here we need all of the groups. In this case, we run through all          # Here we need all of the groups. In this case, we run through all
3422          # of the genome records, putting each one found into the appropriate          # of the genome records, putting each one found into the appropriate
3423          # group. Note that we use a filter clause to insure that only genomes          # group. Note that we use a filter clause to insure that only genomes
3424          # in groups are included in the return set.          # in real NMPDR groups are included in the return set.
3425          my @genomes = $self->GetAll(['Genome'], "Genome(group-name) > ' '", [],          my @genomes = $self->GetAll(['Genome'], "Genome(primary-group) <> ?",
3426                                      ['Genome(id)', 'Genome(group-name)']);                                      [$FIG_Config::otherGroup], ['Genome(id)', 'Genome(primary-group)']);
3427          # Loop through the genomes found.          # Loop through the genomes found.
3428          for my $genome (@genomes) {          for my $genome (@genomes) {
3429              # Pop this genome's ID off the current list.              # Pop this genome's ID off the current list.
# Line 3392  Line 3541 
3541      # Get the parameters.      # Get the parameters.
3542      my ($self, $genomeID, $testFlag) = @_;      my ($self, $genomeID, $testFlag) = @_;
3543      # Perform the delete for the genome's features.      # Perform the delete for the genome's features.
3544      my $retVal = $self->Delete('Feature', "fig|$genomeID.%", $testFlag);      my $retVal = $self->Delete('Feature', "fig|$genomeID.%", testMode => $testFlag);
3545      # Perform the delete for the primary genome data.      # Perform the delete for the primary genome data.
3546      my $stats = $self->Delete('Genome', $genomeID, $testFlag);      my $stats = $self->Delete('Genome', $genomeID, testMode => $testFlag);
3547      $retVal->Accumulate($stats);      $retVal->Accumulate($stats);
3548      # Return the result.      # Return the result.
3549      return $retVal;      return $retVal;
# Line 3442  Line 3591 
3591      return %retVal;      return %retVal;
3592  }  }
3593    
3594  =head2 Internal Utility Methods  =head3 GroupPageName
3595    
3596  =head3 ParseAssignment  C<< my $name = $sprout->GroupPageName($group); >>
3597    
3598  Parse annotation text to determine whether or not it is a functional assignment. If it is,  Return the name of the page for the specified NMPDR group.
 the user, function text, and assigning user will be returned as a 3-element list. If it  
 isn't, an empty list will be returned.  
   
 A functional assignment is always of the form  
   
     C<set >I<YYYY>C< function to\n>I<ZZZZZ>  
   
 where I<YYYY> is the B<user>, and I<ZZZZ> is the actual functional role. In most cases,  
 the user and the assigning user (from MadeAnnotation) will be the same, but that is  
 not always the case.  
   
 In addition, the functional role may contain extra data that is stripped, such as  
 terminating spaces or a comment separated from the rest of the text by a tab.  
   
 This is a static method.  
3599    
3600  =over 4  =over 4
3601    
3602  =item user  =item group
   
 Name of the assigning user.  
   
 =item text  
3603    
3604  Text of the annotation.  Name of the relevant group.
3605    
3606  =item RETURN  =item RETURN
3607    
3608  Returns an empty list if the annotation is not a functional assignment; otherwise, returns  Returns the relative page name (e.g. C<../content/campy.php>). If the group file is not in
3609  a two-element list containing the user name and the function text.  memory it will be read in.
3610    
3611  =back  =back
3612    
3613  =cut  =cut
3614    
3615  sub _ParseAssignment {  sub GroupPageName {
3616      # Get the parameters.      # Get the parameters.
3617      my ($user, $text) = @_;      my ($self, $group) = @_;
3618      # Declare the return value.      # Declare the return variable.
3619      my @retVal = ();      my $retVal;
3620      # Check to see if this is a functional assignment.      # Check for the group file data.
3621      my ($type, $function) = split(/\n/, $text);      if (! defined $self->{groupHash}) {
3622      if ($type =~ m/^set function to$/i) {          # Read the group file.
3623          # Here we have an assignment without a user, so we use the incoming user ID.          my %groupData = Sprout::ReadGroupFile($self->{_options}->{dataDir} . "/groups.tbl");
3624          @retVal = ($user, $function);          # Store it in our object.
3625      } elsif ($type =~ m/^set (\S+) function to$/i) {          $self->{groupHash} = \%groupData;
         # Here we have an assignment with a user that is passed back to the caller.  
         @retVal = ($1, $function);  
3626      }      }
3627      # If we have an assignment, we need to clean the function text. There may be      # Compute the real group name.
3628      # extra junk at the end added as a note from the user.      my $realGroup = $group;
3629      if (defined( $retVal[1] )) {      if ($group =~ /([A-Z]\w+)/) {
3630          $retVal[1] =~ s/(\t\S)?\s*$//;          $realGroup = $1;
3631      }      }
3632      # Return the result list.      # Return the page name.
3633      return @retVal;      $retVal = "../content/" . $self->{groupHash}->{$realGroup}->[1];
3634        # Return the result.
3635        return $retVal;
3636  }  }
3637    
3638  =head3 FriendlyTimestamp  =head3 ReadGroupFile
3639    
3640  Convert a time number to a user-friendly time stamp for display.  C<< my %groupData = Sprout::ReadGroupFile($groupFileName); >>
3641    
3642  This is a static method.  Read in the data from the specified group file. The group file contains information
3643    about each of the NMPDR groups.
3644    
3645  =over 4  =over 4
3646    
3647  =item timeValue  =item name
3648    
3649  Numeric time value.  Name of the group.
3650    
3651    =item page
3652    
3653    Name of the group's page on the web site (e.g. C<campy.php> for
3654    Campylobacter)
3655    
3656    =item genus
3657    
3658    Genus of the group
3659    
3660    =item species
3661    
3662    Species of the group, or an empty string if the group is for an entire
3663    genus. If the group contains more than one species, the species names
3664    should be separated by commas.
3665    
3666    =back
3667    
3668    The parameters to this method are as follows
3669    
3670    =over 4
3671    
3672    =item groupFile
3673    
3674    Name of the file containing the group data.
3675    
3676  =item RETURN  =item RETURN
3677    
3678  Returns a string containing the same time in user-readable format.  Returns a hash keyed on group name. The value of each hash
3679    
3680  =back  =back
3681    
3682  =cut  =cut
3683    
3684  sub FriendlyTimestamp {  sub ReadGroupFile {
3685      my ($timeValue) = @_;      # Get the parameters.
3686      my $retVal = localtime($timeValue);      my ($groupFileName) = @_;
3687      return $retVal;      # Declare the return variable.
3688        my %retVal;
3689        # Read the group file.
3690        my @groupLines = Tracer::GetFile($groupFileName);
3691        for my $groupLine (@groupLines) {
3692            my ($name, $page, $genus, $species) = split(/\t/, $groupLine);
3693            $retVal{$name} = [$page, $genus, $species];
3694        }
3695        # Return the result.
3696        return %retVal;
3697  }  }
3698    
3699  =head3 AddProperty  =head3 AddProperty
# Line 3575  Line 3740 
3740      if (@properties) {      if (@properties) {
3741          # Here the property is already in the database. We save its ID.          # Here the property is already in the database. We save its ID.
3742          $propID = $properties[0];          $propID = $properties[0];
3743        } else {
3744          # Here the property value does not exist. We need to generate an ID. It will be set          # Here the property value does not exist. We need to generate an ID. It will be set
3745          # to a number one greater than the maximum value in the database. This call to          # to a number one greater than the maximum value in the database. This call to
3746          # GetAll will stop after one record.          # GetAll will stop after one record.
# Line 3588  Line 3754 
3754      $self->Insert('HasProperty', { 'from-link' => $featureID, 'to-link' => $propID, evidence => $url });      $self->Insert('HasProperty', { 'from-link' => $featureID, 'to-link' => $propID, evidence => $url });
3755  }  }
3756    
3757    =head2 Virtual Methods
3758    
3759    =head3 CleanKeywords
3760    
3761    C<< my $cleanedString = $sprout->CleanKeywords($searchExpression); >>
3762    
3763    Clean up a search expression or keyword list. This involves converting the periods
3764    in EC numbers to underscores, converting non-leading minus signs to underscores,
3765    a vertical bar or colon to an apostrophe, and forcing lower case for all alphabetic
3766    characters. In addition, any extra spaces are removed.
3767    
3768    =over 4
3769    
3770    =item searchExpression
3771    
3772    Search expression or keyword list to clean. Note that a search expression may
3773    contain boolean operators which need to be preserved. This includes leading
3774    minus signs.
3775    
3776    =item RETURN
3777    
3778    Cleaned expression or keyword list.
3779    
3780    =back
3781    
3782    =cut
3783    
3784    sub CleanKeywords {
3785        # Get the parameters.
3786        my ($self, $searchExpression) = @_;
3787        # Perform the standard cleanup.
3788        my $retVal = $self->ERDB::CleanKeywords($searchExpression);
3789        # Fix the periods in EC and TC numbers.
3790        $retVal =~ s/(\d+|\-)\.(\d+|-)\.(\d+|-)\.(\d+|-)/$1_$2_$3_$4/g;
3791        # Fix non-trailing periods.
3792        $retVal =~ s/\.(\w)/_$1/g;
3793        # Fix non-leading minus signs.
3794        $retVal =~ s/(\w)[\-]/$1_/g;
3795        # Fix the vertical bars and colons
3796        $retVal =~ s/(\w)[|:](\w)/$1'$2/g;
3797        # Return the result.
3798        return $retVal;
3799    }
3800    
3801    =head2 Internal Utility Methods
3802    
3803    =head3 ParseAssignment
3804    
3805    Parse annotation text to determine whether or not it is a functional assignment. If it is,
3806    the user, function text, and assigning user will be returned as a 3-element list. If it
3807    isn't, an empty list will be returned.
3808    
3809    A functional assignment is always of the form
3810    
3811        C<set >I<YYYY>C< function to\n>I<ZZZZZ>
3812    
3813    where I<YYYY> is the B<user>, and I<ZZZZ> is the actual functional role. In most cases,
3814    the user and the assigning user (from MadeAnnotation) will be the same, but that is
3815    not always the case.
3816    
3817    In addition, the functional role may contain extra data that is stripped, such as
3818    terminating spaces or a comment separated from the rest of the text by a tab.
3819    
3820    This is a static method.
3821    
3822    =over 4
3823    
3824    =item user
3825    
3826    Name of the assigning user.
3827    
3828    =item text
3829    
3830    Text of the annotation.
3831    
3832    =item RETURN
3833    
3834    Returns an empty list if the annotation is not a functional assignment; otherwise, returns
3835    a two-element list containing the user name and the function text.
3836    
3837    =back
3838    
3839    =cut
3840    
3841    sub _ParseAssignment {
3842        # Get the parameters.
3843        my ($user, $text) = @_;
3844        # Declare the return value.
3845        my @retVal = ();
3846        # Check to see if this is a functional assignment.
3847        my ($type, $function) = split(/\n/, $text);
3848        if ($type =~ m/^set function to$/i) {
3849            # Here we have an assignment without a user, so we use the incoming user ID.
3850            @retVal = ($user, $function);
3851        } elsif ($type =~ m/^set (\S+) function to$/i) {
3852            # Here we have an assignment with a user that is passed back to the caller.
3853            @retVal = ($1, $function);
3854        }
3855        # If we have an assignment, we need to clean the function text. There may be
3856        # extra junk at the end added as a note from the user.
3857        if (defined( $retVal[1] )) {
3858            $retVal[1] =~ s/(\t\S)?\s*$//;
3859        }
3860        # Return the result list.
3861        return @retVal;
3862    }
3863    
3864    =head3 FriendlyTimestamp
3865    
3866    Convert a time number to a user-friendly time stamp for display.
3867    
3868    This is a static method.
3869    
3870    =over 4
3871    
3872    =item timeValue
3873    
3874    Numeric time value.
3875    
3876    =item RETURN
3877    
3878    Returns a string containing the same time in user-readable format.
3879    
3880    =back
3881    
3882    =cut
3883    
3884    sub FriendlyTimestamp {
3885        my ($timeValue) = @_;
3886        my $retVal = localtime($timeValue);
3887        return $retVal;
3888    }
3889    
3890    
3891  1;  1;

Legend:
Removed from v.1.82  
changed lines
  Added in v.1.97

MCS Webmaster
ViewVC Help
Powered by ViewVC 1.0.3