Mercurial > repos > mahtabm > ensembl
comparison variant_effect_predictor/Bio/Structure/Entry.pm @ 0:1f6dce3d34e0
Uploaded
| author | mahtabm | 
|---|---|
| date | Thu, 11 Apr 2013 02:01:53 -0400 | 
| parents | |
| children | 
   comparison
  equal
  deleted
  inserted
  replaced
| -1:000000000000 | 0:1f6dce3d34e0 | 
|---|---|
| 1 # $Id: Entry.pm,v 1.17 2002/10/22 07:38:44 lapp Exp $ | |
| 2 # | |
| 3 # bioperl module for Bio::Structure::Entry | |
| 4 # | |
| 5 # Cared for by Kris Boulez <kris.boulez@algonomics.com> | |
| 6 # | |
| 7 # Copyright Kris Boulez | |
| 8 # | |
| 9 # You may distribute this module under the same terms as perl itself | |
| 10 | |
| 11 # POD documentation - main docs before the code | |
| 12 | |
| 13 =head1 NAME | |
| 14 | |
| 15 Bio::Structure::Entry - Bioperl structure Object, describes the whole entry | |
| 16 | |
| 17 =head1 SYNOPSIS | |
| 18 | |
| 19 #add synopsis here | |
| 20 | |
| 21 =head1 DESCRIPTION | |
| 22 | |
| 23 This object stores a whole Bio::Structure entry. It can consist of one or | |
| 24 more models (Bio::Structure::Model), which in turn consist of one or more | |
| 25 chains (Bio::Structure::Chain). A chain is composed of residues | |
| 26 (Bio::Structure::Residue) and a residue consists of atoms (Bio::Structure::Atom) | |
| 27 If no specific model or chain is chosen, the first one is choosen. | |
| 28 | |
| 29 =head1 FEEDBACK | |
| 30 | |
| 31 =head2 Mailing Lists | |
| 32 | |
| 33 User feedback is an integral part of the evolution of this and other | |
| 34 Bioperl modules. Send your comments and suggestions preferably to one | |
| 35 of the Bioperl mailing lists. Your participation is much appreciated. | |
| 36 | |
| 37 bioperl-l@bioperl.org - General discussion | |
| 38 http://bio.perl.org/MailList.html - About the mailing lists | |
| 39 | |
| 40 =head2 Reporting Bugs | |
| 41 | |
| 42 Report bugs to the Bioperl bug tracking system to help us keep track | |
| 43 the bugs and their resolution. Bug reports can be submitted via email | |
| 44 or the web: | |
| 45 | |
| 46 bioperl-bugs@bio.perl.org | |
| 47 http://bugzilla.bioperl.org/ | |
| 48 | |
| 49 =head1 AUTHOR - Kris Boulez | |
| 50 | |
| 51 Email kris.boulez@algonomics.com | |
| 52 | |
| 53 =head1 APPENDIX | |
| 54 | |
| 55 The rest of the documentation details each of the object methods. Internal methods are usually preceded with a _ | |
| 56 | |
| 57 =cut | |
| 58 | |
| 59 | |
| 60 # Let the code begin... | |
| 61 | |
| 62 package Bio::Structure::Entry; | |
| 63 use vars qw(@ISA); | |
| 64 use strict; | |
| 65 | |
| 66 use Bio::Root::Root; | |
| 67 use Bio::Structure::StructureI; | |
| 68 use Bio::Structure::Model; | |
| 69 use Bio::Structure::Chain; | |
| 70 use Bio::Annotation::Collection; | |
| 71 use Tie::RefHash; | |
| 72 | |
| 73 @ISA = qw(Bio::Root::Root Bio::Structure::StructureI); | |
| 74 | |
| 75 | |
| 76 =head2 new() | |
| 77 | |
| 78 Title : new() | |
| 79 Usage : $struc = Bio::Structure::Entry->new( | |
| 80 -id => 'structure_id', | |
| 81 ); | |
| 82 | |
| 83 Function: Returns a new Bio::Structure::Entry object from basic | |
| 84 constructors. Probably most called from Bio::Structure::IO. | |
| 85 Returns : a new Bio::Structure::Model object | |
| 86 | |
| 87 =cut | |
| 88 | |
| 89 sub new { | |
| 90 my ($class, @args) = @_; | |
| 91 my $self = $class->SUPER::new(@args); | |
| 92 | |
| 93 my($id, $model, $chain, $residue ) = | |
| 94 $self->_rearrange([qw( | |
| 95 ID | |
| 96 MODEL | |
| 97 CHAIN | |
| 98 RESIDUE | |
| 99 )], | |
| 100 @args); | |
| 101 | |
| 102 # where to store parent->child relations (1 -> 1..n) | |
| 103 # value to this hash will be an array ref | |
| 104 # by using Tie::RefHash we can store references in this hash | |
| 105 $self->{'p_c'} = (); | |
| 106 tie %{ $self->{'p_c'} } , "Tie::RefHash"; | |
| 107 | |
| 108 # where to store child->parent relations (1 -> 1) | |
| 109 $self->{'c_p'} = (); | |
| 110 tie %{ $self->{'c_p'} } , "Tie::RefHash"; | |
| 111 | |
| 112 $id && $self->id($id); | |
| 113 | |
| 114 $self->{'model'} = []; | |
| 115 $model && $self->model($model); | |
| 116 | |
| 117 | |
| 118 if($chain) { | |
| 119 if ( ! defined($self->model) ) { # no model yet, create default one | |
| 120 $self->_create_default_model; | |
| 121 } | |
| 122 for my $m ($self->model) { # add this chain on all models | |
| 123 $m->chain($chain); | |
| 124 } | |
| 125 } | |
| 126 | |
| 127 $residue && $self->residue($residue); | |
| 128 | |
| 129 # taken from Bio::Seq (or should we just inherit Bio::Seq and override some methods) | |
| 130 my $ann = Bio::Annotation::Collection->new; | |
| 131 $self->annotation($ann); | |
| 132 | |
| 133 return $self; | |
| 134 } | |
| 135 | |
| 136 | |
| 137 =head2 model() | |
| 138 | |
| 139 Title : model | |
| 140 Function: Connects a (or a list of) Model objects to a Bio::Structure::Entry. | |
| 141 To add a Model (and keep the existing ones) use add_model() | |
| 142 It returns a list of Model objects. | |
| 143 Returns : list of Bio::Structure::Model objects | |
| 144 Args : One Model or a reference to an array of Model objects | |
| 145 | |
| 146 =cut | |
| 147 | |
| 148 sub model { | |
| 149 my ($self, $model) = @_; | |
| 150 | |
| 151 if( defined $model) { | |
| 152 if( (ref($model) eq "ARRAY") || | |
| 153 ($model->isa('Bio::Structure::Model')) ) { | |
| 154 # remove existing ones, tell they've become orphan | |
| 155 my @obj = $self->model; | |
| 156 if (@obj) { | |
| 157 for my $m (@obj) { | |
| 158 $self->_remove_from_graph($m); | |
| 159 $self->{'model'} = []; | |
| 160 } | |
| 161 } | |
| 162 # add the new ones | |
| 163 $self->add_model($self,$model); | |
| 164 } | |
| 165 else { | |
| 166 $self->throw("Supplied a $model to model, we want a Bio::Structure::Model or a list of these\n"); | |
| 167 } | |
| 168 } | |
| 169 # give back list of models via general get method | |
| 170 $self->get_models($self); | |
| 171 } | |
| 172 | |
| 173 | |
| 174 | |
| 175 =head2 add_model() | |
| 176 | |
| 177 Title : add_model | |
| 178 Usage : $structure->add_model($model); | |
| 179 Function: Adds a (or a list of) Model objects to a Bio::Structure::Entry. | |
| 180 Returns : | |
| 181 Args : One Model or a reference to an array of Model objects | |
| 182 | |
| 183 =cut | |
| 184 | |
| 185 sub add_model { | |
| 186 my($self,$entry,$model) = @_; | |
| 187 | |
| 188 # if only one argument and it's a model, change evrything one place | |
| 189 # this is for people calling $entry->add_model($model); | |
| 190 if ( !defined $model && ref($entry) =~ /^Bio::Structure::Model/) { | |
| 191 $model = $entry; | |
| 192 $entry = $self; | |
| 193 } | |
| 194 # $self and $entry are the same here, but it's used for uniformicity | |
| 195 if ( !defined($entry) || ref($entry) !~ /^Bio::Structure::Entry/) { | |
| 196 $self->throw("first argument to add_model needs to be a Bio::Structure::Entry object\n"); | |
| 197 } | |
| 198 if (defined $model) { | |
| 199 if (ref($model) eq "ARRAY") { | |
| 200 # if the user passed in a reference to an array | |
| 201 for my $m ( @{$model} ) { | |
| 202 if( ! $m->isa('Bio::Structure::Model') ) { | |
| 203 $self->throw("$m is not a Model\n"); | |
| 204 } | |
| 205 if ( $self->_parent($m) ) { | |
| 206 $self->throw("$m already assigned to a parent\n"); | |
| 207 } | |
| 208 push @{$self->{'model'}}, $m; | |
| 209 # create a stringified version of our ref | |
| 210 # not used untill we get symbolic ref working | |
| 211 #my $str_ref = "$self"; | |
| 212 #$m->_grandparent($str_ref); | |
| 213 } | |
| 214 } | |
| 215 elsif ( $model->isa('Bio::Structure::Model') ) { | |
| 216 if ( $self->_parent($model) ) { # already assigned to a parent | |
| 217 $self->throw("$model already assigned\n"); | |
| 218 } | |
| 219 push @{$self->{'model'}}, $model; | |
| 220 # create a stringified version of our ref | |
| 221 #my $str_ref = "$self"; | |
| 222 #$model->_grandparent($str_ref); | |
| 223 } | |
| 224 else { | |
| 225 $self->throw("Supplied a $model to add_model, we want a Model or list of Models\n"); | |
| 226 } | |
| 227 } | |
| 228 | |
| 229 my $array_ref = $self->{'model'}; | |
| 230 return $array_ref ? @{$array_ref} : (); | |
| 231 } | |
| 232 | |
| 233 | |
| 234 =head2 get_models() | |
| 235 | |
| 236 Title : get_models | |
| 237 Usage : $structure->get_models($structure); | |
| 238 Function: general get method for models attached to an Entry | |
| 239 Returns : a list of models attached to this entry | |
| 240 Args : an Entry | |
| 241 | |
| 242 =cut | |
| 243 | |
| 244 sub get_models { | |
| 245 my ($self, $entry) = @_; | |
| 246 | |
| 247 # self and entry can be the same | |
| 248 if ( !defined $entry) { | |
| 249 $entry = $self; | |
| 250 } | |
| 251 # pass through to add_model | |
| 252 $self->add_model($entry); | |
| 253 } | |
| 254 | |
| 255 | |
| 256 | |
| 257 =head2 id() | |
| 258 | |
| 259 Title : id | |
| 260 Usage : $entry->id("identity"); | |
| 261 Function: Gets/sets the ID | |
| 262 Returns : | |
| 263 Args : | |
| 264 | |
| 265 =cut | |
| 266 | |
| 267 sub id { | |
| 268 my ($self, $value) = @_; | |
| 269 if (defined $value) { | |
| 270 $self->{'id'} = $value; | |
| 271 } | |
| 272 return $self->{'id'}; | |
| 273 } | |
| 274 | |
| 275 | |
| 276 =head2 chain() | |
| 277 | |
| 278 Title : chain | |
| 279 Usage : @chains = $structure->chain($chain); | |
| 280 Function: Connects a (or a list of) Chain objects to a Bio::Structure::Entry. | |
| 281 Returns : list of Bio::Structure::Residue objects | |
| 282 Args : One Residue or a reference to an array of Residue objects | |
| 283 | |
| 284 =cut | |
| 285 | |
| 286 sub chain { | |
| 287 my ($self, $chain) = @_; | |
| 288 | |
| 289 if ( ! $self->model ) { | |
| 290 $self->_create_default_model; | |
| 291 } | |
| 292 my @models = $self->model; | |
| 293 my $first_model = $models[0]; | |
| 294 | |
| 295 if ( defined $chain) { | |
| 296 | |
| 297 if( (ref($chain) eq "ARRAY") || | |
| 298 ($chain->isa('Bio::Structure::Chain')) ) { | |
| 299 # remove existing ones, tell they've become orphan | |
| 300 my @obj = $self->get_chains($first_model); | |
| 301 if (@obj) { | |
| 302 for my $c (@obj) { | |
| 303 $self->_remove_from_graph($c); | |
| 304 } | |
| 305 } | |
| 306 # add the new ones | |
| 307 $self->add_chain($first_model,$chain); | |
| 308 } | |
| 309 else { | |
| 310 $self->throw("Supplied a $chain to chain, we want a Bio::Structure::Chain or a list of these\n"); | |
| 311 } | |
| 312 } | |
| 313 $self->get_chains($first_model); | |
| 314 } | |
| 315 | |
| 316 | |
| 317 =head2 add_chain() | |
| 318 | |
| 319 Title : add_chain | |
| 320 Usage : @chains = $structure->add_chain($add_chain); | |
| 321 Function: Adds a (or a list of) Chain objects to a Bio::Structure::Entry. | |
| 322 Returns : | |
| 323 Args : | |
| 324 | |
| 325 =cut | |
| 326 | |
| 327 sub add_chain { | |
| 328 my($self, $model, $chain) = @_; | |
| 329 | |
| 330 if (ref($model) !~ /^Bio::Structure::Model/) { | |
| 331 $self->throw("add_chain: first argument needs to be a Model object ($model)\n"); | |
| 332 } | |
| 333 if (defined $chain) { | |
| 334 if (ref($chain) eq "ARRAY") { | |
| 335 # if the user passed in a reference to an array | |
| 336 for my $c ( @{$chain} ) { | |
| 337 if( ! $c->isa('Bio::Structure::Chain') ) { | |
| 338 $self->throw("$c is not a Chain\n"); | |
| 339 } | |
| 340 if ( $self->_parent($c) ) { | |
| 341 $self->throw("$c already assigned to a parent\n"); | |
| 342 } | |
| 343 $self->_parent($c, $model); | |
| 344 $self->_child($model, $c); | |
| 345 # stringify $self ref | |
| 346 #my $str_ref = "$self"; | |
| 347 #$c->_grandparent($str_ref); | |
| 348 } | |
| 349 } | |
| 350 elsif ( $chain->isa('Bio::Structure::Chain') ) { | |
| 351 if ( $self->_parent($chain) ) { # already assigned to parent | |
| 352 $self->throw("$chain already assigned to a parent\n"); | |
| 353 } | |
| 354 $self->_parent($chain,$model); | |
| 355 $self->_child($model, $chain); | |
| 356 # stringify $self ref | |
| 357 #my $str_ref = "$self"; | |
| 358 #$chain->_grandparent($str_ref); | |
| 359 } | |
| 360 else { | |
| 361 $self->throw("Supplied a $chain to add_chain, we want a Chain or list of Chains\n"); | |
| 362 } | |
| 363 } | |
| 364 my $array_ref = $self->_child($model); | |
| 365 return $array_ref ? @{$array_ref} : (); | |
| 366 } | |
| 367 | |
| 368 | |
| 369 =head2 get_chains() | |
| 370 | |
| 371 Title : get_chains | |
| 372 Usage : $entry->get_chains($model); | |
| 373 Function: general get method for chains attached to a Model | |
| 374 Returns : a list of chains attached to this model | |
| 375 Args : a Model | |
| 376 | |
| 377 =cut | |
| 378 | |
| 379 sub get_chains { | |
| 380 my ($self, $model) = @_; | |
| 381 | |
| 382 if (! defined $model) { | |
| 383 $model = ($self->get_models)[0]; | |
| 384 } | |
| 385 # pass through to add_chain | |
| 386 $self->add_chain($model); | |
| 387 } | |
| 388 | |
| 389 | |
| 390 =head2 residue() | |
| 391 | |
| 392 Title : residue | |
| 393 Usage : @residues = $structure->residue($residue); | |
| 394 Function: Connects a (or a list of) Residue objects to a Bio::Structure::Entry. | |
| 395 Returns : list of Bio::Structure::Residue objects | |
| 396 Args : One Residue or a reference to an array of Residue objects | |
| 397 | |
| 398 =cut | |
| 399 | |
| 400 sub residue { | |
| 401 my ($self, $residue) = @_; | |
| 402 | |
| 403 if ( ! $self->model ) { | |
| 404 my $m = $self->_create_default_model; | |
| 405 $self->add_model($self,$m); | |
| 406 } | |
| 407 my @models = $self->model; | |
| 408 my $first_model = $models[0]; | |
| 409 | |
| 410 if ( ! $self->get_chains($first_model) ) { | |
| 411 my $c = $self->_create_default_chain; | |
| 412 $self->add_chain($first_model, $c); | |
| 413 } | |
| 414 my @chains = $self->get_chains($first_model); | |
| 415 my $first_chain = $chains[0]; | |
| 416 | |
| 417 if( defined $residue) { | |
| 418 if( (ref($residue) eq "ARRAY") || | |
| 419 ($residue->isa('Bio::Structure::Residue')) ) { | |
| 420 # remove existing ones, tell they've become orphan | |
| 421 my @obj = $self->get_residues($first_chain); | |
| 422 if (@obj) { | |
| 423 for my $r (@obj) { | |
| 424 $self->_remove_from_graph($r); | |
| 425 } | |
| 426 } | |
| 427 # add the new ones | |
| 428 $self->add_residue($first_chain,$residue); | |
| 429 } | |
| 430 else { | |
| 431 $self->throw("Supplied a $residue to residue, we want a Bio::Structure::Residue or a list of these\n"); | |
| 432 } | |
| 433 } | |
| 434 $self->get_residues($first_chain); | |
| 435 } | |
| 436 | |
| 437 | |
| 438 =head2 add_residue() | |
| 439 | |
| 440 Title : add_residue | |
| 441 Usage : @residues = $structure->add_residue($residue); | |
| 442 Function: Adds a (or a list of) Residue objects to a Bio::Structure::Entry. | |
| 443 Returns : list of Bio::Structure::Residue objects | |
| 444 Args : One Residue or a reference to an array of Residue objects | |
| 445 | |
| 446 =cut | |
| 447 | |
| 448 sub add_residue { | |
| 449 my($self,$chain,$residue) = @_; | |
| 450 | |
| 451 if (ref($chain) !~ /^Bio::Structure::Chain/) { | |
| 452 $self->throw("add_residue: first argument needs to be a Chain object\n"); | |
| 453 } | |
| 454 if (defined $residue) { | |
| 455 if (ref($residue) eq "ARRAY") { | |
| 456 # if the user passed in a reference to an array | |
| 457 for my $r ( @{$residue} ) { | |
| 458 if( ! $r->isa('Bio::Structure::Residue') ) { | |
| 459 $self->throw("$r is not a Residue\n"); | |
| 460 } | |
| 461 if ( $self->_parent($r) ) { | |
| 462 $self->throw("$r already belongs to a parent\n"); | |
| 463 } | |
| 464 $self->_parent($r, $chain); | |
| 465 $self->_child($chain, $r); | |
| 466 # stringify | |
| 467 my $str_ref = "$self"; | |
| 468 $r->_grandparent($str_ref); | |
| 469 } | |
| 470 } | |
| 471 elsif ( $residue->isa('Bio::Structure::Residue') ) { | |
| 472 if ( $self->_parent($residue) ) { | |
| 473 $self->throw("$residue already belongs to a parent\n"); | |
| 474 } | |
| 475 $self->_parent($residue, $chain); | |
| 476 $self->_child($chain, $residue); | |
| 477 # stringify | |
| 478 my $str_ref = "$self"; | |
| 479 $residue->_grandparent($str_ref); | |
| 480 } | |
| 481 else { | |
| 482 $self->throw("Supplied a $residue to add_residue, we want a Residue or list of Residues\n"); | |
| 483 } | |
| 484 } | |
| 485 my $array_ref = $self->_child($chain); | |
| 486 return $array_ref ? @{$array_ref} : (); | |
| 487 } | |
| 488 | |
| 489 | |
| 490 =head2 get_residues() | |
| 491 | |
| 492 Title : get_residues | |
| 493 Usage : $structure->get_residues($chain); | |
| 494 Function: general get method for residues attached to a Chain | |
| 495 Returns : a list of residues attached to this chain | |
| 496 Args : a chain | |
| 497 | |
| 498 =cut | |
| 499 | |
| 500 sub get_residues { | |
| 501 my ($self, $chain) = @_; | |
| 502 | |
| 503 if ( !defined $chain) { | |
| 504 $self->throw("get_residues needs a Chain as argument"); | |
| 505 } | |
| 506 # pass through to add_residue | |
| 507 $self->add_residue($chain); | |
| 508 } | |
| 509 | |
| 510 | |
| 511 =head2 add_atom() | |
| 512 | |
| 513 Title : add_atom | |
| 514 Usage : @atoms = $structure->add_atom($residue,$atom); | |
| 515 Function: Adds a (or a list of) Atom objects to a Bio::Structure::Residue. | |
| 516 Returns : list of Bio::Structure::Atom objects | |
| 517 Args : a residue and an atom | |
| 518 | |
| 519 =cut | |
| 520 | |
| 521 sub add_atom { | |
| 522 my($self,$residue,$atom) = @_; | |
| 523 | |
| 524 if (ref($residue) !~ /^Bio::Structure::Residue/) { | |
| 525 $self->throw("add_atom: first argument needs to be a Residue object\n"); | |
| 526 } | |
| 527 if (defined $atom) { | |
| 528 if (ref($atom) eq "ARRAY") { | |
| 529 # if the user passed in a reference to an array | |
| 530 for my $a ( @{$atom} ) { | |
| 531 if( ! $a->isa('Bio::Structure::Atom') ) { | |
| 532 $self->throw("$a is not an Atom\n"); | |
| 533 } | |
| 534 if ( $self->_parent($a) ) { | |
| 535 $self->throw("$a already belongs to a parent\n"); | |
| 536 } | |
| 537 $self->_parent($a, $residue); | |
| 538 $self->_child($residue, $a); | |
| 539 # stringify | |
| 540 #my $str_ref = "$self"; | |
| 541 #$r->_grandparent($str_ref); | |
| 542 } | |
| 543 } | |
| 544 #elsif ( $atom->isa('Bio::Structure::Atom') ) { | |
| 545 elsif ( ref($atom) =~ /^Bio::Structure::Atom/ ) { | |
| 546 if ( $self->_parent($atom) ) { | |
| 547 $self->throw("$atom already belongs to a parent\n"); | |
| 548 } | |
| 549 $self->_parent($atom, $residue); | |
| 550 $self->_child($residue, $atom); | |
| 551 # stringify | |
| 552 #my $str_ref = "$self"; | |
| 553 #$atom->_grandparent($str_ref); | |
| 554 } | |
| 555 } | |
| 556 my $array_ref = $self->_child($residue); | |
| 557 return $array_ref ? @{$array_ref} : (); | |
| 558 } | |
| 559 | |
| 560 | |
| 561 =head2 get_atoms() | |
| 562 | |
| 563 Title : get_atoms | |
| 564 Usage : $structure->get_atoms($residue); | |
| 565 Function: general get method for atoms attached to a Residue | |
| 566 Returns : a list of atoms attached to this residue | |
| 567 Args : a residue | |
| 568 | |
| 569 =cut | |
| 570 | |
| 571 sub get_atoms { | |
| 572 my ($self, $residue) = @_; | |
| 573 | |
| 574 if ( !defined $residue) { | |
| 575 $self->throw("get_atoms needs a Residue as argument"); | |
| 576 } | |
| 577 # pass through to add_atom | |
| 578 $self->add_atom($residue); | |
| 579 } | |
| 580 | |
| 581 | |
| 582 =head2 parent() | |
| 583 | |
| 584 Title : parent | |
| 585 Usage : $structure->parent($residue); | |
| 586 Function: returns the parent of the argument | |
| 587 Returns : the parent of the argument | |
| 588 Args : a Bio::Structure object | |
| 589 | |
| 590 =cut | |
| 591 | |
| 592 =head2 conect() | |
| 593 | |
| 594 Title : conect | |
| 595 Usage : $structure->conect($source); | |
| 596 Function: get/set method for conect | |
| 597 Returns : a list of serial numbers for atoms connected to source | |
| 598 (together with $entry->get_atom_by_serial($model, $serial) this should be OK for now) | |
| 599 Args : the serial number for the source atom | |
| 600 | |
| 601 =cut | |
| 602 | |
| 603 sub conect { | |
| 604 my ($self, $source, $serial, $type) = @_; | |
| 605 | |
| 606 if ( !defined $source ) { | |
| 607 $self->throw("You need to supply at least a source to conect"); | |
| 608 } | |
| 609 if ( defined $serial && defined $type ) { | |
| 610 if ( !exists(${$self->{'conect'}}{$source}) || ref(${$self->{'conect'}}{$source} !~ /^ARRAY/ ) ) { | |
| 611 ${$self->{'conect'}}{$source} = []; | |
| 612 } | |
| 613 # we also need to store type, a conect object might be better | |
| 614 my $c = $serial . "_" . $type; | |
| 615 push @{ ${$self->{'conect'}}{$source} }, $c; | |
| 616 } | |
| 617 return @{ ${$self->{'conect'}}{$source} }; | |
| 618 } | |
| 619 | |
| 620 =head2 get_all_conect_source() | |
| 621 | |
| 622 Title : get_all_conect_source | |
| 623 Usage : @sources = $structure->get_all_conect_source; | |
| 624 Function: get all the sources for the conect records | |
| 625 Returns : a list of serial numbers for atoms connected to source | |
| 626 (together with $entry->get_atom_by_serial($model, $serial) this should be OK for now) | |
| 627 Args : | |
| 628 Description : This is a bit of a kludge, but it's the best for now. Conect info might need | |
| 629 to go in a sepearte object | |
| 630 | |
| 631 =cut | |
| 632 | |
| 633 sub get_all_conect_source { | |
| 634 my ($self) = shift; | |
| 635 my (@sources); | |
| 636 | |
| 637 for my $source (sort {$a<=>$b} keys %{$self->{'conect'}}) { | |
| 638 push @sources, $source; | |
| 639 } | |
| 640 return @sources; | |
| 641 } | |
| 642 | |
| 643 | |
| 644 =head2 master() | |
| 645 | |
| 646 Title : master | |
| 647 Usage : $structure->master($source); | |
| 648 Function: get/set method for master | |
| 649 Returns : the master line | |
| 650 Args : the master line for this entry | |
| 651 | |
| 652 =cut | |
| 653 | |
| 654 sub master { | |
| 655 my ($self, $value) = @_; | |
| 656 if (defined $value) { | |
| 657 $self->{'master'} = $value; | |
| 658 } | |
| 659 return $self->{'master'}; | |
| 660 } | |
| 661 | |
| 662 | |
| 663 =head2 seqres() | |
| 664 | |
| 665 Title : seqres | |
| 666 Usage : $seqobj = $structure->seqres("A"); | |
| 667 Function: gets a sequence object containing the sequence from the SEQRES record. | |
| 668 if a chain-ID is given , the sequence for this chain is given, if none | |
| 669 is provided the first chain is choosen | |
| 670 Returns : a Bio::PrimarySeq | |
| 671 Args : the chain-ID of the chain you want the sequence from | |
| 672 | |
| 673 =cut | |
| 674 | |
| 675 sub seqres { | |
| 676 my ($self, $chainid) = @_; | |
| 677 my $s_u = "x3 A1 x7 A3 x1 A3 x1 A3 x1 A3 x1 A3 x1 A3 x1 A3 x1 A3 x1 A3 x1 A3 x1 A3 x1 A3 x1 A3"; | |
| 678 my (%seq_ch); | |
| 679 if ( !defined $chainid) { | |
| 680 my $m = ($self->get_models($self))[0]; | |
| 681 my $c = ($self->get_chains($m))[0]; | |
| 682 $chainid = $c->id; | |
| 683 } | |
| 684 my $seqres = ($self->annotation->get_Annotations("seqres"))[0]; | |
| 685 my $seqres_string = $seqres->as_text; | |
| 686 $self->debug("seqres : $seqres_string\n"); | |
| 687 $seqres_string =~ s/^Value: //; | |
| 688 # split into lines of 62 long | |
| 689 my @l = unpack("A62" x (length($seqres_string)/62), $seqres_string); | |
| 690 for my $line (@l) { | |
| 691 # get out chain_id and sequence | |
| 692 # we use a1, as A1 strips all spaces :( | |
| 693 my ($chid, $seq) = unpack("x3 a1 x7 A51", $line); | |
| 694 if ($chid eq " ") { | |
| 695 $chid = "default"; | |
| 696 } | |
| 697 $seq =~ s/(\w+)/\u\L$1/g; # ALA -> Ala (for SeqUtils) | |
| 698 $seq =~ s/\s//g; # strip all spaces | |
| 699 $seq_ch{$chid} .= $seq; | |
| 700 $self->debug("seqres : $chid $seq_ch{$chid}\n"); | |
| 701 } | |
| 702 # do we have a seqres for this chainid | |
| 703 if(! exists $seq_ch{$chainid} ) { | |
| 704 $self->warn("There is no SEQRES known for chainid \"$chainid\""); | |
| 705 return undef; | |
| 706 } | |
| 707 | |
| 708 # this will break for non-protein structures (about 10% for now) XXX KB | |
| 709 my $pseq = Bio::PrimarySeq->new(-alphabet => 'protein'); | |
| 710 $pseq = Bio::SeqUtils->seq3in($pseq,$seq_ch{$chainid}); | |
| 711 my $id = $self->id . "_" . $chainid; | |
| 712 $pseq->id($id); | |
| 713 return $pseq; | |
| 714 } | |
| 715 | |
| 716 =head2 get_atom_by_serial() | |
| 717 | |
| 718 Title : get_atom_by_serial | |
| 719 Usage : $structure->get_atom_by_serial($module, $serial); | |
| 720 Function: get the Atom for a for get_atom_by_serial | |
| 721 Returns : the Atom object with this serial number in the model | |
| 722 Args : Model on which to work, serial number for atom | |
| 723 (if only a number is supplied, the first model is chosen) | |
| 724 | |
| 725 =cut | |
| 726 | |
| 727 sub get_atom_by_serial { | |
| 728 my ($self, $model, $serial) = @_; | |
| 729 | |
| 730 if ($model =~ /^\d+$/ && !defined $serial) { # only serial given | |
| 731 $serial = $model; | |
| 732 my @m = $self->get_models($self); | |
| 733 $model = $m[0]; | |
| 734 } | |
| 735 if ( !defined $model || ref($model) !~ /^Bio::Structure::Model/ ) { | |
| 736 $self->throw("Could not find (first) model\n"); | |
| 737 } | |
| 738 if ( !defined $serial || ($serial !~ /^\d+$/) ) { | |
| 739 $self->throw("The serial number you provided looks fishy ($serial)\n"); | |
| 740 } | |
| 741 for my $chain ($self->get_chains($model) ) { | |
| 742 for my $residue ($self->get_residues($chain) ) { | |
| 743 for my $atom ($self->get_atoms($residue) ) { | |
| 744 # this could get expensive, do we cache ??? | |
| 745 next unless ($atom->serial == $serial); | |
| 746 return $atom; | |
| 747 } | |
| 748 } | |
| 749 } | |
| 750 } | |
| 751 | |
| 752 sub parent { | |
| 753 my ($self, $obj) = @_; | |
| 754 | |
| 755 if ( !defined $obj) { | |
| 756 $self->throw("parent: you need to supply an argument to get the parent from\n"); | |
| 757 } | |
| 758 | |
| 759 # for now we pass on to _parent, untill we get the symbolic ref thing working. | |
| 760 $self->_parent($obj); | |
| 761 } | |
| 762 | |
| 763 sub DESTROY { | |
| 764 my $self = shift; | |
| 765 | |
| 766 #print STDERR "DESTROY on $self being called\n"; | |
| 767 | |
| 768 ## for my $pc (keys %{ $self->{'p_c'} } ) { | |
| 769 ## next unless ( defined ${ $self->{'p_c'} }{$pc} ); | |
| 770 ## delete ${$self->{'p_c'}}{$pc}; | |
| 771 ## } | |
| 772 ## for my $cp (keys %{ $self->{'c_p'} } ) { | |
| 773 ## next unless ( defined ${ $self->{'c_p'} }{$cp} ); | |
| 774 ## delete ${$self->{'c_p'}}{$cp}; | |
| 775 ## } | |
| 776 %{ $self->{'p_c'} } = (); | |
| 777 %{ $self->{'c_p'} } = (); | |
| 778 } | |
| 779 | |
| 780 # copied from Bio::Seq.pm | |
| 781 # | |
| 782 =head2 annotation | |
| 783 | |
| 784 Title : annotation | |
| 785 Usage : $obj->annotation($seq_obj) | |
| 786 Function: | |
| 787 Example : | |
| 788 Returns : value of annotation | |
| 789 Args : newvalue (optional) | |
| 790 | |
| 791 | |
| 792 =cut | |
| 793 | |
| 794 sub annotation { | |
| 795 my ($obj,$value) = @_; | |
| 796 if( defined $value) { | |
| 797 $obj->{'annotation'} = $value; | |
| 798 } | |
| 799 return $obj->{'annotation'}; | |
| 800 | |
| 801 } | |
| 802 | |
| 803 | |
| 804 # | |
| 805 # from here on only private methods | |
| 806 # | |
| 807 | |
| 808 =head2 _remove_models() | |
| 809 | |
| 810 Title : _remove_models | |
| 811 Usage : | |
| 812 Function: Removes the models attached to an Entry. Tells the models they | |
| 813 don't belong to this Entry any more | |
| 814 Returns : | |
| 815 Args : | |
| 816 | |
| 817 =cut | |
| 818 | |
| 819 #' | |
| 820 | |
| 821 sub _remove_models { | |
| 822 my ($self) = shift; | |
| 823 | |
| 824 ; | |
| 825 } | |
| 826 | |
| 827 | |
| 828 =head2 _create_default_model() | |
| 829 | |
| 830 Title : _create_default_model | |
| 831 Usage : | |
| 832 Function: Creates a default Model for this Entry. Typical situation | |
| 833 in an X-ray structure where there is only one model | |
| 834 Returns : | |
| 835 Args : | |
| 836 | |
| 837 =cut | |
| 838 | |
| 839 sub _create_default_model { | |
| 840 my ($self) = shift; | |
| 841 | |
| 842 my $model = Bio::Structure::Model->new(-id => "default"); | |
| 843 return $model; | |
| 844 } | |
| 845 | |
| 846 | |
| 847 =head2 _create_default_chain() | |
| 848 | |
| 849 Title : _create_default_chain | |
| 850 Usage : | |
| 851 Function: Creates a default Chain for this Model. Typical situation | |
| 852 in an X-ray structure where there is only one chain | |
| 853 Returns : | |
| 854 Args : | |
| 855 | |
| 856 =cut | |
| 857 | |
| 858 sub _create_default_chain { | |
| 859 my ($self) = shift; | |
| 860 | |
| 861 my $chain = Bio::Structure::Chain->new(-id => "default"); | |
| 862 return $chain; | |
| 863 } | |
| 864 | |
| 865 | |
| 866 | |
| 867 =head2 _parent() | |
| 868 | |
| 869 Title : _parent | |
| 870 Usage : This is an internal function only. It is used to have one | |
| 871 place that keeps track of which object has which other object | |
| 872 as parent. Thus allowing the underlying modules (Atom, Residue,...) | |
| 873 to have no knowledge about all this (and thus removing the possibility | |
| 874 of reference cycles). | |
| 875 This method hides the details of manipulating references to an anonymous | |
| 876 hash. | |
| 877 Function: To get/set an objects parent | |
| 878 Returns : a reference to the parent if it exist, undef otherwise. In the | |
| 879 current implementation each node should have a parent (except Entry). | |
| 880 Args : | |
| 881 | |
| 882 =cut | |
| 883 | |
| 884 # manipulating the c_p hash | |
| 885 | |
| 886 sub _parent { | |
| 887 no strict "refs"; | |
| 888 my ($self, $key, $value) = @_; | |
| 889 | |
| 890 if ( (!defined $key) || (ref($key) !~ /^Bio::/) ) { | |
| 891 $self->throw("First argument to _parent needs to be a reference to a Bio:: object ($key)\n"); | |
| 892 } | |
| 893 if ( (defined $value) && (ref($value) !~ /^Bio::/) ) { | |
| 894 $self->throw("Second argument to _parent needs to be a reference to a Bio:: object\n"); | |
| 895 } | |
| 896 # no checking here for consistency of key and value, needs to happen in caller | |
| 897 | |
| 898 if (defined $value) { | |
| 899 # is this value already in, shout | |
| 900 if (defined ( $self->{'c_p'}->{$key}) && | |
| 901 exists ( $self->{'c_p'}->{$key}) | |
| 902 ) { | |
| 903 $self->throw("_parent: $key already has a parent ${$self->{'c_p'}}{$key}\n"); | |
| 904 } | |
| 905 ${$self->{'c_p'}}{$key} = $value; | |
| 906 } | |
| 907 return ${$self->{'c_p'}}{$key}; | |
| 908 } | |
| 909 | |
| 910 | |
| 911 =head2 _child() | |
| 912 | |
| 913 Title : _child | |
| 914 Usage : This is an internal function only. It is used to have one | |
| 915 place that keeps track of which object has which other object | |
| 916 as child. Thus allowing the underlying modules (Atom, Residue,...) | |
| 917 to have no knowledge about all this (and thus removing the possibility | |
| 918 to have no knowledge about all this (and thus removing the possibility | |
| 919 of reference cycles). | |
| 920 This method hides the details of manipulating references to an anonymous | |
| 921 hash. | |
| 922 Function: To get/set an object's child(ren) | |
| 923 Returns : a reference to an array of child(ren) if it exist, undef otherwise. | |
| 924 Args : | |
| 925 | |
| 926 =cut | |
| 927 | |
| 928 # manipulating the p_c hash | |
| 929 sub _child { | |
| 930 my ($self, $key, $value) = @_; | |
| 931 | |
| 932 if ( (!defined $key) || (ref($key) !~ /^Bio::/) ) { | |
| 933 $self->throw("First argument to _child needs to be a reference to a Bio:: object\n"); | |
| 934 } | |
| 935 if ( (defined $value) && (ref($value) !~ /^Bio::/) ) { | |
| 936 $self->throw("Second argument to _child needs to be a reference to a Bio:: object\n"); | |
| 937 } | |
| 938 # no checking here for consistency of key and value, needs to happen in caller | |
| 939 | |
| 940 if (defined $value) { | |
| 941 if ( !exists(${$self->{'p_c'}}{$key}) || ref(${$self->{'p_c'}}{$key}) !~ /^ARRAY/ ) { | |
| 942 ${$self->{'p_c'}}{$key} = []; | |
| 943 } | |
| 944 push @{ ${$self->{'p_c'}}{$key} }, $value; | |
| 945 } | |
| 946 return ${$self->{'p_c'}}{$key}; | |
| 947 } | |
| 948 | |
| 949 | |
| 950 | |
| 951 =head2 _remove_from_graph() | |
| 952 | |
| 953 Title : _remove_from_graph | |
| 954 Usage : This is an internal function only. It is used to remove from | |
| 955 the parent/child graph. We only remove the links from object to | |
| 956 his parent. Not the ones from object to its children. | |
| 957 Function: To remove an object from the parent/child graph | |
| 958 Returns : | |
| 959 Args : the object to be orphaned | |
| 960 | |
| 961 =cut | |
| 962 | |
| 963 sub _remove_from_graph { | |
| 964 my ($self, $object) = @_; | |
| 965 | |
| 966 if ( !defined($object) && ref($object) !~ /^Bio::/) { | |
| 967 $self->throw("_remove_from_graph needs a Bio object as argument"); | |
| 968 } | |
| 969 if ( $self->_parent($object) ) { | |
| 970 my $dad = $self->_parent($object); | |
| 971 # if we have a parent, remove me as being a child | |
| 972 for my $k (0 .. $#{$self->_child($dad)}) { | |
| 973 if ($object eq ${$self->{'p_c'}{$dad}}[$k]) { | |
| 974 splice(@{$self->{'p_c'}{$dad}}, $k,1); | |
| 975 } | |
| 976 } | |
| 977 delete( $self->{'c_p'}{$object}); | |
| 978 } | |
| 979 } | |
| 980 | |
| 981 | |
| 982 sub _print_stats_pc { | |
| 983 # print stats about the parent/child hashes | |
| 984 my ($self) =@_; | |
| 985 my $pc = scalar keys %{$self->{'p_c'}}; | |
| 986 my $cp = scalar keys %{$self->{'c_p'}}; | |
| 987 my $now_time = Time::HiRes::time(); | |
| 988 $self->debug("pc stats: P_C $pc C_P $cp $now_time\n"); | |
| 989 } | |
| 990 | |
| 991 | |
| 992 1; | 
