bug 2549; fixed small bug in Bio::Taxon which doesn't catch -common_name
[bioperl-live.git] / Bio / Map / Physical.pm
blob5f25ab271d643bd8f5132eac4d85ce29e86e7cf2
1 # $Id$
3 # BioPerl module for Bio::Map::Physical
5 # Cared for by Sendu Bala <bix@sendu.me.uk>
7 # Copyright AGCoL
9 # You may distribute this module under the same terms as perl itself
11 # POD documentation - main docs before the code
13 =head1 NAME
15 Bio::Map::Physical - A class for handling a Physical Map (such as FPC)
17 =head1 SYNOPSIS
19 use Bio::MapIO;
21 # accquire a Bio::Map::Physical using Bio::MapIO::fpc
22 my $mapio = Bio::MapIO->new(-format => "fpc",-file => "rice.fpc",
23 -readcor => 0);
25 my $physical = $mapio->next_map();
27 # get all the markers ids
28 foreach my $marker ( $physical->each_markerid() ) {
29 print "Marker $marker\n";
31 # acquire the marker object using Bio::Map::FPCMarker
32 my $markerobj = $physical->get_markerobj($marker);
34 # get all the clones hit by this marker
35 foreach my $clone ($markerobj->each_cloneid() ) {
36 print " +++$clone\n";
40 =head1 DESCRIPTION
42 This class is basically a continer class for a collection of Contig maps and
43 other physical map information.
45 Bio::Map::Physical has been tailored to work for FPC physical maps, but
46 could probably be used for others as well (with the appropriate MapIO
47 module).
49 This class also has some methods with specific functionalities:
51 print_gffstyle() : Generates GFF; either Contigwise[Default] or
52 Groupwise
54 print_contiglist() : Prints the list of Contigs, markers that hit the
55 contig, the global position and whether the marker
56 is a placement (<P>) or a Framework (<F>) marker.
58 print_markerlist() : Prints the markers list; contig and corresponding
59 number of clones.
61 matching_bands() : Given two clones [and tolerence], this method
62 calculates how many matching bands do they have.
64 coincidence_score() : Given two clones [,tolerence and gellen], this
65 method calculates the Sulston Coincidence score.
67 For faster access and better optimization, the data is stored internally in
68 hashes. The corresponding objects are created on request.
70 =head1 FEEDBACK
72 =head2 Mailing Lists
74 User feedback is an integral part of the evolution of this and other
75 Bioperl modules. Send your comments and suggestions preferably to
76 the Bioperl mailing list. Your participation is much appreciated.
78 bioperl-l@bioperl.org - General discussion
79 http://bioperl.org/wiki/Mailing_lists - About the mailing lists
81 =head2 Reporting Bugs
83 Report bugs to the Bioperl bug tracking system to help us keep track
84 of the bugs and their resolution. Bug reports can be submitted via the
85 web:
87 http://bugzilla.open-bio.org/
89 =head1 AUTHOR - Gaurav Gupta
91 Email gaurav@genome.arizona.edu
93 =head1 CONTRIBUTORS
95 Sendu Bala bix@sendu.me.uk
97 =head1 PROJECT LEADERS
99 Jamie Hatfield jamie@genome.arizona.edu
100 Dr. Cari Soderlund cari@genome.arizona.edu
102 =head1 PROJECT DESCRIPTION
104 The project was done in Arizona Genomics Computational Laboratory (AGCoL)
105 at University of Arizona.
107 This work was funded by USDA-IFAFS grant #11180 titled "Web Resources for
108 the Computation and Display of Physical Mapping Data".
110 For more information on this project, please refer:
111 http://www.genome.arizona.edu
113 =head1 APPENDIX
115 The rest of the documentation details each of the object methods.
116 Internal methods are usually preceded with a _
118 =cut
120 # Let the code begin...
122 package Bio::Map::Physical;
123 use vars qw($MAPCOUNT);
124 use strict;
125 use POSIX;
127 use Bio::Map::Clone;
128 use Bio::Map::Contig;
129 use Bio::Map::FPCMarker;
131 use base qw(Bio::Map::SimpleMap);
132 BEGIN { $MAPCOUNT = 1; }
134 =head1 Access Methods
136 These methods let you get and set the member variables
138 =head2 version
140 Title : version
141 Usage : my $version = $map->version();
142 Function: Get/set the version of the program used to
143 generate this map
144 Returns : scalar representing the version
145 Args : none to get, OR string to set
147 =cut
149 sub version {
150 my ($self,$value) = @_;
151 if (defined($value)) {
152 $self->{'_version'} = $value;
154 return $self->{'_version'};
157 =head2 modification_user
159 Title : modification_user
160 Usage : my $modification_user = $map->modification_user();
161 Function: Get/set the name of the user who last modified this map
162 Returns : scalar representing the username
163 Args : none to get, OR string to set
165 =cut
167 sub modification_user {
168 my ($self,$value) = @_;
169 if (defined($value)) {
170 $self->{'_modification_user'} = $value;
172 return $self->{'_modification_user'};
175 =head2 group_type
177 Title : group_type
178 Usage : $map->group_type($grptype);
179 my $grptype = $map->group_type();
180 Function: Get/set the group type of this map
181 Returns : scalar representing the group type
182 Args : none to get, OR string to set
184 =cut
186 sub group_type {
187 my ($self,$value) = @_;
188 if (defined($value)) {
189 $self->{'_grouptype'} = $value;
191 return $self->{'_grouptype'};
194 =head2 group_abbr
196 Title : group_abbr
197 Usage : $map->group_abbr($grpabbr);
198 my $grpabbr = $map->group_abbr();
199 Function: get/set the group abbrev of this map
200 Returns : string representing the group abbrev
201 Args : none to get, OR string to set
203 =cut
205 sub group_abbr {
206 my ($self,$value) = @_;
207 if (defined($value)) {
208 $self->{'_groupabbr'} = $value;
210 return $self->{'_groupabbr'};
213 =head2 core_exists
215 Title : core_exists
216 Usage : my $core_exists = $map->core_exists();
217 Function: Get/set if the FPC file is accompanied by COR file
218 Returns : boolean
219 Args : none to get, OR 1|0 to set
221 =cut
223 sub core_exists {
224 my ($self,$value) = @_;
225 if (defined($value)) {
226 $self->{'_corexists'} = $value ? 1 : 0;
228 return $self->{'_corexists'};
231 =head2 each_cloneid
233 Title : each_cloneid
234 Usage : my @clones = $map->each_cloneid();
235 Function: returns an array of clone names
236 Returns : list of clone names
237 Args : none
239 =cut
241 sub each_cloneid {
242 my ($self) = @_;
243 return keys %{$self->{'_clones'}};
246 =head2 get_cloneobj
248 Title : get_cloneobj
249 Usage : my $cloneobj = $map->get_cloneobj('CLONEA');
250 Function: returns an object of the clone given in the argument
251 Returns : object of the clone
252 Args : scalar representing the clone name
254 =cut
256 sub get_cloneobj {
257 my ($self,$clone) = @_;
259 return 0 if(!defined($clone));
260 return if($clone eq "");
261 return if(!exists($self->{'_clones'}{$clone}));
263 my ($type,$contig,$bands,$gel,$group,$remark,$fp_number);
264 my ($sequence_type,$sequence_status,$fpc_remark,@amatch,@pmatch,@ematch,
265 $startrange,$endrange);
266 my %clones = %{$self->{'_clones'}{$clone}};
267 my @markers;
269 if (ref($clones{'clone'}) eq 'Bio::Map::Clone') {
270 return $clones{'clone'};
273 $type = $clones{'type'} if (exists($clones{'type'}));
274 @markers = (keys %{$clones{'markers'}}) if (exists($clones{'markers'}));
275 $contig = $clones{'contig'} if (exists($clones{'contig'}));
276 $bands = $clones{'bands'} if (exists($clones{'bands'}));
277 $gel = $clones{'gel'} if (exists($clones{'gel'}));
278 $group = $clones{'group'} if (exists($clones{'group'}));
279 $remark = $clones{'remark'} if (exists($clones{'remark'}));
281 $fp_number = $clones{'fp_number'} if (exists($clones{'fp_number'}));
282 $fpc_remark = $clones{'fpc_remark'} if (exists($clones{'fpc_remark'}));
284 $sequence_type = $clones{'sequence_type'}
285 if (exists($clones{'sequence_type'}));
286 $sequence_status = $clones{'sequence_status'}
287 if (exists($clones{'sequence_status'} ));
289 @amatch = (keys %{$clones{'matcha'}}) if (exists($clones{'matcha'}));
290 @ematch = (keys %{$clones{'matche'}}) if (exists($clones{'matche'}));
291 @pmatch = (keys %{$clones{'matchp'}}) if (exists($clones{'matchp'}));
293 $startrange = $clones{'range'}{'start'}
294 if (exists($clones{'range'}{'start'}));
295 $endrange = $clones{'range'}{'end'}
296 if (exists($clones{'range'}{'end'}));
298 #*** why doesn't it call Bio::Map::Clone->new ? Seems dangerous...
299 my $cloneobj = bless( {
300 _name => $clone,
301 _markers => \@markers,
302 _contig => $contig,
303 _type => $type,
304 _bands => $bands,
305 _gel => $gel,
306 _group => $group,
307 _remark => $remark,
308 _fpnumber => $fp_number,
309 _sequencetype => $sequence_type,
310 _sequencestatus => $sequence_status,
311 _fpcremark => $fpc_remark,
312 _matche => \@ematch,
313 _matcha => \@amatch,
314 _matchp => \@pmatch,
315 _range => Bio::Range->new(-start => $startrange,
316 -end => $endrange),
317 }, 'Bio::Map::Clone');
319 $self->{'_clones'}{$clone}{'clone'} = $cloneobj;
320 return $cloneobj;
323 =head2 each_markerid
325 Title : each_markerid
326 Usage : my @markers = $map->each_markerid();
327 Function: returns list of marker names
328 Returns : list of marker names
329 Args : none
331 =cut
333 sub each_markerid {
334 my ($self) = @_;
335 return keys (%{$self->{'_markers'}});
338 =head2 get_markerobj
340 Title : get_markerobj
341 Usage : my $markerobj = $map->get_markerobj('MARKERA');
342 Function: returns an object of the marker given in the argument
343 Returns : object of the marker
344 Args : scalar representing the marker name
346 =cut
348 sub get_markerobj {
349 my ($self,$marker) = @_;
351 return 0 if(!defined($marker));
352 return if($marker eq "");
353 return if(!exists($self->{'_markers'}{$marker}));
355 my ($global,$framework,$group,$anchor,$remark,$type,$linkage,$subgroup);
356 my %mkr = %{$self->{'_markers'}{$marker}};
358 return $mkr{'marker'} if (ref($mkr{'marker'}) eq 'Bio::Map::FPCMarker');
360 $type = $mkr{'type'} if(exists($mkr{'type'}));
361 $global = $mkr{'global'} if(exists($mkr{'global'} ));
362 $framework = $mkr{'framework'} if(exists($mkr{'framework'}));
363 $anchor = $mkr{'anchor'} if(exists($mkr{'anchor'}));
364 $group = $mkr{'group'} if(exists($mkr{'group'}));
365 $subgroup = $mkr{'subgroup'} if(exists($mkr{'subgroup'}));
366 $remark = $mkr{'remark'} if(exists($mkr{'remark'}));
368 my %clones = %{$mkr{'clones'}};
369 my %contigs = %{$mkr{'contigs'}};
371 my %markerpos = %{$mkr{'posincontig'}} if(exists($mkr{'posincontig'}));
373 #*** why doesn't it call Bio::Map::FPCMarker->new ? Seems dangerous...
374 my $markerobj = bless( {
375 _name => $marker,
376 _type => $type,
377 _global => $global,
378 _frame => $framework,
379 _group => $group,
380 _subgroup => $subgroup,
381 _anchor => $anchor,
382 _remark => $remark,
383 _clones => \%clones,
384 _contigs => \%contigs,
385 _position => \%markerpos,
386 }, 'Bio::Map::FPCMarker');
388 $self->{'_markers'}{$marker}{'marker'} = $markerobj;
389 return $markerobj;
392 =head2 each_contigid
394 Title : each_contigid
395 Usage : my @contigs = $map->each_contigid();
396 Function: returns a list of contigs (numbers)
397 Returns : list of contigs
398 Args : none
400 =cut
402 sub each_contigid {
403 my ($self) = @_;
404 return keys (%{$self->{'_contigs'}});
407 =head2 get_contigobj
409 Title : get_contigobj
410 Usage : my $contigobj = $map->get_contigobj('CONTIG1');
411 Function: returns an object of the contig given in the argument
412 Returns : object of the contig
413 Args : scalar representing the contig number
415 =cut
417 sub get_contigobj {
418 my ($self,$contig) = @_;
420 return 0 if(!defined($contig));
421 return if($contig eq "");
422 return if(!exists($self->{'_contigs'}{$contig}));
424 my ($group,$anchor,$uremark,$tremark,$cremark,$startrange,$endrange,
425 $linkage,$subgroup);
426 my %ctg = %{$self->{'_contigs'}{$contig}};
427 my (%position, %pos);
429 return $ctg{'contig'} if (ref($ctg{'contig'}) eq 'Bio::Map::Contig');
431 $group = $ctg{'group'} if (exists($ctg{'group'}));
432 $subgroup = $ctg{'subgroup'} if (exists($ctg{'subgroup'}));
433 $anchor = $ctg{'anchor'} if (exists($ctg{'anchor'}));
434 $cremark = $ctg{'chr_remark'} if (exists($ctg{'chr_remark'}));
435 $uremark = $ctg{'usr_remark'} if (exists($ctg{'usr_remark'}));
436 $tremark = $ctg{'trace_remark'} if (exists($ctg{'trace_remark'}));
438 $startrange = $ctg{'range'}{'start'}
439 if (exists($ctg{'range'}{'start'}));
440 $endrange = $ctg{'range'}{'end'}
441 if (exists($ctg{'range'}{'end'}));
443 my %clones = %{$ctg{'clones'}} if (exists($ctg{'clones'}));
444 my %markers = %{$ctg{'markers'}} if (exists($ctg{'markers'}));
446 my $pos = $ctg{'position'};
448 #*** why doesn't it call Bio::Map::Contig->new ? Seems dangerous...
449 my $contigobj = bless( {
450 _group => $group,
451 _subgroup => $subgroup,
452 _anchor => $anchor,
453 _markers => \%markers,
454 _clones => \%clones,
455 _name => $contig,
456 _cremark => $cremark,
457 _uremark => $uremark,
458 _tremark => $tremark,
459 _position => $pos,
460 _range => Bio::Range->new(-start => $startrange,
461 -end => $endrange),
462 }, 'Bio::Map::Contig');
464 $self->{'_contigs'}{$contig}{'contig'} = $contigobj;
465 return $contigobj;
468 =head2 matching_bands
470 Title : matching_bands
471 Usage : $self->matching_bands('cloneA','cloneB',[$tol]);
472 Function: given two clones [and tolerence], this method calculates how many
473 matching bands do they have.
474 (this method is ported directly from FPC)
475 Returns : scalar representing the number of matching bands
476 Args : names of the clones ('cloneA', 'cloneB') [Default tolerence=7]
478 =cut
480 sub matching_bands {
481 my($self,$cloneA,$cloneB,$tol) = @_;
482 my($lstart,$kband,$match,$diff,$i,$j);
484 return 0 if(!defined($cloneA) || !defined($cloneB) ||
485 !($self->core_exists()));
487 $tol = 7 if (!defined($tol));
489 my %_clones = %{$self->{'_clones'}};
491 my @bandsA = @{$_clones{$cloneA}{'bands'}};
492 my @bandsB = @{$_clones{$cloneB}{'bands'}};
494 $match = 0;
495 $lstart = 0;
497 for ($i=0; $i<scalar(@bandsA);$i++) {
498 $kband = $bandsA[$i];
499 for ($j = $lstart; $j<scalar(@bandsB); $j++) {
500 $diff = $kband - $bandsB[$j];
501 if (abs($diff) <= $tol ) {
502 $match++;
503 $lstart = $j+1;
504 last;
506 elsif ($diff < 0) {
507 $lstart = $j;
508 last;
512 return $match;
515 =head2 coincidence_score
517 Title : coincidence_score
518 Usage : $self->coincidence_score('cloneA','cloneB'[,$tol,$gellen]);
519 Function: given two clones [,tolerence and gellen], this method calculates
520 the Sulston Coincidence score.
521 (this method is ported directly from FPC)
522 Returns : scalar representing the Sulston coincidence score.
523 Args : names of the clones ('cloneA', 'cloneB')
524 [Default tol=7 gellen=3300.0]
526 =cut
528 sub coincidence_score {
529 my($self,$cloneA,$cloneB,$tol,$gellen) = @_;
531 return 0 if(!defined($cloneA) || !defined($cloneB) ||
532 !($self->core_exists()));
534 my %_clones = %{$self->{'_clones'}};
536 my $numbandsA = scalar(@{$_clones{$cloneA}{'bands'}});
537 my $numbandsB = scalar(@{$_clones{$cloneB}{'bands'}});
539 my ($nL,$nH,$m,$i,$psmn,$pp,$pa,$pb,$t,$c,$a,$n);
540 my @logfact;
541 my $score;
543 $gellen = 3300.0 if (!defined($gellen));
544 $tol = 7 if (!defined($tol));
546 if ($numbandsA > $numbandsB) {
547 $nH = $numbandsA;
548 $nL = $numbandsB;
550 else {
551 $nH = $numbandsB;
552 $nL = $numbandsA;
555 $m = $self->matching_bands($cloneA, $cloneB,$tol);
557 $logfact[0] = 0.0;
558 $logfact[1] = 0.0;
559 for ($i=2; $i<=$nL; $i++) {
560 $logfact[$i] = $logfact[$i - 1] + log($i);
563 $psmn = 1.0 - ((2*$tol)/$gellen);
565 $pp = $psmn ** $nH;
566 $pa = log($pp);
567 $pb = log(1 - $pp);
568 $t = 1e-37;
570 for ($n = $m; $n <= $nL; $n++) {
571 $c = $logfact[$nL] - $logfact[$nL - $n] - $logfact[$n];
572 $a = exp($c + ($n * $pb) + (($nL - $n) * $pa));
573 $t += $a;
576 $score = sprintf("%.e",$t);
577 return $score;
580 =head2 print_contiglist
582 Title : print_contiglist
583 Usage : $map->print_contiglist([showall]); #[Default 0]
584 Function: prints the list of contigs, markers that hit the contig, the
585 global position and whether the marker is a placement (P) or
586 a Framework (F) marker.
587 Returns : none
588 Args : [showall] [Default 0], 1 includes all the discrepant markers
590 =cut
592 sub print_contiglist{
593 my ($self,$showall) = @_;
594 my $pos;
596 $showall = 0 if (!defined($showall));
597 my %_contigs = %{$self->{'_contigs'}};
598 my %_markers = %{$self->{'_markers'}};
599 my %_clones = %{$self->{'_clones'}};
601 my @contigs = $self->each_contigid();
602 my @sortedcontigs = sort {$a <=> $b } @contigs;
604 print "\n\nContig List\n\n";
605 foreach my $contig (@sortedcontigs) {
606 my %list;
607 my %alist;
609 my $ctgAnchor = $_contigs{$contig}{'anchor'};
610 my $ctgGroup = $_contigs{$contig}{'group'};
612 my @mkr = keys ( %{$_contigs{$contig}{'markers'}} );
614 foreach my $marker (@mkr) {
615 my $mrkGroup = $_markers{$marker}{'group'};
616 my $mrkGlobal = $_markers{$marker}{'global'};
617 my $mrkFramework = $_markers{$marker}{'framework'};
618 my $mrkAnchor = $_markers{$marker}{'anchor'};
620 if($ctgGroup =~ /\d+|\w/ && $ctgGroup != 0) {
621 if ($mrkGroup eq $ctgGroup) {
622 if ($mrkFramework == 0) {
623 $pos = $mrkGlobal."P";
625 else {
626 $pos = $mrkGlobal."F";
628 $list{$marker} = $pos;
630 elsif ($showall == 1) {
631 my $chr = $self->group_abbr().$mrkGroup;
632 $alist{$marker} = $chr;
635 elsif ($showall == 1 && $ctgGroup !~ /\d+/) {
636 my $chr = $self->group_abbr().$mrkGroup;
637 $alist{$marker} = $chr;
641 my $chr = $ctgGroup;
642 $chr = $self->group_abbr().$ctgGroup if ($ctgGroup =~ /\d+|\w/);
644 if ($showall == 1 ) {
646 print " ctg$contig ", $chr, " "
647 if ($_contigs{$contig}{'group'} !~ /\d+|\w/);
649 elsif ($ctgGroup =~ /\d+|\w/ && $ctgGroup ne 0){
650 print " ctg",$contig, " ",$chr, " ";
653 while (my ($k,$v) = each %list) {
654 print "$k/$v ";
657 print "\n" if ($showall == 0 && $ctgGroup =~ /\d+|\w/ &&
658 $ctgGroup ne 0 );
660 if ($showall == 1) {
661 while (my ($k,$v) = each %alist) {
662 print "$k/$v ";
664 print "\n";
669 =head2 print_markerlist
671 Title : print_markerlist
672 Usage : $map->print_markerlist();
673 Function : prints the marker list; contig and corresponding number of
674 clones for each marker.
675 Returns : none
676 Args : none
678 =cut
680 sub print_markerlist {
681 my ($self) = @_;
683 my %_contigs = %{$self->{'_contigs'}};
684 my %_markers = %{$self->{'_markers'}};
685 my %_clones = %{$self->{'_clones'}};
687 print "Marker List\n\n";
689 foreach my $marker ($self->each_markerid()) {
690 print " ",$marker, " ";
692 my %list;
693 my %mclones = %{$_markers{$marker}{'clones'}};
695 foreach my $clone (%mclones) {
696 if (exists($_clones{$clone}{'contig'}) ) {
697 my $ctg = $_clones{$clone}{'contig'};
699 if (exists($list{$ctg})) {
700 my $clonehits = $list{$ctg};
701 $clonehits++;
702 $list{$ctg} = $clonehits;
704 else {
705 $list{$ctg} = 1;
709 while (my ($k,$v) = each %list) {
710 print "$k/$v ";
712 print "\n";
716 =head2 print_gffstyle
718 Title : print_gffstyle
719 Usage : $map->print_gffstyle([style]);
720 Function : prints GFF; either Contigwise (default) or Groupwise
721 Returns : none
722 Args : [style] default = 0 contigwise, else
723 1 groupwise (chromosome-wise).
725 =cut
727 sub print_gffstyle {
728 my ($self,$style) = @_;
730 $style = 0 if(!defined($style));
732 my %_contigs = %{$self->{'_contigs'}};
733 my %_markers = %{$self->{'_markers'}};
734 my %_clones = %{$self->{'_clones'}};
736 my $i;
737 my ($depth, $save_depth);
738 my ($x, $y);
739 my @stack;
740 my ($k, $j, $s);
741 my $pos;
742 my $contig;
744 # Calculate the position for the marker in the contig
746 my @contigs = $self->each_contigid();
747 my @sortedcontigs = sort {$a <=> $b } @contigs;
748 my $offset = 0;
749 my %gffclones;
750 my %gffcontigs;
751 my %gffmarkers;
752 my $basepair = 4096;
754 foreach my $contig (@sortedcontigs) {
755 if($_contigs{$contig}{'range'} ) {
756 $offset = $_contigs{$contig}{'range'}{'start'};
758 if ($offset <= 0){
759 $offset = $offset * -1;
760 $gffcontigs{$contig}{'start'} = 1;
761 $gffcontigs{$contig}{'end'} =
762 ($_contigs{$contig}{'range'}{'end'} +
763 $offset ) * $basepair + 1;
765 else {
766 $offset = 0;
767 $gffcontigs{$contig}{'start'} =
768 $_contigs{$contig}{'range'}{'start'} * $basepair;
769 $gffcontigs{$contig}{'end'} =
770 $_contigs{$contig}{'range'}{'end'} * $basepair;
773 else {
774 $gffcontigs{$contig}{'start'} = 1;
775 $gffcontigs{$contig}{'end'} = 1;
778 my @clones = keys %{$_contigs{$contig}{'clones'}};
779 foreach my $clone (@clones) {
780 if(exists ($_clones{$clone}{'range'}) ) {
781 my $gffclone = $clone;
783 $gffclone =~ s/sd1$//;
785 $gffclones{$gffclone}{'start'} =
786 (($_clones{$clone}{'range'}{'start'} + $offset) *
787 $basepair + 1);
789 $gffclones{$gffclone}{'end'} =
790 (($_clones{$clone}{'range'}{'end'}
791 + $offset) * $basepair + 1);
794 if(!$contig) {
795 my %markers = %{$_clones{$clone}{'markers'}}
796 if (exists($_clones{$clone}{'markers'}));
798 while (my ($k,$v) = each %markers) {
799 $gffmarkers{$contig}{$k} =
800 ( ( $_clones{$clone}{'range'}{'start'} +
801 $_clones{$clone}{'range'}{'end'} ) / 2 ) *
802 $basepair + 1 ;
807 if($contig) {
808 my %markers = %{$_contigs{$contig}{'markers'}}
809 if (exists($_contigs{$contig}{'markers'}));
811 while (my ($k,$v) = each %markers) {
812 $gffmarkers{$contig}{$k} = ($v + $offset) * $basepair + 1;
817 if (!$style) {
818 foreach my $contig (@sortedcontigs) {
820 if(exists ($_contigs{$contig}{'range'} ) ) {
821 print join("\t","ctg$contig","assembly","contig",
822 $gffcontigs{$contig}{'start'},
823 $gffcontigs{$contig}{'end'},".",".",".",
824 "Sequence \"ctg$contig\"; Name \"ctg$contig\"\n"
828 my @clones = (keys %{$_contigs{$contig}{'clones'}} );
830 foreach my $clone (@clones) {
831 if(exists ($_clones{$clone}{'range'}) ) {
832 print join("\t","ctg$contig","FPC");
834 my $type = $_clones{$clone}{'type'};
836 if($clone =~ /sd1$/) {
837 $clone =~ s/sd1$//;
838 $type = "sequenced";
840 print join ("\t","\t$type",$gffclones{$clone}{'start'},
841 $gffclones{$clone}{'end'},".",".",".",
842 "$type \"$clone\"; Name \"$clone\"");
844 my @markers = keys %{$_clones{$clone}{'markers'}};
845 print "; Marker_hit" if (scalar(@markers));
847 foreach my $mkr(@markers) {
848 if (exists($_markers{$mkr}{'framework'})) {
849 print " \"$mkr ",$_markers{$mkr}{'group'}," ",
850 $_markers{$mkr}{'global'},"\"";
852 else {
853 print " \"$mkr 0 0\"";
856 print "; Contig_hit \"",$_clones{$clone}{'contig'},"\" "
857 if (defined($_clones{$clone}{'contig'}));
859 print "\n";
862 if (exists ($_contigs{$contig}{'markers'}) ) {
863 my %list = %{$_contigs{$contig}{'markers'}};
865 while (my ($k,$v) = each %list) {
866 print "ctg", $contig, "\tFPC\t";
867 my $position = $gffmarkers{$contig}{$k};
869 my $type = "marker";
871 $type = "electronicmarker"
872 if ($_markers{$k}{'type'} eq "eMRK");
874 if( exists($_markers{$k}{'framework'})) {
875 $type = "frameworkmarker"
876 if($_markers{$k}{'framework'} == 1);
878 $type = "placementmarker"
879 if($_markers{$k}{'framework'} == 0);
882 print join ("\t","$type",$position,$position,".",".",
883 ".","$type \"$k\"; Name \"$k\"");
885 my @clonelist;
886 my @clones = keys %{$_markers{$k}{'clones'}};
888 foreach my $cl (@clones) {
889 push (@clonelist, $cl)
890 if($_clones{$cl}{'contig'} == $contig);
893 $" = " ";
894 print("; Contig_hit \"ctg$contig - ",scalar(@clonelist),
895 "\" (@clonelist)\n");
900 else {
901 my %_groups;
902 my $margin = 2 * $basepair;
903 my $displacement = 0;
904 my @grouplist;
906 foreach my $contig (@sortedcontigs) {
907 my $recordchr;
908 my $chr = $_contigs{$contig}{'group'};
909 $chr = 0 if ($chr !~ /\d+|\w+/);
911 $recordchr->{group} = $chr;
912 $recordchr->{contig} = $contig;
913 $recordchr->{position} = $_contigs{$contig}{'position'};
915 push @grouplist, $recordchr;
918 my @chr = keys (%{$_groups{'group'}});
919 my @sortedchr;
921 if ($self->group_type eq 'Chromosome') {
922 @sortedchr = sort { $a->{'group'} <=> $b->{'group'}
924 $a->{'contig'} <=> $b->{'contig'}
925 } @grouplist;
927 else {
928 @sortedchr = sort { $a->{'group'} cmp $b->{'group'}
930 $a->{'contig'} cmp $b->{'contig'}
931 } @grouplist;
933 my $lastchr = -1;
934 my $chrend = 0;
936 foreach my $chr (@sortedchr) {
937 my $chrname = $self->group_abbr().$chr->{'group'};
939 if ($lastchr eq -1 || $chr->{'group'} ne $lastchr ) {
940 $lastchr = $chr->{'group'} if ($lastchr eq -1);
941 $displacement = 0;
943 # caluclate the end position of the contig
944 my $ctgcount = 0;
945 my $prevchr = 0;
946 $chrend = 0;
948 if ($chr->{contig} != 0) {
949 foreach my $ch (@sortedchr) {
950 if ($ch->{'group'} eq $chr->{'group'}) {
951 if($ch->{'contig'} != 0) {
952 my $ctg = $ch->{'contig'}
953 if($ch->{'contig'} != 0);
955 $chrend += $gffcontigs{$ctg}->{'end'};
956 ++$ctgcount;
960 $chrend += ($ctgcount-1) * $margin;
962 else {
963 $chrend = $gffcontigs{'0'}->{'end'};
966 $chrname = $self->group_abbr()."ctg0"
967 if ($chr->{'contig'} == 0);
969 print join ("\t", $chrname,"assembly","Chromosome",1,
970 "$chrend",".",".",".",
971 "Sequence \"$chrname\"; Name \"$chrname\"\n");
974 print join ("\t", $chrname,"assembly","Chromosome",1,
975 "$chrend",".",".",".",
976 "Sequence \"$chrname\"; Name \"$chrname\"\n")
977 if ($chr->{'group'} ne $lastchr && $chr->{'group'} eq 0 );
979 $lastchr = $chr->{'group'};
980 $lastchr = -1 if ($chr->{'contig'} == 0);
982 my $contig = $chr->{'contig'};
984 if(exists ($_contigs{$contig}{'range'} ) ) {
986 print join ("\t",$chrname, "FPC","contig",
987 $gffcontigs{$contig}{'start'}+$displacement,
988 $gffcontigs{$contig}{'end'}+$displacement,
989 ".",".",".",
990 "contig \"ctg$contig\"; Name \"ctg$contig\"\n");
993 my @clones = (keys %{$_contigs{$contig}{'clones'}} );
994 foreach my $clone (@clones) {
995 if(exists ($_clones{$clone}{'range'}) ) {
996 print join ("\t",$chrname,"FPC");
997 my $type = $_clones{$clone}{'type'};
999 if ($clone =~ /sd1$/) {
1000 $clone =~ s/sd1$//;
1001 $type = "sequenced";
1004 print join ("\t","\t$type",$gffclones{$clone}{'start'}
1005 +$displacement,$gffclones{$clone}{'end'}
1006 +$displacement,".",".",".",
1007 "$type \"$clone\"; Name \"$clone\"");
1009 my @markers = keys %{$_clones{$clone}{'markers'}};
1010 print "; Marker_hit" if (scalar(@markers));
1012 foreach my $mkr(@markers) {
1013 if (exists($_markers{$mkr}{'framework'})) {
1014 print " \"$mkr ",$_markers{$mkr}{'group'}," ",
1015 $_markers{$mkr}{'global'},"\"";
1017 else {
1018 print (" \"$mkr 0 0\"");
1021 print "; Contig_hit \"",$_clones{$clone}{'contig'},"\" "
1022 if (defined($_clones{$clone}{'contig'}));
1024 print "\n";
1027 if (exists ($_contigs{$contig}{'markers'}) ) {
1028 my %list = %{$_contigs{$contig}{'markers'}};
1030 while (my ($k,$v) = each %list) {
1031 print join ("\t",$chrname,"FPC");
1032 my $type = "marker";
1034 $type = "electronicmarker"
1035 if ($_markers{$k}{'type'} eq "eMRK");
1037 if( exists($_markers{$k}{'framework'})) {
1038 $type = "frameworkmarker"
1039 if($_markers{$k}{'framework'} == 1);
1041 $type = "placementmarker"
1042 if($_markers{$k}{'framework'} == 0);
1045 print join ("\t","\t$type",$gffmarkers{$contig}{$k}
1046 + $displacement,$gffmarkers{$contig}{$k}
1047 + $displacement,".",".",".",
1048 "$type \"$k\"; Name \"$k\"");
1050 my @clonelist;
1051 my @clones = keys %{$_markers{$k}{'clones'}};
1053 foreach my $cl (@clones) {
1054 push (@clonelist, $cl)
1055 if($_clones{$cl}{'contig'} == $contig);
1058 $" = " ";
1059 print("; Contig_hit \"ctg$contig - ",
1060 scalar(@clonelist),"\" (@clonelist)\n");
1063 $displacement += $margin + $gffcontigs{$contig}{'end'};
1068 =head2 _calc_markerposition
1070 Title : _calc_markerposition
1071 Usage : $map->_calc_markerposition();
1072 Function: Calculates the position of the marker in the contig
1073 Returns : none
1074 Args : none
1076 =cut
1078 sub _calc_markerposition {
1079 my ($self) = @_;
1080 my %_contigs = %{$self->{'_contigs'}};
1081 my %_markers = %{$self->{'_markers'}};
1082 my %_clones = %{$self->{'_clones'}};
1084 my $i;
1085 my ($depth, $save_depth);
1086 my ($x, $y);
1087 my @stack;
1088 my ($k, $j, $s);
1089 my $pos;
1090 my $contig;
1092 # Calculate the position for the marker in the contig
1094 my @contigs = $self->each_contigid();
1095 my @sortedcontigs = sort {$a <=> $b } @contigs;
1096 my $offset;
1097 my %gffclones;
1098 my %gffcontigs;
1100 foreach my $marker ($self->each_markerid()) {
1101 my (@ctgmarker, @sortedctgmarker);
1103 my @clones = (keys %{$_markers{$marker}{'clones'}})
1104 if (exists ($_markers{$marker}{'clones'} ));
1106 foreach my $clone (@clones) {
1107 my $record;
1108 $record->{contig} = $_clones{$clone}{'contig'};
1109 $record->{start} = $_clones{$clone}{'range'}{'start'};
1110 $record->{end} = $_clones{$clone}{'range'}{'end'};
1111 push @ctgmarker,$record;
1114 # sorting by contig and left position
1115 @sortedctgmarker = sort { $a->{'contig'} <=> $b->{'contig'}
1117 $b->{'start'} <=> $a->{'start'}
1118 } @ctgmarker;
1120 my $ctg = -1;
1122 for ($i=0; $i < scalar(@sortedctgmarker); $i++) {
1123 if ($ctg != $sortedctgmarker[$i]->{'contig'}) {
1124 if ($ctg == -1) {
1125 $ctg = $sortedctgmarker[$i]->{'contig'};
1127 else {
1128 if ($depth > $save_depth){
1129 $pos = ($x + $y) >> 1;
1130 $_contigs{$ctg}{'markers'}{$marker} = $pos;
1131 $_markers{$marker}{'posincontig'}{$ctg} = $pos;
1135 $ctg = $sortedctgmarker[$i]->{'contig'};
1136 $x = $sortedctgmarker[$i]->{'start'};
1137 $y = $sortedctgmarker[$i]->{'end'};
1138 $stack[0] = $y;
1140 $pos = ($x + $y) >> 1;
1141 $_contigs{$ctg}{'markers'}{$marker} = $pos;
1142 $_markers{$marker}{'posincontig'}{$ctg} = $pos;
1144 $depth = $save_depth = 1;
1146 elsif ($sortedctgmarker[$i] <= $y) {
1147 $stack[$depth++] = $sortedctgmarker[$i]->{'end'};
1148 # MAX
1149 if ($x < $sortedctgmarker[$i]->{'start'} ) {
1150 $x = $sortedctgmarker[$i]->{'start'};
1152 # MIN
1153 if ($y > $sortedctgmarker[$i]->{'end'}) {
1154 $y = $sortedctgmarker[$i]->{'end'};
1157 else {
1158 if ($depth > $save_depth) {
1159 $save_depth = $depth;
1160 $pos = ($x + $y) >> 1;
1161 $_contigs{$ctg}{'markers'}{$marker} = $pos;
1162 $_markers{$marker}{'posincontig'}{$ctg} = $pos;
1165 $x = $sortedctgmarker[$i]->{'start'};
1166 $y = $sortedctgmarker[$i]->{'end'};
1167 $stack[$depth++] = $y;
1169 for($j=-1, $k=0, $s=0; $s<$depth; $s++) {
1170 if ($stack[$s] <$x) {
1171 $stack[$s] = -1;
1172 $j = $s if ($j == -1);
1174 else {
1175 $k++;
1176 # MIN
1177 $y = $stack[$s] if ($y > $stack[$s]);
1178 if ($stack[$j] == -1) {
1179 $stack[$j] = $stack[$s];
1180 $stack[$s] = -1;
1181 while ($stack[$j] != -1) {$j++;}
1183 else {
1184 $j = $s;
1187 $depth = $k;
1190 if ($depth > $save_depth) {
1191 $pos = ($x + $y) >> 1;
1192 $_contigs{$ctg}{'markers'}{$marker} = $pos;
1193 $_markers{$marker}{'posincontig'}{$ctg} = $pos;
1199 =head2 _calc_contigposition
1201 Title : _calc_contigposition
1202 Usage : $map->_calc_contigposition();
1203 Function: calculates the position of the contig in the group
1204 Returns : none
1205 Args : none
1207 =cut
1209 sub _calc_contigposition{
1210 my ($self) = @_;
1212 my %_contigs = %{$self->{'_contigs'}};
1213 my %_markers = %{$self->{'_markers'}};
1214 my %_clones = %{$self->{'_clones'}};
1216 my @contigs = $self->each_contigid();
1217 my @sortedcontigs = sort {$a <=> $b } @contigs;
1219 foreach my $contig (@sortedcontigs) {
1220 my $position = 0;
1221 my $group;
1223 if (exists($_contigs{$contig}{'group'}) ) {
1225 my %weightedmarkers;
1226 my @mkrs = keys (%{$_contigs{$contig}{'markers'}})
1227 if (exists($_contigs{$contig}{'markers'})) ;
1229 my $chr = $_contigs{$contig}{'group'};
1230 $chr = 0 if ($_contigs{$contig}{'group'} =~ /\?/);
1232 foreach my $mkr (@mkrs) {
1233 if (exists($_markers{$mkr}{'group'})) {
1234 if ( $_markers{$mkr}{'group'} == $chr ) {
1235 my @mkrclones = keys( %{$_markers{$mkr}{'clones'}});
1236 my $clonescount = 0;
1237 foreach my $clone (@mkrclones) {
1238 ++$clonescount
1239 if ($_clones{$clone}{'contig'} == $contig);
1241 $weightedmarkers{$_markers{$mkr}{'global'}} =
1242 $clonescount;
1247 my $weightedctgsum = 0;
1248 my $totalhits = 0;
1250 while (my ($mpos,$hits) = each %weightedmarkers) {
1251 $weightedctgsum += ($mpos * $hits);
1252 $totalhits += $hits;
1255 $position = sprintf("%.2f",$weightedctgsum / $totalhits)
1256 if ($totalhits != 0);
1258 $_contigs{$contig}{'position'} = $position;
1263 =head2 _calc_contiggroup
1265 Title : _calc_contiggroup
1266 Usage : $map->_calc_contiggroup();
1267 Function: calculates the group of the contig
1268 Returns : none
1269 Args : none
1271 =cut
1273 sub _calc_contiggroup {
1274 my ($self) = @_;
1275 my %_contig = %{$self->{'_contigs'}};
1276 my @contigs = $self->each_contigid();
1278 foreach my $ctg (@contigs) {
1279 my $chr = floor($ctg/1000);
1280 $_contig{$ctg}{'group'} = $chr;
1284 =head2 _setI<E<lt>TypeE<gt>>Ref
1286 Title : _set<Type>Ref
1287 Usage : These are used for initializing the reference of the hash in
1288 Bio::MapIO (fpc.pm) to the corresponding hash in Bio::Map
1289 (physical.pm). Should be used only from Bio::MapIO System.
1290 $map->setCloneRef(\%_clones);
1291 $map->setMarkerRef(\%_markers);
1292 $map->setContigRef(\%_contigs);
1293 Function: sets the hash references to the corresponding hashes
1294 Returns : none
1295 Args : reference of the hash.
1297 =cut
1299 sub _setCloneRef {
1300 my ($self, $ref) = @_;
1301 %{$self->{'_clones'}} = %{$ref};
1304 sub _setMarkerRef {
1305 my ($self, $ref) = @_;
1306 %{$self->{'_markers'}} = %{$ref};
1309 sub _setContigRef {
1310 my ($self, $ref) = @_;
1311 %{$self->{'_contigs'}} = %{$ref};