File Coverage

Bio/MapIO/fpc.pm
Criterion Covered Total %
statement 191 231 82.6
branch 84 120 70.0
condition 19 33 57.5
subroutine 10 11 90.9
pod 2 2 100.0
total 306 397 77.0


line stmt bran cond sub pod time code
1             # fpc.pm,v 1.2.2.1 2005/10/09 15:16:27 jason Exp
2             #
3             # BioPerl module for Bio::MapIO::fpc
4             #
5             # Please direct questions and support issues to
6             #
7             # Cared for by Gaurav Gupta
8             #
9             # Copyright AGCoL
10             #
11             # You may distribute this module under the same terms as perl itself
12              
13             # POD documentation - main docs before the code
14              
15             =head1 NAME
16              
17             Bio::MapIO::fpc - A FPC Map reader
18              
19             =head1 SYNOPSIS
20              
21             # do not use this object directly it is accessed through the Bio::MapIO system
22              
23             use Bio::MapIO;
24              
25             -format : specifies the format of the file format is "fpc",
26             -file : specifies the name of the .fpc file
27             -readcor : boolean argument, indicating if .cor is to be read
28             or not. It looks for the .cor file in the same path
29             as .fpc file.
30             0 : doesn't read .cor file
31             1 : reads the .cor file
32             [default 0]
33             -verbose : indicates the process of loading of fpc file
34             my $mapio = Bio::MapIO->new(-format => "fpc",
35             -file => "rice.fpc",
36             -readcor => 0,
37             -verbose => 0);
38              
39             my $map = $mapio->next_map();
40              
41             foreach my $marker ( $map->each_markerid() ) {
42             # loop through the markers associated with the map
43             # likewise for contigs, clones, etc.
44             }
45              
46              
47             =head1 DESCRIPTION
48              
49             This object contains code for parsing and processing FPC files and creating
50             L object from it.
51              
52             For faster access and better optimization, the data is stored internally in
53             hashes. The corresponding objects are created on request.
54              
55             We handle reading of the FPC ourselves, since MapIO module of Bioperl adds
56             too much overhead.
57              
58             =cut
59              
60             # Let the code begin...
61              
62             package Bio::MapIO::fpc;
63 2     2   8 use strict;
  2         2  
  2         53  
64 2     2   419 use POSIX;
  2         4914  
  2         11  
65              
66 2     2   3808 use Bio::Map::Physical;
  2         3  
  2         51  
67 2     2   7 use Bio::Map::Clone;
  2         2  
  2         30  
68 2     2   6 use Bio::Map::Contig;
  2         2  
  2         25  
69 2     2   5 use Bio::Map::FPCMarker;
  2         2  
  2         25  
70 2     2   5 use Bio::Range;
  2         1  
  2         35  
71              
72 2     2   6 use base qw(Bio::MapIO);
  2         1  
  2         4163  
73              
74             my $_readcor;
75              
76             =head1 Initializer
77              
78             =head2 _initialize
79              
80             Title : _initialize
81             Usage : called implicitly
82             Function: calls the SUPER::_initialize
83             Returns : nothing
84             Args : species, readcor
85              
86             =cut
87              
88             sub _initialize{
89 2     2   5 my ($self,@args) = @_;
90 2         2 my $species;
91 2         12 $self->SUPER::_initialize(@args);
92 2         6 ($species,$_readcor) = $self->_rearrange([qw(SPECIES READCOR)], @args);
93 2 100       9 $_readcor = 0 unless (defined($_readcor));
94             }
95              
96             =head1 Access Methods
97              
98             These methods let you get and set the member variables
99              
100             =head2 next_map
101              
102             Title : next_map
103             Usage : my $fpcmap = $mapio->next_map();
104             Function: gets the fpcmap from MapIO
105             Returns : object of type L
106             Args : none
107              
108             =cut
109              
110             sub next_map{
111              
112 2     2 1 4 my ($self) = @_;
113              
114 2         3 my $line;
115 2         1 my ($name,$fpcver,$moddate,$moduser,$contigcnt,$clonecnt,$markerscnt,
116             $bandcnt,$marker,$seqclone);
117 0         0 my ($corfile,$corindex,$BUFFER);
118 0         0 my @cordata;
119 0         0 my %fpcmarker;
120 0         0 my ($contig, $contigNumber);
121 2         2 my $curClone = 0;
122 2         3 my $curMarker = 0;
123 2         1 my $curContig = 0;
124 2         3 my %_clones;
125             my %_markers;
126 0         0 my %_contigs;
127 2         2 my $ctgzeropos = 1;
128              
129 2         14 my $map = Bio::Map::Physical->new('-units' => 'CB',
130             '-type' => 'physical');
131              
132 2         5 my $filename = $self->file();
133 2         3 my $fh = $self->{'_filehandle'};
134              
135 2 50       5 if (defined($_readcor)) {
136 2         4 $map->core_exists($_readcor);
137             }
138             else {
139 0         0 $map->core_exists(0);
140             }
141              
142 2 100       5 if ($map->core_exists()) {
143 1         3 $corfile = substr($filename,0,length($filename)-3)."cor";
144 1 50       34 if (open my $CORE, '<', $corfile) {
145 1         20 while( read($CORE, $BUFFER, 2) ) {
146 9772         13138 push @cordata, unpack('n*', $BUFFER);
147             }
148             }
149             else {
150 0         0 $map->core_exists(0);
151             }
152             }
153              
154             ## Read in the header
155 2         35 while (defined($line = <$fh>)) {
156 20         18 chomp($line);
157              
158 20 100       38 if ($line =~ m{^//\s+fpc\s+project\s+(.+)}) { $map->name($1); }
  2         20  
159 20 100       43 if ($line =~ m{^//\s+([\d.]+)}) {
160 2         4 my $version = $1;
161 2         6 $version =~ /((\d+)\.(\d+))(.*)/;
162 2         8 $map->version($1);
163 2 50       7 if ($line =~ /User:\s+(.+)/) { $map->modification_user($1); }
  2         6  
164             }
165              
166 20 100       28 if ($line =~ m{^//\s+Framework\s+(\w+)\s+(\w+)\s+([-\w]+)\s+(\w+)\s+(\w+)\s+(.+)$})
167             {
168 2 50       13 $map->group_type($3) if ($2 eq "Label");
169 2 50       8 $map->group_abbr($5) if ($4 eq "Abbrev");
170             }
171              
172 20 100       70 last unless ($line =~ m{^//});
173             }
174              
175 2 50 33     6 if (!defined($map->group_type()) || !defined($map->group_abbr()) ) {
176 0         0 $map->group_type("Chromosome");
177 0         0 $map->group_abbr("Chr");
178             }
179              
180 2         6 $_contigs{0}{'range'}{'end'} = 0;
181 2         4 $_contigs{0}{'range'}{'start'} = 0;
182              
183             ## Read in the clone data
184 2         5 while (defined($line = <$fh>)) {
185 975         669 $marker = 0;
186 975         571 $contig = 0;
187 975         547 $seqclone = 0;
188 975         558 $contigNumber = 0;
189              
190 975         554 my ($type,$name);
191 0         0 my (@amatch,@pmatch,@ematch);
192              
193 975         553 my $bandsread = 0;
194              
195 975 100       1235 last if ($line =~ /^Markerdata/);
196              
197              
198 973         2015 $line =~ /^(\w+)\s+:\s+"(.+)"/;
199              
200             ## these will be set if we did find the clone line
201 973         1168 ($type, $name) = ($1, $2);
202              
203 973 100       1278 if ($name =~ /sd1/) {
204 30         20 $seqclone = 1;
205             }
206              
207 973         1946 $_clones{$name}{'type'} = $type;
208 973         793 $_clones{$name}{'contig'} = 0;
209 973         789 $_contigs{'0'}{'clones'}{$name} = 0;
210              
211 973         566 my $temp;
212              
213             ## Loop through the following lines, getting attributes for clone
214 973   66     3738 while (defined($line = <$fh>) && $line !~ /^\s*\n$/) {
215              
216 7259 100 66     30979 if ($line =~ /^Map "ctg(\d+)" Ends (Left|Right) ([-\d]+)/) {
    100          
    100          
    100          
    100          
    100          
    100          
    100          
    100          
217 965         1341 $_clones{$name}{'contig'} = $1;
218 965         1129 $_contigs{$1}{'clones'}{$name} = 0;
219              
220 965         906 delete($_contigs{'0'}{'clones'}{$name});
221              
222 965         738 $temp = $3;
223 965         727 $contigNumber = $1;
224 965         1213 $line = <$fh>;
225 965         1570 $line =~ /^Map "ctg(\d+)" Ends (Left|Right) ([\d]+)/;
226 965         1520 $_clones{$name}{'range'}{'start'} = $temp;
227              
228             $_contigs{$contigNumber}{'range'}{'start'} = $temp
229             if (!exists($_contigs{$contigNumber}{'range'}{'start'})
230 965 100 100     3273 || $_contigs{$contigNumber}{'range'}{'start'}
231             > $temp );
232              
233 965         1288 $_clones{$name}{'range'}{'end'} = $3;
234              
235             $_contigs{$contigNumber}{'range'}{'end'} = $3
236             if (!exists($_contigs{$contigNumber}{'range'}{'end'})
237 965 100 100     6062 || $_contigs{$contigNumber}{'range'}{'end'} < $3 );
238              
239             }
240             elsif ($line =~ /^([a-zA-Z]+)_match_to_\w+\s+"(.+)"/) {
241 440         704 my $matchtype = "match" . lc(substr($1, 0, 1));
242 440         2257 $_clones{$name}{$matchtype}{$2} = 0;
243             }
244             elsif ($line =~ /^Positive_(\w+)\s+"(.+)"/) {
245 1079         1616 $_clones{$name}{'markers'}{$2} = 0;
246 1079         1325 $_markers{$2}{'clones'}{$name} = 0;
247 1079         1103 $_markers{$2}{'type'} = $1;
248 1079         1007 $_markers{$2}{'contigs'}{$contigNumber} = 0;
249 1079         4298 $_contigs{$contigNumber}{'markers'}{$2} = 0;
250             }
251             elsif ($line =~ /^Bands\s+(\d+)\s+(\d+)/ && !$bandsread) {
252 973         697 my $i = 0;
253 973         563 my @numbands;
254 973         632 $bandsread = 1;
255              
256 973 100       1477 if ($map->core_exists()) {
257 355         591 while($i<$2){
258 9772         8505 push(@numbands,$cordata[($1-1)+$i]);
259 9772         10925 $i++;
260             }
261 355         457 $_clones{$name}{'bands'} = \@numbands;
262             }
263             else {
264 618         1018 push(@numbands,$1,$2);
265 618         733 $_clones{$name}{'bands'} = \@numbands;
266             }
267 973 100       4942 if (exists($_contigs{0}{'clones'}{$name})) {
268 8         12 $_clones{$name}{'range'}{'start'} = $ctgzeropos;
269 8         14 $_clones{$name}{'range'}{'end'} = $ctgzeropos + $2;
270 8         11 $_contigs{0}{'range'}{'end'} = $ctgzeropos + $2;
271 8         44 $ctgzeropos += $2;
272             }
273             }
274             elsif ($line =~ /^Gel_number\s+(.+)/) {
275 973         4089 $_clones{$name}{'gel'} = $1;
276             }
277             elsif ($line =~ /^Remark\s+"(.+)"/) {
278 135         224 $_clones{$name}{'remark'} .= $1;
279 135         99 $_clones{$name}{'remark'} .= "\n";
280 135 100       240 if($seqclone == 1 ) {
281 123 100       469 if( $1 =~ /\,\s+Chr(\d+)\s+/){
282 30         150 $_clones{$name}{'group'} = $1;
283             }
284             }
285             }
286             elsif ($line =~ /^Fp_number\s+"(.+)"/) {
287 549         2351 $_clones{$name}{'fp_number'} = $1;
288             }
289             elsif ($line =~ /^Shotgun\s+(\w+)\s+(\w+)/) {
290 37         76 $_clones{$name}{'sequence_type'} = $1;
291 37         169 $_clones{$name}{'sequence_status'} = $2;
292             }
293             elsif ($line =~ /^Fpc_remark\s+"(.+)"/) {
294 162         266 $_clones{$name}{'fpc_remark'} .= $1;
295 162         643 $_clones{$name}{'fpc_remark'} .= "\n";
296             }
297             }
298              
299 973         667 $curClone++;
300 973 50 33     1512 print "Adding clone $curClone...\n\r"
301             if ($self->verbose() && $curClone % 1000 == 0);
302             }
303              
304 2         13 $map->_setCloneRef(\%_clones);
305 2         28 $line = <$fh>;
306              
307 2   33     16 while (defined($line = <$fh>) && $line !~ /Contigdata/) {
308 167         105 my ($type,$name);
309              
310 167 100       381 last if ($line !~ /^Marker_(\w+)\s+:\s+"(.+)"/);
311              
312 165         193 ($type, $name) = ($1, $2);
313              
314 165         189 $_markers{$name}{'type'} = $type;
315 165         135 $_markers{$name}{'group'} = 0;
316 165         111 $_markers{$name}{'global'} = 0;
317 165         113 $_markers{$name}{'anchor'} = 0;
318              
319 165   66     590 while (defined($line = <$fh>) && $line !~ /^\s*\n$/) {
320 490 50       2066 if ($line =~ /^Global_position\s+([\d.]+)\s*(Frame)?/) {
    100          
    100          
    50          
    100          
321 0         0 my $position = $1 - floor($1/1000)*1000;
322 0         0 $position = sprintf("%.2f",$position);
323              
324 0         0 $_markers{$name}{'global'} = $position;
325 0         0 $_markers{$name}{'group'} = floor($1/1000);
326 0         0 $_markers{$name}{'anchor'} = 1;
327              
328 0 0       0 if(defined($2)) {
329 0         0 $_markers{$name}{'framework'} = 1;
330             }
331             else {
332 0         0 $_markers{$name}{'framework'} = 0;
333             }
334             }
335             elsif ($line =~ /^Anchor_bin\s+"([\w\d.]+)"/) {
336 48         51 my $grpmatch = $1;
337 48         65 my $grptype = $map->group_type();
338              
339 48         69 $grpmatch =~ /(\d+|\w)(.*)/;
340              
341 48         32 my ($group,$subgroup);
342 48         41 $group = $1;
343 48         31 $subgroup = $2;
344              
345 48 50       55 $subgroup = substr($subgroup,1) if ($subgroup =~ /^\./);
346              
347 48         49 $_markers{$name}{'group'} = $group;
348 48         212 $_markers{$name}{'subgroup'} = $subgroup;
349             }
350             elsif ($line =~ /^Anchor_pos\s+([\d.]+)\s+(F|P)?/){
351 48         66 $_markers{$name}{'global'} = $1;
352 48         33 $_markers{$name}{'anchor'} = 1;
353              
354 48 100       63 if ($2 eq 'F') {
355 26         120 $_markers{$name}{'framework'} = 1;
356             }
357             else {
358 22         99 $_markers{$name}{'framework'} = 0;
359             }
360             }
361             elsif ($line =~ /^anchor$/) {
362 0         0 $_markers{$name}{'anchor'} = 1;
363             }
364             elsif ($line =~ /^Remark\s+"(.+)"/) {
365 64         108 $_markers{$name}{'remark'} .= $1;
366 64         230 $_markers{$name}{'remark'} .= "\n";
367             }
368             }
369 165         95 $curMarker++;
370 165 50 33     220 print "Adding Marker $curMarker...\n"
371             if ($self->verbose() && $curMarker % 1000 == 0);
372             }
373              
374 2         12 $map->_setMarkerRef(\%_markers);
375              
376 2         7 my $ctgname;
377 2         7 my $grpabbr = $map->group_abbr();
378 2         3 my $chr_remark;
379              
380 2         5 $_contigs{0}{'group'} = 0;
381              
382 2         7 while (defined($line = <$fh>)) {
383              
384 31 100 66     359 if ($line =~ /^Ctg(\d+)/) {
    50          
    100          
    100          
    100          
385 12         14 $ctgname = $1;
386 12         13 $_contigs{$ctgname}{'group'} = 0;
387 12         10 $_contigs{$ctgname}{'anchor'} = 0;
388 12         12 $_contigs{$ctgname}{'position'} = 0;
389              
390 12 50       52 if ($line =~ /#\w*(.*)\w*$/) {
391 12         18 $_contigs{$ctgname}{'remark'} = $1;
392 12 50       21 if ($line =~ /#\s+Chr(\d+)\s+/) {
393 0         0 $_contigs{$ctgname}{'group'} = $1;
394 0         0 $_contigs{$ctgname}{'anchor'} = 1;
395             }
396             }
397             }
398             elsif ($line =~ /^Chr_remark\s+"(-|\+|Chr(\d+))\s+(.+)"$/) {
399              
400 0         0 $_contigs{$ctgname}{'anchor'} = 1;
401 0 0       0 $_contigs{$ctgname}{'chr_remark'} = $3 if(defined($3));
402              
403 0 0       0 if (defined($2)) {
404 0         0 $_contigs{$ctgname}{'group'} = $2;
405             }
406             else {
407 0         0 $_contigs{$ctgname}{'group'} = "?";
408             }
409             }
410             elsif ($line =~ /^User_remark\s+"(.+)"/) {
411 2         8 $_contigs{$ctgname}{'usr_remark'} = $1;
412             }
413             elsif ($line =~ /^Trace_remark\s+"(.+)"/) {
414 1         2 $_contigs{$ctgname}{'trace_remark'} = $1;
415             }
416             elsif ($grpabbr && $line =~ /^Chr_remark\s+"(\W|$grpabbr((\d+)|(\w+)|([.\w\d]+)))\s*(\{(.*)\}|\[(.*)\])?"\s+(Pos\s+((\d.)+|NaN))(NOEDIT)?/)
417             {
418 4         7 my $grpmatch = $2;
419 4         4 my $pos = $10;
420 4 50       10 if ($pos eq "NaN") {
421 0         0 $pos = 0;
422 0         0 print "Warning: Nan encountered for Contig position \n";
423             }
424 4         11 $_contigs{$ctgname}{'chr_remark'} = $6;
425 4         6 $_contigs{$ctgname}{'position'} = $pos;
426 4         7 $_contigs{$ctgname}{'subgroup'} = 0;
427              
428 4 50       8 if (defined($grpmatch)) {
429 4         6 $_contigs{$ctgname}{'anchor'} = 1;
430              
431 4 50       7 if ($grpmatch =~ /((\d+)((\D\d.\d+)|(.\d+)))|((\w+)(\.\d+))/) {
432              
433 0         0 my ($group,$subgroup);
434 0 0       0 $group = $2 if($grpabbr eq "Chr");
435 0 0       0 $subgroup = $3 if($grpabbr eq "Chr");
436              
437 0 0       0 $group = $7 if($grpabbr eq "Lg");
438 0 0       0 $subgroup = $8 if($grpabbr eq "Lg");
439              
440 0 0       0 $subgroup = substr($subgroup,1) if ($subgroup =~ /^\./);
441 0         0 $_contigs{$ctgname}{'group'} = $group;
442 0         0 $_contigs{$ctgname}{'subgroup'} = $subgroup;
443              
444             }
445             else {
446 4         6 $_contigs{$ctgname}{'group'} = $grpmatch;
447             }
448             }
449             else {
450 0         0 $_contigs{$ctgname}{'anchor'} = 1;
451 0         0 $_contigs{$ctgname}{'group'} = "?";
452             }
453             }
454 31         19 $curContig++;
455 31 50 33     41 print "Adding Contig $curContig...\n"
456             if ($self->verbose() && $curContig % 100 == 0);
457             }
458              
459 2         12 $map->_setContigRef(\%_contigs);
460 2         9 $map->_calc_markerposition();
461 2 50       15 $map->_calc_contigposition() if ($map->version() < 7.0);
462 2 50       7 $map->_calc_contiggroup() if ($map->version() == 4.6);
463              
464 2         243 return $map;
465             }
466              
467              
468             =head2 write_map
469              
470             Title : write_map
471             Usage : $mapio->write_map($map);
472             Function: Write a map out
473             Returns : none
474             Args : Bio::Map::MapI
475              
476             =cut
477              
478             sub write_map{
479 0     0 1   my ($self,@args) = @_;
480 0           $self->throw_not_implemented();
481             }
482              
483             1;
484              
485             =head1 FEEDBACK
486              
487             =head2 Mailing Lists
488              
489             User feedback is an integral part of the evolution of this and other
490             Bioperl modules. Send your comments and suggestions preferably to
491             the Bioperl mailing list. Your participation is much appreciated.
492              
493             bioperl-l@bioperl.org - General discussion
494             http://bioperl.org/wiki/Mailing_lists - About the mailing lists
495              
496             =head2 Support
497              
498             Please direct usage questions or support issues to the mailing list:
499              
500             I
501              
502             rather than to the module maintainer directly. Many experienced and
503             reponsive experts will be able look at the problem and quickly
504             address it. Please include a thorough description of the problem
505             with code and data examples if at all possible.
506              
507             =head2 Reporting Bugs
508              
509             Report bugs to the Bioperl bug tracking system to help us keep track
510             of the bugs and their resolution. Bug reports can be submitted via the
511             web:
512              
513             https://github.com/bioperl/bioperl-live/issues
514              
515             =head1 AUTHOR - Gaurav Gupta
516              
517             Email gaurav@genome.arizona.edu
518              
519             =head1 PROJECT LEADERS
520              
521             Jamie Hatfield jamie@genome.arizona.edu
522              
523             Dr. Cari Soderlund cari@genome.arizona.edu
524              
525             =head1 PROJECT DESCRIPTION
526              
527             The project was done in Arizona Genomics Computational Laboratory
528             (AGCoL) at University of Arizona.
529              
530             This work was funded by USDA-IFAFS grant #11180 titled "Web Resources
531             for the Computation and Display of Physical Mapping Data".
532              
533             For more information on this project, please refer:
534             http://www.genome.arizona.edu
535              
536             =head1 APPENDIX
537              
538             The rest of the documentation details each of the object methods.
539             Internal methods are usually preceded with a _
540              
541             =cut