00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00025
00026
00027 #ifndef BTK_BUILDABLE_MONOMER_H
00028 #define BTK_BUILDABLE_MONOMER_H
00029
00030
00031 #include "buildable_atom.h"
00032 #include "buildable_atom_algorithms.h"
00033 #include "buildable_atom_group_concept.h"
00034 #include "buildable_monomer_family_pattern.h"
00035 #include "monomer.h"
00036
00037 #include <boost/concept_check.hpp>
00038 #include <boost/static_assert.hpp>
00039 #include <boost/type_traits.hpp>
00040
00041 #include <cassert>
00042
00043 #include <string>
00044 #include <utility>
00045
00046
00047 #include <iostream>
00048
00049 namespace BTK{
00050
00051
00064 template <typename AtomType>
00065 class BuildableMonomer : public Monomer<AtomType>, public BuildableAtomGroupConcept {
00066 BOOST_CLASS_REQUIRE2(AtomType, BuildableAtom, boost, ConvertibleConcept);
00067
00068 typedef Monomer<AtomType> base_type;
00069 typedef BuildableMonomer<AtomType> self_type;
00070
00071 typedef BuildableMonomerFamilyPattern pattern_t;
00072 public:
00073 typedef self_type buildable_monomer_types;
00074
00076
00077 typedef typename base_type::value_type value_type;
00078 typedef typename base_type::reference reference;
00079 typedef typename base_type::const_reference const_reference;
00080 typedef typename base_type::pointer pointer;
00081 typedef typename base_type::const_pointer const_pointer;
00082 typedef typename base_type::size_type size_type;
00083 typedef typename base_type::iterator iterator;
00084 typedef typename base_type::const_iterator const_iterator;
00086
00088
00089 typedef value_type atom_type;
00090 typedef iterator atom_iterator;
00091 typedef const_iterator const_atom_iterator;
00093
00094 typedef std::map<ATOM::index_t,pointer> atom_index_map_t;
00095
00096 typedef pattern_t::types::monomer_atom_idx_t monomer_atom_idx_t;
00097
00098
00104 BuildableMonomer(const BuildableMonomerFamilyPattern& family_pattern)
00105 : _family_pattern(family_pattern) {}
00106
00111 template <typename AtomIterator>
00112 BuildableMonomer(AtomIterator first,
00113 AtomIterator last,
00114 self_type* prev_monomer,
00115 self_type* next_monomer,
00116 const AtomGroupConcept::group_variant_container_t& modifiers,
00117 const BuildableMonomerFamilyPattern& family_pattern)
00118 : base_type(first,last),
00119 _prev_monomer(prev_monomer),
00120 _next_monomer(next_monomer),
00121 _group_index(GROUP::name3_to_index(first->group_name3())),
00122 _group_variants(modifiers),
00123 _family_pattern(family_pattern)
00124 {
00125 set_buildable_group();
00126 initialize_atoms();
00127 initialize_bonds();
00128 if(_prev_monomer) _prev_monomer->set_next_monomer(this);
00129 if(_next_monomer) _next_monomer->set_prev_monomer(this);
00130 }
00131
00134 BuildableMonomer(const self_type& source)
00135 : base_type(source),
00136 _prev_monomer(0),
00137 _next_monomer(0),
00138 _group_index(source._group_index),
00139 _group_variants(source._group_variants),
00140 _family_pattern(source._family_pattern)
00141 {
00142 set_buildable_group();
00143 initialize_bonds();
00144 }
00145
00146 template <typename T2>
00147 BuildableMonomer(const BuildableMonomer<T2>& source)
00148 : base_type(source),
00149 _prev_monomer(0),
00150 _next_monomer(0),
00151 _group_index(source._group_index),
00152 _group_variants(source._group_variants),
00153 _family_pattern(source._family_pattern)
00154 {
00155 set_buildable_group();
00156 initialze_bonds();
00157 }
00158
00159
00163 self_type&
00164 operator=(const self_type& rhs)
00165 {
00166 if (&rhs == this) return *this;
00167 base_type::operator=(rhs);
00168 _prev_monomer = 0;
00169 _next_monomer = 0;
00170 _group_index = rhs._group_index;
00171 _group_variants = rhs._group_variants;
00172 _family_pattern = rhs._family_pattern;
00173
00174
00175
00176 set_buildable_group();
00177 initialize_bonds();
00178
00179 return *this;
00180 }
00181
00182 template <typename T2>
00183 self_type&
00184 operator=(const BuildableMonomer<T2>& rhs)
00185 {
00186 base_type::operator=(rhs);
00187 _prev_monomer = 0;
00188 _next_monomer = 0;
00189 _group_index = rhs._group_index;
00190 _family_pattern = rhs._family_pattern;
00191
00192 set_buildable_group();
00193 initialize_bonds();
00194
00195 return *this;
00196 }
00197
00199
00200
00201 virtual
00202 GROUP::index_t
00203 group_index() const
00204 {
00205 return _group_index;
00206 }
00207
00208 virtual
00209 const AtomGroupConcept::group_variant_container_t&
00210 group_variants() const
00211 {
00212 return _group_variants;
00213 }
00214
00215
00216 virtual
00217 const std::string&
00218 group_name3() const
00219 {
00220 return GROUP::index_to_name3(group_index());
00221 }
00222
00224
00225
00226 virtual
00227 char
00228 group_name1() const
00229 {
00230 return GROUP::index_to_name1(group_index());
00231 }
00232
00234
00235 void
00236 insert_group_variant(GROUP_VARIANT::index_t v)
00237 {
00239 _group_variants.insert(v);
00240 }
00241
00242 void
00243 erase_group_variant(GROUP_VARIANT::index_t v)
00244 {
00245 _group_variants.erase(v);
00246 }
00247
00250
00251
00252
00253
00254
00255 reference
00256 atom(monomer_atom_idx_t ma)
00257 {
00258 pointer a = atom_pointer(ma);
00259 assert(a);
00260 return *a;
00261 }
00262
00263 const_reference
00264 atom(monomer_atom_idx_t ma) const
00265 {
00266 const_pointer a = atom_pointer(ma);
00267 assert(a);
00268 return *a;
00269 }
00271
00273
00274
00275 reference
00276 atom(ATOM::index_t atom_index)
00277 {
00278 pointer a = atom_pointer(atom_index);
00279 assert(a);
00280 return *a;
00281 }
00282
00283 const_reference
00284 atom(ATOM::index_t atom_index) const
00285 {
00286 const_pointer a = atom_pointer(atom_index);
00287 assert(a);
00288 return *a;
00289 }
00291
00298 double
00299 torsion_angle(TORSION::index_t t) const
00300 {
00301 const pattern_t::types::torsion_atom_t& an = _family_pattern.torsion_atoms(group_index(),t);
00302 return torsion_angle_impl(an);
00303 }
00304
00305 void
00306 set_torsion_angle(TORSION::index_t t,
00307 double angle)
00308 {
00309 const pattern_t::types::torsion_atom_t& an = _family_pattern.torsion_atoms(group_index(),t);
00310 double delta_angle = angle - torsion_angle_impl(an);
00311
00312 reference start = atom(boost::get<2>(an));
00313 reference boundary = atom(boost::get<1>(an));
00314
00315 restricted_rotate(start,boundary,delta_angle);
00316 }
00317
00318
00319
00320
00321
00322 virtual
00323 bool
00324 build_atom(const ATOM::index_t atom_index,
00325 bool is_bootstrap)
00326 {
00327
00328
00329 pointer build_atom_ptr = atom_pointer(atom_index);
00330 if(!build_atom_ptr) return false;
00331
00332
00333
00334 bool result = find_tetrads_and_build_atom(std::make_pair(0,atom_index),
00335 build_atom_ptr,
00336 is_bootstrap);
00337 if(result) return true;
00338
00339
00340
00341 if(_prev_monomer) {
00342 result = _prev_monomer->find_tetrads_and_build_atom(std::make_pair(1,atom_index),
00343 build_atom_ptr,
00344 is_bootstrap);
00345 if(result) return true;
00346 }
00347
00348 if(_next_monomer) {
00349 result = _next_monomer->find_tetrads_and_build_atom(std::make_pair(-1,atom_index),
00350 build_atom_ptr,
00351 is_bootstrap);
00352 if(result) return true;
00353 }
00354
00355 return false;
00356 }
00357
00358
00359 private:
00360
00361
00362
00363
00364
00365
00366
00367 pointer
00368 atom_pointer(monomer_atom_idx_t ma)
00369 {
00370 int monomer_difference = ma.first;
00371 ATOM::index_t atom_index = ma.second;
00372 if(monomer_difference==0) {
00373 return atom_pointer(atom_index);
00374 } else if(monomer_difference<0) {
00375 if(! _prev_monomer) return 0;
00376 else return _prev_monomer->atom_pointer(std::make_pair(monomer_difference+1,atom_index));
00377 } else {
00378 if(! _next_monomer) return 0;
00379 else return _next_monomer->atom_pointer(std::make_pair(monomer_difference-1,atom_index));
00380 }
00381 }
00382
00383 const_pointer
00384 atom_pointer(monomer_atom_idx_t ma) const
00385 {
00386 int monomer_difference = ma.first;
00387 ATOM::index_t atom_index = ma.second;
00388 if(monomer_difference==0) {
00389 return atom_pointer(atom_index);
00390 } else if(monomer_difference<0) {
00391 if(! _prev_monomer) return 0;
00392 else return _prev_monomer->atom_pointer(std::make_pair(monomer_difference+1,atom_index));
00393 } else {
00394 if(! _next_monomer) return 0;
00395 else return _next_monomer->atom_pointer(std::make_pair(monomer_difference-1,atom_index));
00396 }
00397 }
00398
00399 pointer
00400 atom_pointer(ATOM::index_t atom_index)
00401 {
00402 typename atom_index_map_t::iterator a = _atom_index_to_atom_map.find(atom_index);
00403 if(a ==_atom_index_to_atom_map.end()) return 0;
00404 else return a->second;
00405 }
00406
00407 const_pointer
00408 atom_pointer(ATOM::index_t atom_index) const
00409 {
00410 typename atom_index_map_t::const_iterator a = _atom_index_to_atom_map.find(atom_index);
00411 if(a ==_atom_index_to_atom_map.end()) return 0;
00412 else return a->second;
00413 }
00414
00415
00416
00417
00418
00419
00420 double
00421 get_bond_length_from_tetrads(monomer_atom_idx_t ma1,
00422 monomer_atom_idx_t ma2)
00423 {
00424 typedef pattern_t::types::tetrad_container_t tc_t;
00425
00426 tc_t tc;
00427 double result = -1.;
00428
00429 tc = _family_pattern.tetrads(group_index(),group_variants(),ma1);
00430 result = get_bond_length_from_tetrad_container(tc,ma2);
00431
00432 if(result >= 0.) return result;
00433
00434 tc = _family_pattern.tetrads(group_index(),group_variants(),ma2);
00435 result = get_bond_length_from_tetrad_container(tc,ma1);
00436
00437 return result;
00438 }
00439
00440
00441
00442
00443 double
00444 get_bond_length_from_tetrad_container(const pattern_t::types::tetrad_container_t& tc,
00445 const monomer_atom_idx_t& ma)
00446 {
00447 pattern_t::types::tetrad_container_t::const_iterator ti=tc.begin(),ti_end=tc.end();
00448 for(; ti != ti_end ; ++ti ){
00449 if(ti->atom_index3()==ma) return ti->len34();
00450 }
00451 return -1.;
00452 }
00453
00454
00455
00456 bool
00457 find_tetrads_and_build_atom(monomer_atom_idx_t ma,
00458 pointer build_atom_ptr,
00459 bool is_bootstrap)
00460 {
00461 typedef pattern_t::types::tetrad_container_t tc_t;
00462 tc_t tc = _family_pattern.tetrads(group_index(),group_variants(), ma);
00463
00464 return build_atom_from_tetrad_container(tc,build_atom_ptr,is_bootstrap);
00465 }
00466
00467
00468
00469 bool
00470 build_atom_from_tetrad_container(const pattern_t::types::tetrad_container_t& tc,
00471 pointer build_atom_ptr,
00472 bool is_bootstrap)
00473 {
00474
00475
00476
00477 for(unsigned pass=0;pass<2;++pass){
00478 pattern_t::types::tetrad_container_t::const_iterator ti=tc.begin(),ti_end=tc.end();
00479 for(; ti != ti_end ; ++ti ){
00480 if((pass == 0) && (ti->is_real_torsion())) continue;
00481 if((pass == 1) && (!ti->is_real_torsion())) continue;
00482 bool result = build_atom_from_tetrad(*ti,build_atom_ptr,is_bootstrap);
00483 if (result) return true;
00484 }
00485 }
00486 return false;
00487 }
00488
00489
00490
00491
00492 bool
00493 build_atom_from_tetrad(const AtomIndexTetrad& t,
00494 pointer build_atom_ptr,
00495 bool is_bootstrap)
00496 {
00498
00499
00500
00501
00502 const_pointer atom_ptr3 = atom_pointer(t.atom_index3());
00503 if(!atom_ptr3) return false;
00504 if(!is_bootstrap && !atom_ptr3->is_built()) return false;
00505 const_pointer atom_ptr2 = atom_pointer(t.atom_index2());
00506 if(!atom_ptr2) return false;
00507 if(!is_bootstrap && !atom_ptr2->is_built()) return false;
00508
00509 if(!is_bootstrap){
00510 const_pointer atom_ptr1 = atom_pointer(t.atom_index1());
00511 if(!atom_ptr1) return false;
00512 if(!atom_ptr1->is_built()) return false;
00513
00514
00515
00516 build_atom_ptr->
00517 set_position(set_vector_from_dihedral(atom_ptr3->position(),
00518 atom_ptr2->position(),
00519 atom_ptr1->position(),
00520 t.len34(),
00521 t.ang234(),
00522 t.dih1234()));
00523 build_atom_ptr->set_is_built(true);
00524
00525 } else {
00526
00527
00528
00529
00530
00531 double len23 = get_bond_length_from_tetrads(t.atom_index3(),t.atom_index2());
00532 if( len23 <= 0.) return false;
00533 build_atom_ptr->set_position(new_vector(t.len34(),0.,0.));
00534 build_atom_ptr->set_is_built(true);
00535 atom_ptr3->set_position(new_vector(0.,0.,0.));
00536 atom_ptr3->set_is_built(true);
00537 atom_ptr2->set_position(new_vector(cos(t.ang234())*len23,sin(t.ang234())*len23,0.));
00538 atom_ptr2->set_is_built(true);
00539 }
00540 return true;
00541 }
00542
00543
00545
00546 void
00547 set_buildable_group()
00548 {
00549 iterator i=begin(),i_end=end();
00550 for(;i!=i_end;++i) i->set_buildable_group(*this);
00551 }
00552
00553 double
00554 torsion_angle_impl(const pattern_t::types::torsion_atom_t& an) const
00555 {
00556 return point_dihedral( atom(boost::get<0>(an)).position(),
00557 atom(boost::get<1>(an)).position(),
00558 atom(boost::get<2>(an)).position(),
00559 atom(boost::get<3>(an)).position());
00560 }
00561
00562 void
00563 initialize_bonds()
00564 {
00565 typedef pattern_t::types::bond_container_t bc_t;
00566 bc_t bc = _family_pattern.bonds(group_index(),group_variants());
00567
00568 std::cerr << "init bonds: group_num: " << group_num() << std::endl;
00569
00570 bc_t::const_iterator bi=bc.begin(),bi_end=bc.end();
00571 for(; bi != bi_end; ++bi){
00572 pointer a1 = atom_pointer(bi->atom_index1());
00573 if(!a1) continue;
00574 pointer a2 = atom_pointer(bi->atom_index2());
00575 if(!a2) continue;
00576 std::cerr << "creating bond: atom1: " << *a1 << std::endl;
00577 std::cerr << "creating bond: atom2: " << *a2 << std::endl;
00578
00579 add_bond(*a1,*a2);
00580 }
00581 }
00582
00583 void
00584 set_next_monomer(self_type* next_monomer)
00585 {
00586 _next_monomer = next_monomer;
00587 }
00588
00589 void
00590 set_prev_monomer(self_type* prev_monomer)
00591 {
00592 _prev_monomer = prev_monomer;
00593 }
00594
00595 void
00596 initialize_atoms()
00597 {
00598 pattern_t::types::atom_container_t ac = _family_pattern.atoms(group_index(),group_variants());
00599
00600 std::cerr << "init atoms: group_num: " << group_num() << std::endl;
00601
00602
00603 for(atom_iterator i=atom_begin();i != atom_end(); ++i){
00604 ATOM::index_t atom_index = i->atom_index();
00605
00606 if( ac.find(atom_index) == ac.end() ){
00607
00608 std::cerr << "throwing away atom: " << i->atom_name() << std::endl;
00609 i = erase(i) - 1;
00610 } else {
00611
00612 std::cerr << "adding atom: " << i->atom_name() << std::endl;
00613 _atom_index_to_atom_map[ atom_index ] = &(*i);
00614 ac.erase(atom_index);
00615
00616 i->set_is_built(true);
00617 }
00618 }
00619
00620
00621 pattern_t::types::atom_container_t::const_iterator i=ac.begin(), i_end=ac.end();
00622 for(;i!=i_end;++i){
00623 shallow_push_back(new atom_type());
00624 back().set_atom_index(*i);
00625 _atom_index_to_atom_map[ *i ] = &(back());
00626
00627
00628 back().set_is_built(false);
00629 back().set_group(*this);
00630 back().set_buildable_group(*this);
00631 std::cerr << "adding new atom: " << back().atom_name() << std::endl;
00632 }
00633 }
00634
00635
00636 private:
00637 self_type* _prev_monomer;
00638 self_type* _next_monomer;
00639
00640 atom_index_map_t _atom_index_to_atom_map;
00641
00642 GROUP::index_t _group_index;
00643
00644 AtomGroupConcept::group_variant_container_t _group_variants;
00645
00646 const pattern_t& _family_pattern;
00647
00648 };
00649 }
00650
00651
00652
00653 #endif