Beautiful Code [172]
The code story then calls Bio::Graphics::Panel->new() (line 4), creating a new panel object, and calls add_track() twice (line 5–6). This adds two tracks, one each for the first and second sets of features. Each call to add_track() takes an initial argument consisting of a reference to the array of features to add, followed by additional arguments controlling the appearance of the track.
The last step in the code story is to convert the panel into a PNG file and immediately print the result to standard output.
Initially this looked like a reasonable story, but as I thought about it further, I realized there were some basic deficiencies in the API. The biggest problem was that it forces the programmer to load all features into memory before beginning to construct the image. However, it is often convenient to read sequence features one at a time from a file or database. Several of the implementations of Bio::SeqFeature::CollectionI allow you to do this:
Code View: Scroll / Show All
$iterator = Bio::SeqFeature::CollectionI->get_seq_stream(@query_parameters);
while ($feature = $iterator->next_seq) {
# do something with the feature
}
Another problem was that once you called $panel->add_track(), you couldn't change the track's configuration settings. However, I could envision situations in which a developer would want to add a bunch of tracks in advance, and then go back and change an earlier track configuration later.
Finally, it seemed to me that add_track() was too inflexible, in that it forced the developer to add the tracks in a fixed order (top to bottom). However, there should be a way to insert tracks at arbitrary positions.
These considerations mandated the creation of a Track object:
$track1 = $panel_object->add_track(\@set_of_gene_features,
track_options..);
$track2 = $panel_object->add_track(\@set_of_variation_features,
track_options...);
One could then add features to an existing track like this:
$track1->add_features(feature1,feature2,feature3....)
or change its configuration this way:
$track1->configure(new_options)
This led to the alternative code story shown in Example 12-1.
Example 12-2. Story for BioPerl::Graphics use with tracks (pseudocode)
1 use Bio::Graphics::Panel;
2 $panel_object = Bio::Graphics::Panel->new(panel_options...)
3 $track1 = $panel_object->add_track(bump_true,other_track_options...);
4 $track2 = $panel_object->add_track(bump_true,other_track_options...);
5 $collection = Bio::SeqFeature::CollectionI->new(@args);
6 $iterator = $collection->get_seq_stream(@query_parameters);
7 $genes=0; $variations=0;
8 while ($feature = $iterator->next_seq) {
9 if ($feature->method eq 'gene') {
10 $track1->add_feature($feature);
11 $genes++;
12 } elsif ($feature->method eq 'variation') {
13 $track2->add_feature($feature);
14 $variations++;
15 }
16 }
17 $track1->configure(bump_false) if $genes > 100;
18 $track2->configure(bump_false) if $variations > 100;
19 print $panel_object->png;
In this version of the story, we first create two tracks without providing any features up front (lines 3–4). We do, however, provide add_track() with a set of options, including a "bump" option that is initially set to true. When designing this story,