line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package Bio::GMOD; |
2
|
|
|
|
|
|
|
|
3
|
13
|
|
|
13
|
|
67454
|
use strict; |
|
13
|
|
|
|
|
29
|
|
|
13
|
|
|
|
|
468
|
|
4
|
13
|
|
|
13
|
|
69
|
use warnings; |
|
13
|
|
|
|
|
24
|
|
|
13
|
|
|
|
|
466
|
|
5
|
13
|
|
|
13
|
|
66
|
use vars qw/@ISA $VERSION/; |
|
13
|
|
|
|
|
24
|
|
|
13
|
|
|
|
|
728
|
|
6
|
|
|
|
|
|
|
|
7
|
13
|
|
|
13
|
|
13405
|
use Bio::GMOD::Util::Status; |
|
13
|
|
|
|
|
45
|
|
|
13
|
|
|
|
|
387
|
|
8
|
13
|
|
|
13
|
|
78
|
use Bio::GMOD::Util::Rearrange; |
|
13
|
|
|
|
|
22
|
|
|
13
|
|
|
|
|
17366
|
|
9
|
|
|
|
|
|
|
|
10
|
|
|
|
|
|
|
@ISA = qw/Bio::GMOD::Util::Status/; |
11
|
|
|
|
|
|
|
|
12
|
|
|
|
|
|
|
$VERSION = '0.028'; |
13
|
|
|
|
|
|
|
|
14
|
|
|
|
|
|
|
sub new { |
15
|
2
|
|
|
2
|
1
|
69
|
my ($self,@p) = @_; |
16
|
2
|
|
|
|
|
20
|
my ($requested_mod,$class,$overrides) = rearrange([qw/MOD CLASS/],@p); |
17
|
|
|
|
|
|
|
|
18
|
|
|
|
|
|
|
# Establish a generic GMOD object. This is largely used |
19
|
|
|
|
|
|
|
# for situations when we want to work across all MODs. |
20
|
2
|
50
|
|
|
|
50
|
unless ($requested_mod) { |
21
|
0
|
|
|
|
|
0
|
my $this = bless {},$self; |
22
|
0
|
|
|
|
|
0
|
return $this; |
23
|
|
|
|
|
|
|
} |
24
|
|
|
|
|
|
|
|
25
|
2
|
50
|
|
|
|
10
|
my $mod = ($self->supported_mods($requested_mod)) ? $requested_mod : 0; |
26
|
2
|
50
|
|
|
|
7
|
$mod = $self->species2mod($requested_mod) unless $mod; |
27
|
2
|
50
|
|
|
|
6
|
$mod = $self->organism2mod($requested_mod) unless $mod; |
28
|
|
|
|
|
|
|
|
29
|
2
|
50
|
|
|
|
5
|
$self->logit(-msg => "The supplied mod $requested_mod is not a currently available MOD.", |
30
|
|
|
|
|
|
|
-die => 1) unless $mod; |
31
|
|
|
|
|
|
|
|
32
|
2
|
|
|
|
|
7
|
my $adaptor_class = "Bio::GMOD::Adaptor::$mod"; |
33
|
2
|
50
|
|
|
|
172
|
eval "require $adaptor_class" or $self->logit(-msg=>"Could not subclass $adaptor_class: $!",-die=>1); |
34
|
0
|
|
|
|
|
0
|
my $adaptor = $adaptor_class->new($overrides); |
35
|
0
|
|
|
|
|
0
|
my $name = $adaptor->name; |
36
|
0
|
|
|
|
|
0
|
my $this = {}; |
37
|
|
|
|
|
|
|
|
38
|
|
|
|
|
|
|
# Establish generic subclassing for the various top level classes |
39
|
|
|
|
|
|
|
# This assumes that none of these subclasses will require their own new() |
40
|
0
|
|
|
|
|
0
|
my $subclass = "$self" . "::$name"; |
41
|
0
|
0
|
0
|
|
|
0
|
if ($class) { # Force a specific class |
|
|
0
|
|
|
|
|
|
42
|
0
|
|
|
|
|
0
|
bless $this,$class; |
43
|
|
|
|
|
|
|
} elsif ($name && eval "require $subclass" ) { |
44
|
0
|
|
|
|
|
0
|
bless $this,$subclass; |
45
|
|
|
|
|
|
|
} else { |
46
|
0
|
|
|
|
|
0
|
bless $this,$self; |
47
|
|
|
|
|
|
|
} |
48
|
|
|
|
|
|
|
|
49
|
0
|
|
|
|
|
0
|
$this->{adaptor} = $adaptor; |
50
|
0
|
|
|
|
|
0
|
$this->{mod} = $mod; |
51
|
0
|
|
|
|
|
0
|
return $this; |
52
|
|
|
|
|
|
|
} |
53
|
|
|
|
|
|
|
|
54
|
|
|
|
|
|
|
sub species2mod { |
55
|
0
|
|
|
0
|
1
|
0
|
my ($self,$provided_species) = @_; |
56
|
0
|
|
|
|
|
0
|
my %species2mod = ( |
57
|
|
|
|
|
|
|
elegans => 'WormBase', |
58
|
|
|
|
|
|
|
briggsae => 'WormBase', |
59
|
|
|
|
|
|
|
remanei => 'WormBase', |
60
|
|
|
|
|
|
|
japonica => 'WormBase', |
61
|
|
|
|
|
|
|
melanogaster => 'FlyBase', |
62
|
|
|
|
|
|
|
cerevisae => 'SGD', |
63
|
|
|
|
|
|
|
dictyostelium => 'DictyBase', |
64
|
|
|
|
|
|
|
); |
65
|
0
|
0
|
|
|
|
0
|
return ($species2mod{$provided_species}) if defined $species2mod{$provided_species}; |
66
|
|
|
|
|
|
|
|
67
|
|
|
|
|
|
|
# Maybe someone has used Genus species or G. species |
68
|
0
|
|
|
|
|
0
|
foreach my $species (keys %species2mod) { |
69
|
0
|
0
|
|
|
|
0
|
return $species2mod{$species} if ($provided_species =~ /$species/); |
70
|
|
|
|
|
|
|
} |
71
|
0
|
|
|
|
|
0
|
return 0; |
72
|
|
|
|
|
|
|
} |
73
|
|
|
|
|
|
|
|
74
|
|
|
|
|
|
|
sub organism2mod { |
75
|
0
|
|
|
0
|
1
|
0
|
my ($self,$organism) = @_; |
76
|
0
|
|
|
|
|
0
|
my %organism2mod = ( |
77
|
|
|
|
|
|
|
worm => 'WormBase', |
78
|
|
|
|
|
|
|
nematode => 'WormBase', |
79
|
|
|
|
|
|
|
fruitfly => 'FlyBase', |
80
|
|
|
|
|
|
|
fly => 'FlyBase', |
81
|
|
|
|
|
|
|
yeast => 'SGD', |
82
|
|
|
|
|
|
|
slime => 'DictyBase', |
83
|
|
|
|
|
|
|
); |
84
|
0
|
0
|
|
|
|
0
|
return ($organism2mod{$organism}) if defined $organism2mod{$organism}; |
85
|
0
|
|
|
|
|
0
|
return 0; |
86
|
|
|
|
|
|
|
} |
87
|
|
|
|
|
|
|
|
88
|
|
|
|
|
|
|
# ACCESSORS |
89
|
0
|
|
|
0
|
0
|
0
|
sub adaptor { return shift->{adaptor}; } |
90
|
0
|
|
|
0
|
0
|
0
|
sub mod { return shift->{mod}; } |
91
|
0
|
|
|
0
|
0
|
0
|
sub biogmod_version { return $VERSION }; |
92
|
|
|
|
|
|
|
|
93
|
|
|
|
|
|
|
|
94
|
|
|
|
|
|
|
|
95
|
|
|
|
|
|
|
#### WORK IN PROGRESS! HARD HATS REQUIRED! #### |
96
|
|
|
|
|
|
|
## This is a stab at implementing a multi-MOD object |
97
|
|
|
|
|
|
|
## within the current structure... |
98
|
|
|
|
|
|
|
## It's not done yet... |
99
|
|
|
|
|
|
|
sub new_alterantive { |
100
|
0
|
|
|
0
|
0
|
0
|
my ($self,@p) = @_; |
101
|
0
|
|
|
|
|
0
|
my ($mod,$class,$overrides) = rearrange([qw/MOD CLASS/],@p); |
102
|
|
|
|
|
|
|
|
103
|
|
|
|
|
|
|
# Establish a generic GMOD object. This is largely used |
104
|
|
|
|
|
|
|
# for situations when we want to work across all MODs. |
105
|
0
|
|
|
|
|
0
|
my $this = {}; |
106
|
0
|
0
|
|
|
|
0
|
unless ($mod) { |
107
|
|
|
|
|
|
|
# Instantiate adaptors to all the MODs |
108
|
0
|
|
|
|
|
0
|
bless $this,$self; |
109
|
0
|
|
|
|
|
0
|
map { $this->instatiate_adaptor($_,$overrides) } $this->supported_mods(); |
|
0
|
|
|
|
|
0
|
|
110
|
0
|
|
|
|
|
0
|
return $this; |
111
|
|
|
|
|
|
|
} |
112
|
|
|
|
|
|
|
|
113
|
|
|
|
|
|
|
# If more than a single MOD is supplied, let's assume that |
114
|
|
|
|
|
|
|
# the user wants to do comparative tasks between MODs. |
115
|
|
|
|
|
|
|
# Instatiate adaptors for all the requested MODs |
116
|
|
|
|
|
|
|
|
117
|
|
|
|
|
|
|
# If a single MOD is supplied, let's assume the task is something |
118
|
|
|
|
|
|
|
# that applies to a single MOD, like doing updates or archives. |
119
|
0
|
0
|
|
|
|
0
|
if (ref $mod) { |
120
|
0
|
|
|
|
|
0
|
map { $this->instatiate_adaptor($_,$overrides) } @$mod; |
|
0
|
|
|
|
|
0
|
|
121
|
0
|
|
|
|
|
0
|
$this = bless {},$self; |
122
|
|
|
|
|
|
|
} else { |
123
|
0
|
|
|
|
|
0
|
my $adaptor = $self->instatiate_adaptor($_,$overrides); |
124
|
0
|
|
|
|
|
0
|
my $name = $adaptor->name; |
125
|
|
|
|
|
|
|
|
126
|
|
|
|
|
|
|
# Establish generic subclassing for the various top level classes |
127
|
|
|
|
|
|
|
# This assumes that none of these subclasses will require their own new() |
128
|
0
|
|
|
|
|
0
|
my $subclass = "$self" . "::$name"; |
129
|
0
|
0
|
0
|
|
|
0
|
if ($class) { # Force a specific class (ooh, when is this used)? |
|
|
0
|
|
|
|
|
|
130
|
0
|
|
|
|
|
0
|
bless $this,$class; |
131
|
|
|
|
|
|
|
} elsif ($name && eval "require $subclass" ) { |
132
|
0
|
|
|
|
|
0
|
bless $this,$subclass; |
133
|
|
|
|
|
|
|
} else { |
134
|
0
|
|
|
|
|
0
|
bless $this,$self; |
135
|
|
|
|
|
|
|
} |
136
|
|
|
|
|
|
|
|
137
|
|
|
|
|
|
|
# For ease of access, store this primary MOD as adaptor |
138
|
0
|
|
|
|
|
0
|
$this->{adaptor} = $adaptor; |
139
|
0
|
|
|
|
|
0
|
$this->{mod} = $mod; |
140
|
|
|
|
|
|
|
} |
141
|
0
|
|
|
|
|
0
|
return $this; |
142
|
|
|
|
|
|
|
} |
143
|
|
|
|
|
|
|
|
144
|
|
|
|
|
|
|
# Instatiate a new adaptor if necessary; |
145
|
|
|
|
|
|
|
# If not just return an old one. |
146
|
|
|
|
|
|
|
sub instatiate_adaptor { |
147
|
0
|
|
|
0
|
0
|
0
|
my ($self,$requested_mod,$overrides) = @_; |
148
|
0
|
0
|
|
|
|
0
|
my $mod = ($self->supported_mods($requested_mod)) ? $requested_mod : 0; |
149
|
0
|
0
|
|
|
|
0
|
$mod = $self->species2mod($requested_mod) unless $mod; |
150
|
0
|
0
|
|
|
|
0
|
$mod = $self->organism2mod($requested_mod) unless $mod; |
151
|
0
|
|
|
|
|
0
|
my $adaptor = $self->adaptor($mod); |
152
|
0
|
0
|
|
|
|
0
|
unless ($adaptor) { |
153
|
0
|
0
|
|
|
|
0
|
$self->logit(-msg => "The supplied mod $_ is not a currently available MOD.", |
154
|
|
|
|
|
|
|
-die => 1) unless $mod; |
155
|
0
|
|
|
|
|
0
|
my $adaptor_class = "Bio::GMOD::Adaptor::$mod"; |
156
|
0
|
0
|
|
|
|
0
|
eval "require $adaptor_class" or $self->logit(-msg=>"Could not subclass $adaptor_class: $!",-die=>1); |
157
|
0
|
|
|
|
|
0
|
$adaptor = $adaptor_class->new($overrides); |
158
|
0
|
|
|
|
|
0
|
my $name = $adaptor->name; |
159
|
0
|
|
|
|
|
0
|
$self->{adaptors}->{$name} = $adaptor; |
160
|
|
|
|
|
|
|
} |
161
|
0
|
|
|
|
|
0
|
return $adaptor; |
162
|
|
|
|
|
|
|
} |
163
|
|
|
|
|
|
|
|
164
|
|
|
|
|
|
|
# Return a list of supported mods |
165
|
|
|
|
|
|
|
# These should correspond to symbolic names that are used |
166
|
|
|
|
|
|
|
# as module names |
167
|
|
|
|
|
|
|
sub supported_mods { |
168
|
2
|
|
|
2
|
0
|
5
|
my ($self,$mod) = @_; |
169
|
2
|
|
|
|
|
9
|
my %mods = ( |
170
|
|
|
|
|
|
|
WormBase => 1, |
171
|
|
|
|
|
|
|
FlyBase => 1 |
172
|
|
|
|
|
|
|
); |
173
|
2
|
50
|
|
|
|
8
|
unless ($mod) { |
174
|
0
|
|
|
|
|
0
|
return [ keys %mods ]; |
175
|
|
|
|
|
|
|
} |
176
|
2
|
50
|
|
|
|
13
|
return 1 if defined $mods{$mod}; |
177
|
0
|
|
|
|
|
|
return 0; |
178
|
|
|
|
|
|
|
} |
179
|
|
|
|
|
|
|
|
180
|
|
|
|
|
|
|
############ END WORK IN PROGRESS ############## |
181
|
|
|
|
|
|
|
|
182
|
|
|
|
|
|
|
1; |
183
|
|
|
|
|
|
|
|
184
|
|
|
|
|
|
|
=pod |
185
|
|
|
|
|
|
|
|
186
|
|
|
|
|
|
|
=head1 NAME |
187
|
|
|
|
|
|
|
|
188
|
|
|
|
|
|
|
Bio::GMOD - Unified API for Model Organism Databases |
189
|
|
|
|
|
|
|
|
190
|
|
|
|
|
|
|
=head1 SYNOPSIS |
191
|
|
|
|
|
|
|
|
192
|
|
|
|
|
|
|
Check the installed version of a MOD |
193
|
|
|
|
|
|
|
|
194
|
|
|
|
|
|
|
use Bio::GMOD::Util::CheckVersions.pm |
195
|
|
|
|
|
|
|
my $mod = Bio::GMOD::Util::CheckVersions->new(-mod=>'WormBase'); |
196
|
|
|
|
|
|
|
my $version = $mod->live_version; |
197
|
|
|
|
|
|
|
|
198
|
|
|
|
|
|
|
Update a MOD installation |
199
|
|
|
|
|
|
|
|
200
|
|
|
|
|
|
|
use Bio::GMOD::Update; |
201
|
|
|
|
|
|
|
my $mod = Bio::GMOD::Update->new(-mod=>'WormBase'); |
202
|
|
|
|
|
|
|
$gmod->update(); |
203
|
|
|
|
|
|
|
|
204
|
|
|
|
|
|
|
Fetch a list of genes from a MOD |
205
|
|
|
|
|
|
|
|
206
|
|
|
|
|
|
|
use Bio::GMOD::Query; |
207
|
|
|
|
|
|
|
my $mod = Bio::GMOD::Query->new(-mod=>'WormBase'); |
208
|
|
|
|
|
|
|
my @genes = $mod->fetch(-class=>'Gene',-name=>'unc-26'); |
209
|
|
|
|
|
|
|
|
210
|
|
|
|
|
|
|
=head1 DESCRIPTION |
211
|
|
|
|
|
|
|
|
212
|
|
|
|
|
|
|
Bio::GMOD is a unified API for accessing various Model Organism |
213
|
|
|
|
|
|
|
Databases. It is a part of the Generic Model Organism Database |
214
|
|
|
|
|
|
|
project, as well as distributed on CPAN. |
215
|
|
|
|
|
|
|
|
216
|
|
|
|
|
|
|
MODs are highly curated resources of biological data. Although they |
217
|
|
|
|
|
|
|
typically incorporate sequence data housed at community repositories |
218
|
|
|
|
|
|
|
such as NCBI, they place this information within a framework of |
219
|
|
|
|
|
|
|
biological fuction gelaned from the published literature of |
220
|
|
|
|
|
|
|
experiments in model organisms. |
221
|
|
|
|
|
|
|
|
222
|
|
|
|
|
|
|
Given the great proliferation of MODs, cross-site data mining |
223
|
|
|
|
|
|
|
strategies have been difficult to implement. Such strategies |
224
|
|
|
|
|
|
|
typically require a familiarity with both the underlying data model |
225
|
|
|
|
|
|
|
and the historical vocabulary of the model system. |
226
|
|
|
|
|
|
|
|
227
|
|
|
|
|
|
|
Furthermore, the quickly-evolving nature of these projects have made |
228
|
|
|
|
|
|
|
installing a MOD locally and keeping it up-to-date a delicate and |
229
|
|
|
|
|
|
|
time-consuming experience. |
230
|
|
|
|
|
|
|
|
231
|
|
|
|
|
|
|
Bio::GMOD aims to solve these problems by: |
232
|
|
|
|
|
|
|
|
233
|
|
|
|
|
|
|
1. Enabling cross-MOD data mining through a unified API |
234
|
|
|
|
|
|
|
2. Insulating programmatic end users from model changes |
235
|
|
|
|
|
|
|
3. Making MODs easy to install |
236
|
|
|
|
|
|
|
4. Making MODs easy to upgrade |
237
|
|
|
|
|
|
|
|
238
|
|
|
|
|
|
|
=head1 PUBLIC METHODS |
239
|
|
|
|
|
|
|
|
240
|
|
|
|
|
|
|
=over 4 |
241
|
|
|
|
|
|
|
|
242
|
|
|
|
|
|
|
=item Bio::GMOD->new(@options) |
243
|
|
|
|
|
|
|
|
244
|
|
|
|
|
|
|
Name : new() |
245
|
|
|
|
|
|
|
Status : public |
246
|
|
|
|
|
|
|
Required args : mod || organism || species |
247
|
|
|
|
|
|
|
Optional args : hash of system defaults to override |
248
|
|
|
|
|
|
|
Returns : Bio::GMOD::* object as appropriate, with embedded |
249
|
|
|
|
|
|
|
Bio::GMOD::Adaptor::* object |
250
|
|
|
|
|
|
|
|
251
|
|
|
|
|
|
|
Bio::GMOD->new() is the generic factory new constructor for all of |
252
|
|
|
|
|
|
|
Bio::GMOD.pm (with the exception of Bio::GMOD::Adaptor, discussed |
253
|
|
|
|
|
|
|
elsewhere). new() will create an object of the appropriate class, |
254
|
|
|
|
|
|
|
including dynamic subclassing when necessary, as well as initializing |
255
|
|
|
|
|
|
|
an appropriate default Bio::GMOD::Adaptor::* object. |
256
|
|
|
|
|
|
|
|
257
|
|
|
|
|
|
|
Options: |
258
|
|
|
|
|
|
|
-mod The symbolic name of the MOD to use (WormBase, FlyBase, SGD, etc) |
259
|
|
|
|
|
|
|
-class Force instantiation of a specific class (eg see Bio::GMOD::Monitor) |
260
|
|
|
|
|
|
|
|
261
|
|
|
|
|
|
|
Any additional options, passed in the named parameter "-name => value" |
262
|
|
|
|
|
|
|
style will automatically be considered to be default values specific |
263
|
|
|
|
|
|
|
to the MOD adaptor of choice. These values will be parsed and loaded |
264
|
|
|
|
|
|
|
into the Bio::GMOD::Adaptor::"your_mod" object. A corresponding accessor |
265
|
|
|
|
|
|
|
method (ie $adaptor->name) will be generated. See Bio::GMOD::Adaptor for |
266
|
|
|
|
|
|
|
additional details. |
267
|
|
|
|
|
|
|
|
268
|
|
|
|
|
|
|
if "--mod" is not specified, adaptors to all available MODs will be |
269
|
|
|
|
|
|
|
instantiated. Note that this probably does not make sense for classes |
270
|
|
|
|
|
|
|
like Update::*. It does provide a convenient mechanism to iteract |
271
|
|
|
|
|
|
|
with all MODs without too much extra coding. You can also specify a |
272
|
|
|
|
|
|
|
subset of MODs. Specifying a single MOD has special behavior fo use |
273
|
|
|
|
|
|
|
in things like updates. |
274
|
|
|
|
|
|
|
|
275
|
|
|
|
|
|
|
=item $self->species2mod($species); |
276
|
|
|
|
|
|
|
|
277
|
|
|
|
|
|
|
Name : species2mod($species) |
278
|
|
|
|
|
|
|
Status : public |
279
|
|
|
|
|
|
|
Required args : a species name |
280
|
|
|
|
|
|
|
Optional args : none |
281
|
|
|
|
|
|
|
Returns : a MOD name as string |
282
|
|
|
|
|
|
|
|
283
|
|
|
|
|
|
|
Provided with a single species, return the most appropriate MOD name. |
284
|
|
|
|
|
|
|
Species can be in the form of "G. species", "Genus species", or simple |
285
|
|
|
|
|
|
|
"species" for the lazy. |
286
|
|
|
|
|
|
|
|
287
|
|
|
|
|
|
|
eg: |
288
|
|
|
|
|
|
|
my $mod = $self->_species2mod('elegans'); |
289
|
|
|
|
|
|
|
# $mod contains 'WormBase' |
290
|
|
|
|
|
|
|
|
291
|
|
|
|
|
|
|
=item $self->organism2mod($organism) |
292
|
|
|
|
|
|
|
|
293
|
|
|
|
|
|
|
Name : organism2mod($organism) |
294
|
|
|
|
|
|
|
Status : public |
295
|
|
|
|
|
|
|
Required args : a general organism name |
296
|
|
|
|
|
|
|
Optional args : none |
297
|
|
|
|
|
|
|
Returns : a MOD name as string |
298
|
|
|
|
|
|
|
|
299
|
|
|
|
|
|
|
Like species2mod(), _organism2mod translates a general organism into |
300
|
|
|
|
|
|
|
the most appropriate hosting MOD. |
301
|
|
|
|
|
|
|
|
302
|
|
|
|
|
|
|
eg: |
303
|
|
|
|
|
|
|
my $mod = $self->_organism2mod('nematode'); |
304
|
|
|
|
|
|
|
# $mod contains 'WormBase' |
305
|
|
|
|
|
|
|
|
306
|
|
|
|
|
|
|
=back |
307
|
|
|
|
|
|
|
|
308
|
|
|
|
|
|
|
=head1 NOTES FOR DEVELOPERS |
309
|
|
|
|
|
|
|
|
310
|
|
|
|
|
|
|
Bio::GMOD.pm uses a generically subclass-able architecture that lets |
311
|
|
|
|
|
|
|
MOD developers support various features as needed or desired. For |
312
|
|
|
|
|
|
|
example, a developer may wish to override the default methods for |
313
|
|
|
|
|
|
|
Update.pm by building a Bio::GMOD::Update::FlyBase package that |
314
|
|
|
|
|
|
|
provides an update() method, as well as various supporting methods. |
315
|
|
|
|
|
|
|
|
316
|
|
|
|
|
|
|
Currently, the only participating MOD is WormBase. The author hopes |
317
|
|
|
|
|
|
|
that this will change in the future! |
318
|
|
|
|
|
|
|
|
319
|
|
|
|
|
|
|
=head1 BUGS |
320
|
|
|
|
|
|
|
|
321
|
|
|
|
|
|
|
None reported. |
322
|
|
|
|
|
|
|
|
323
|
|
|
|
|
|
|
=head1 SEE ALSO |
324
|
|
|
|
|
|
|
|
325
|
|
|
|
|
|
|
L, L |
326
|
|
|
|
|
|
|
|
327
|
|
|
|
|
|
|
=head1 AUTHOR |
328
|
|
|
|
|
|
|
|
329
|
|
|
|
|
|
|
Todd W. Harris Eharris@cshl.orgE. |
330
|
|
|
|
|
|
|
|
331
|
|
|
|
|
|
|
Copyright (c) 2003-2005 Cold Spring Harbor Laboratory. |
332
|
|
|
|
|
|
|
|
333
|
|
|
|
|
|
|
This library is free software; you can redistribute it and/or modify |
334
|
|
|
|
|
|
|
it under the same terms as Perl itself. |
335
|
|
|
|
|
|
|
|
336
|
|
|
|
|
|
|
=head1 ACKNOWLEDGEMENTS |
337
|
|
|
|
|
|
|
|
338
|
|
|
|
|
|
|
Much thanks to David Craig (dacraig@stanford.edu) for extensive alpha |
339
|
|
|
|
|
|
|
testing. |
340
|
|
|
|
|
|
|
|
341
|
|
|
|
|
|
|
=cut |