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

Diff of /Sprout/SearchHelper.pm

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

revision 1.1, Tue Sep 26 13:46:03 2006 UTC revision 1.2, Wed Sep 27 16:55:38 2006 UTC
# Line 16  Line 16 
16      use FIGRules;      use FIGRules;
17      use HTML;      use HTML;
18      use BasicLocation;      use BasicLocation;
19        use FeatureQuery;
20    
21  =head1 Search Helper Base Class  =head1 Search Helper Base Class
22    
# Line 74  Line 75 
75    
76  =back  =back
77    
78    =head2 Adding a new Search Tool
79    
80    To add a new search tool to the system, you must
81    
82    =over 4
83    
84    =item 1
85    
86    Choose a class name for your search tool.
87    
88    =item 2
89    
90    Create a new subclass of this object and implement each of the virtual methods. The
91    name of the subclass must be C<SH>I<className>.
92    
93    =item 3
94    
95    Create an include file among the web server pages that describes how to use
96    the search tool. The include file must be in the B<includes> directory, and
97    its name must be C<SearchHelp_>I<className>C<.inc>.
98    
99    =item 4
100    
101    In the C<SearchSkeleton.cgi> script, add a C<use> statement for your search tool
102    and then put the class name in the C<@advancedClasses> list.
103    
104    =back
105    
106    =head3 Building a Search Form
107    
108    All search forms are three-column tables. In general, you want one form
109    variable per table row. The first column should contain the label and
110    the second should contain the form control for specifying the variable
111    value. If the control is wide, you should use C<colspan="2"> to give it
112    extra room. B<Do not> specify a width in any of your table cells, as
113    width management is handled by this class.
114    
115    The general code for creating the form should be
116    
117        sub Form {
118            my ($self) = @_;
119            # Get the CGI object.
120            my $cgi = @self->Q();
121            # Start the form.
122            my $retVal = $self->FormStart("form title");
123            # Assemble the table rows.
124            my @rows = ();
125            ... push table row Html into @rows ...
126            push @rows, $self->SubmitRow();
127            ... push more Html into @rows ...
128            # Build the table from the rows.
129            $retVal .= $self->MakeTable(\@rows);
130            # Close the form.
131            $retVal .= $self->FormEnd();
132            # Return the form Html.
133            return $retVal;
134        }
135    
136    Several helper methods are provided for particular purposes.
137    
138    =over 4
139    
140    =item 1
141    
142    L</NmpdrGenomeMenu> generates a control for selecting one or more genomes.
143    
144    =item 2
145    
146    L</FeatureFilterRow> formats several rows of controls for filtering features.
147    When you start building the code for the L</Find> method, you can use a
148    B<FeatureQuery> object to automatically filter each genome's features using
149    the values from the filter controls.
150    
151    =item 3
152    
153    L</QueueFormScript> allows you to queue JavaScript statements for execution
154    after the form is fully generated. If you are using very complicated
155    form controls, the L</QueueFormScript> method allows you to perform
156    JavaScript initialization. The L</NmpdrGenomeMenu> control uses this
157    facility to display a list of the pre-selected genomes.
158    
159    =back
160    
161    Finally, when generating the code for your controls, be sure to use any incoming
162    query parameters as default values so that the search request is persistent.
163    
164    =head3 Finding Search Results
165    
166    The L</Find> method is used to create the search results. For a search that
167    wants to return features (which is most of them), the basic code structure
168    would work as follows. It is assumed that the L</FeatureFilterRows> method
169    has been used to create feature filtering parameters.
170    
171        sub Find {
172            my ($self) = @_;
173            # Get the CGI and Sprout objects.
174            my $cgi = $self->Q();
175            my $sprout = $self->DB();
176            # Declare the return variable. If it remains undefined, the caller will
177            # know that an error occurred.
178            my $retVal;
179            ... validate the parameters ...
180            if (... invalid parameters...) {
181                $self->SetMessage(...appropriate message...);
182            } elsif (FeatureQuery::Valid($self)) {
183                # Initialize the session file.
184                $self->OpenSession();
185                # Initialize the result counter.
186                $retVal = 0;
187                ... get a list of genomes ...
188                for my $genomeID (... each genome ...) {
189                    my $fq = FeatureQuery->new($self, $genomeID);
190                    while (my $feature = $fq->Fetch()) {
191                        ... examine the feature ...
192                        if (... we want to keep it ...) {
193                            $self->PutFeature($fq);
194                            $retVal++;
195                        }
196                    }
197                }
198            }
199            # Close the session file.
200            $self->CloseSession();
201            # Return the result count.
202            return $retVal;
203        }
204    
205    A Find method is of course much more complicated than generating a form, and there
206    are variations on the above them. For example, you could eschew feature filtering
207    entirely in favor of your own custom filtering, you could include extra columns
208    in the output, or you could search for something that's not a feature at all. The
209    above code is just a loose framework.
210    
211    If you wish to add your own extra columns to the output, use the B<AddExtraColumns>
212    method of the feature query object.
213    
214        $fq->AddExtraColumns(score => $sc);
215    
216    The L</Find> method must return C<undef> if the search parameters are invalid. If this
217    is the case, then a message describing the problem should be passed to the framework
218    by calling L</SetMessage>. If the parameters are valid, then the method must return
219    the number of items found.
220    
221    =head2 Virtual Methods
222    
223    =head3 Form
224    
225    C<< my $html = $shelp->Form(); >>
226    
227    Generate the HTML for a form to request a new search.
228    
229    =head3 Find
230    
231    C<< my $resultCount = $shelp->Find(); >>
232    
233    Conduct a search based on the current CGI query parameters. The search results will
234    be written to the session cache file and the number of results will be
235    returned. If the search parameters are invalid, a result count of C<undef> will be
236    returned and a result message will be stored in this object describing the problem.
237    
238    =head3 Description
239    
240    C<< my $htmlText = $shelp->Description(); >>
241    
242    Return a description of this search. The description is used for the table of contents
243    on the main search tools page. It may contain HTML, but it should be character-level,
244    not block-level, since the description is going to appear in a list.
245    
246  =cut  =cut
247    
248  # This counter is used to insure every form on the page has a unique name.  # This counter is used to insure every form on the page has a unique name.
# Line 113  Line 282 
282      # Compute the subclass name.      # Compute the subclass name.
283      $class =~ /SH(.+)$/;      $class =~ /SH(.+)$/;
284      my $subClass = $1;      my $subClass = $1;
     # Create the Sprout object.  
     my $sprout = SFXlate->new_sprout_only();  
285      # Insure everybody knows we're in Sprout mode.      # Insure everybody knows we're in Sprout mode.
286      $query->param(-name => 'SPROUT', -value => 1);      $query->param(-name => 'SPROUT', -value => 1);
287      # Generate the form name.      # Generate the form name.
# Line 122  Line 289 
289      $formCount++;      $formCount++;
290      # Create the shelp object. It contains the query object (with the session ID)      # Create the shelp object. It contains the query object (with the session ID)
291      # as well as an indicator as to whether or not the session is new, plus the      # as well as an indicator as to whether or not the session is new, plus the
292      # class name and the Sprout object.      # class name and a placeholder for the Sprout object.
293      my $retVal = {      my $retVal = {
294                    query => $query,                    query => $query,
295                    type => $type,                    type => $type,
296                    class => $subClass,                    class => $subClass,
297                    sprout => $sprout,                    sprout => undef,
298                    orgs => {},                    orgs => {},
299                    name => $formName,                    name => $formName,
300                    scriptQueue => [],                    scriptQueue => [],
# Line 163  Line 330 
330  sub DB {  sub DB {
331      # Get the parameters.      # Get the parameters.
332      my ($self) = @_;      my ($self) = @_;
333        # Insure we have a database.
334        my $retVal = $self->{sprout};
335        if (! defined $retVal) {
336            $retVal = SFXlate->new_sprout_only();
337            $self->{sprout} = $retVal;
338        }
339      # Return the result.      # Return the result.
340      return $self->{sprout};      return $retVal;
341  }  }
342    
343  =head3 IsNew  =head3 IsNew
# Line 437  Line 610 
610    
611  =head3 PutFeature  =head3 PutFeature
612    
613  C<< $shelp->PutFeature($record, %extraCols); >>  C<< $shelp->PutFeature($fquery); >>
614    
615  Store a feature in the result cache. This is the workhorse method for most  Store a feature in the result cache. This is the workhorse method for most
616  searches, since the primary data item in the database is features.  searches, since the primary data item in the database is features.
617    
618  For each feature, there are certain columns that are standard: the feature name, the  For each feature, there are certain columns that are standard: the feature name, the
619  GBrowse and protein page links, the functional assignment, and so forth. If additional  GBrowse and protein page links, the functional assignment, and so forth. If additional
620  columns are required by a particular search subclass, they should be included in the  columns are required by a particular search subclass, they should be stored in
621  parameters, in key-value form. For example, the following call adds columns for  the feature query object using the B<AddExtraColumns> method. For example, the following
622  essentiality and virulence.  code adds columns for essentiality and virulence.
623    
624      $shelp->PutFeature($record, essential => $essentialFlag, virulence => $vfactor);      $fq->AddExtraColumns(essential => $essentialFlag, virulence => $vfactor);
625        $shelp->PutFeature($fq);
626    
627  For correct results, all values should be specified for all extra columns in all calls to  For correct results, all values should be specified for all extra columns in all calls to
628  B<PutFeature>. (In particular, the column header names are computed on the first  B<PutFeature>. (In particular, the column header names are computed on the first
# Line 458  Line 632 
632      if (! $essentialFlag) {      if (! $essentialFlag) {
633          $essentialFlag = undef;          $essentialFlag = undef;
634      }      }
635      $shelp->PutFeature($record, essential => $essentialFlag, virulence = $vfactor);      $fq->AddExtraColumns(essential => $essentialFlag, virulence => $vfactor);
636        $shelp->PutFeature($fq);
637    
638  =over 4  =over 4
639    
640  =item record  =item fquery
   
 DBObject record for the feature.  
641    
642  =item extraCols  FeatureQuery object containing the current feature data.
643    
644  =back  =back
645    
646  =cut  =cut
647    
648  sub PutFeature {  sub PutFeature {
649      # Get the parameters. Note that the extra columns are read in as a list      # Get the parameters.
650      # instead of a hash so that the column order is preserved.      my ($self, $fq) = @_;
651      my ($self, $record, @extraColList) = @_;      # Get the feature data.
652        my $record = $fq->Feature();
653        my $extraCols = $fq->ExtraCols();
654      # Check for a first-call situation.      # Check for a first-call situation.
655      if (! defined $self->{cols}) {      if (! defined $self->{cols}) {
656          # Here we need to set up the column information. Start with the defaults.          # Here we need to set up the column information. Start with the defaults.
657          $self->{cols} = $self->DefaultFeatureColumns();          $self->{cols} = $self->DefaultFeatureColumns();
658          # Append the extras. Note we proceed by twos because the columns are          # Append the extras, sorted by column name.
659          # specified in the form name => value.          for my $col (sort keys %{$extraCols}) {
660          for (my $i = 0; $i <= $#extraColList; $i += 2) {              push @{$self->{cols}}, "X=$col";
             push @{$self->{cols}}, "X=$extraColList[$i]";  
661          }          }
662          # Write out the column headers. This also prepares the cache file to receive          # Write out the column headers. This also prepares the cache file to receive
663          # output.          # output.
# Line 491  Line 665 
665      }      }
666      # Get the feature ID.      # Get the feature ID.
667      my ($fid) = $record->Value('Feature(id)');      my ($fid) = $record->Value('Feature(id)');
     # Now we process the columns themselves. First, convert the extra column list  
     # to a hash.  
     my %extraCols = @extraColList;  
668      # Loop through the column headers, producing the desired data.      # Loop through the column headers, producing the desired data.
669      my @output = ();      my @output = ();
670      for my $colName (@{$self->{cols}}) {      for my $colName (@{$self->{cols}}) {
671          push @output, $self->FeatureColumnValue($colName, $record, \%extraCols);          push @output, $self->FeatureColumnValue($colName, $record, $extraCols);
672      }      }
673      # Compute the sort key. The sort key floats NMPDR organism features to the      # Compute the sort key. The sort key floats NMPDR organism features to the
674      # top of the return list.      # top of the return list.
# Line 1094  Line 1265 
1265      # Return the result.      # Return the result.
1266      return $retVal;      return $retVal;
1267  }  }
1268    
1269    =head3 FeatureFilterRows
1270    
1271    C<< my $htmlText = $shelp->FeatureFilterRows(); >>
1272    
1273    This method creates table rows that can be used to filter features. There are
1274    two rows returned, and the values can be used to select features by genome
1275    using the B<FeatureQuery> object.
1276    
1277    =cut
1278    
1279    sub FeatureFilterRows {
1280        # Get the parameters.
1281        my ($self) = @_;
1282        # Return the result.
1283        return FeatureQuery::FilterRows($self);
1284    }
1285    
1286  =head3 GBrowseFeatureURL  =head3 GBrowseFeatureURL
1287    
1288  C<< my $url = SearchHelper::GBrowseFeatureURL($sprout, $feat); >>  C<< my $url = SearchHelper::GBrowseFeatureURL($sprout, $feat); >>

Legend:
Removed from v.1.1  
changed lines
  Added in v.1.2

MCS Webmaster
ViewVC Help
Powered by ViewVC 1.0.3