36 #include <basic/Tracer.hh>
42 #include <numeric/random/random.hh>
43 #include <numeric/xyzMatrix.hh>
44 #include <numeric/xyzVector.hh>
45 #include <numeric/xyz.functions.hh>
50 #include <ObjexxFCL/FArray1D.hh>
51 #include <ObjexxFCL/FArray2D.hh>
52 #include <ObjexxFCL/format.hh>
54 #include <utility/vector1.hh>
59 namespace conformation {
62 static basic::Tracer
TR(
"core.conformation.symmetry.util");
63 static numeric::random::RandomGenerator
RG(408529);
67 if(lb_resi==0) lb_resi = 1;
68 if(ub_resi==0) ub_resi = ft.
nres();
72 if( lb_resi <= dn && dn <= ub_resi && ( up < lb_resi || ub_resi < up ) ) resi = dn;
74 if( (
int)lb_resi <= resi && resi <= (
int)ub_resi )
return resi;
76 if( (
int)lb_resi <= resi && resi <= (
int)ub_resi )
return resi;
77 utility_exit_with_message(
"can'd get fold_tree root in range!!!");
85 if(lb_resi==0) lb_resi = 1;
86 if(ub_resi==0) ub_resi = src_conf.
size();
89 if(input==
"FIRST" || input==
"FIRST_RESIDUE" ) resi = lb_resi;
90 if(input==
"LAST" || input==
"LAST_RESIDUE" ) resi = ub_resi;
91 if(input==
"") resi = 0;
92 if(resi == -1) resi = utility::string2int(input);
93 if(resi < 0) utility_exit_with_message(
"error in process_residue_request: '"+input+
"'");
99 for(std::map<
char,std::pair<Size,Size> >::const_iterator it = chain2range.begin(); it != chain2range.end(); ++it) {
100 Size const lb = it->second.first, ub = it->second.second;
101 if( lb <= up && up <= ub && lb <= dn && dn <= ub )
return true;
107 for(std::map<
char,std::pair<Size,Size> >::const_iterator it = chain2range.begin(); it != chain2range.end(); ++it) {
108 Size const lb = it->second.first, ub = it->second.second;
109 if( lb <= resi && resi <= ub )
return it->first;
111 utility_exit_with_message(
"resi not in any component!");
118 std::map<
char,std::pair<Size,Size> >
const &
122 ObjexxFCL::FArray2D_int jumps( 2, f_orig.
num_jump() );
130 std::sort(cutpoints.begin(),cutpoints.end());
131 cutpoints.push_back(f_orig.
nres());
134 for(
Size i = 1; i < cutpoints.size(); ++i) {
135 cuts(i) = cutpoints[i];
136 jumps(1,i) = cutpoints[i];
143 for(
Size i = 1; i < cutpoints.size(); ++i) {
185 std::map<char,std::pair<Size,Size> >
196 std::map<char,std::pair<Size,Size> > crange;
197 std::string const nullchain =
"ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890";
199 char chain = src_conf2pdb_chain.count(i)==0 ? nullchain[i-1] : src_conf2pdb_chain[i];
200 if(crange.count(chain)==0) crange[chain] = std::make_pair(99999999,0);
201 crange[chain].first = std::min( src_conf.
chain_begin(i), crange[chain].first );
202 crange[chain].second = std::max( src_conf.
chain_end (i), crange[chain].second );
205 for(std::map<
char,std::pair<Size,Size> >::const_iterator i = crange.begin(); i != crange.end(); ++i) {
207 if( i->second.first > i->second.second ) utility_exit_with_message(
"THIS SHOULD NEVER HAPPEN!");
208 for(std::map<
char,std::pair<Size,Size> >::const_iterator j = crange.begin(); j != crange.end(); ++j) {
209 if( i->second.first==j->second.first && i->second.second==j->second.second )
continue;
210 if( i->second.first > j->second.first && i->second.first > j->second.second )
continue;
211 if( j->second.first > i->second.first && j->second.first > i->second.second )
continue;
212 utility_exit_with_message(
"[ERROR] overlapping chain ranges in pose!!!!!!!!");
222 return ( dynamic_cast< conformation::symmetry::SymmetricConformation const * >( &conf ) );
262 std::map< int, char > src_conf2pdb_chain
272 std::map<char,std::pair<Size,Size> >
const chain2range =
get_chain2range(src_conformation,src_conf2pdb_chain);
295 Size const nres_monomer( conf.
size() );
299 std::map< std::string, conformation::symmetry::VirtualCoordinate > coords ( symmdata.
get_virtual_coordinates() );
300 std::map< std::string, std::pair< std::string, std::string > > virtual_connects( symmdata.
get_virtual_connects() );
316 for (
Size i =1; i <= virtual_num_to_id.size(); ++i ) {
317 if ( virtual_num_to_id.find( i ) == virtual_num_to_id.end() ) {
318 utility_exit_with_message(
"[ERROR] Cannot find jump number..." );
320 std::string tag ( virtual_num_to_id.find( i )->second );
321 if ( coords.find( tag ) == coords.end() ) {
322 utility_exit_with_message(
"[ERROR] Cannot find tag " + tag );
325 rsd->set_xyz(
"ORIG", virt_coord.get_origin() );
326 rsd->set_xyz(
"X", virt_coord.get_x().normalized() + virt_coord.get_origin() );
327 rsd->set_xyz(
"Y", virt_coord.get_y().normalized() + virt_coord.get_origin() );
336 Size const insert_seqpos( nres_monomer * i + 1 );
337 Size const insert_jumppos( njump_monomer * i + 1 );
338 Size const anchor_pseudo( nres_monomer * i + i + 1 );
339 Size const new_jump_number( njump_monomer*( i + 1 ) + i + 1 );
351 f.reorder( new_root );
352 TR.Debug << f << std::endl;
359 std::map<char,std::pair<Size,Size> > component_bounds;
361 char chain = src_conf2pdb_chain[ic];
362 component_bounds[chain].first = src_conformation.
chain_begin(ic);
363 component_bounds[chain].second = src_conformation.
chain_end(ic);
365 symm_info_raw.set_multicomponent_info(
375 for(std::map< Size, SymDof >::const_iterator j = symm_info.
get_dofs().begin(); j != symm_info.
get_dofs().end(); ++j){
379 TR <<
"MULTICOMPONENT " <<
"DOF " << dofname << std::endl;
380 TR <<
"MULTICOMPONENT " <<
" moves these components:";
385 TR <<
"MULTICOMPONENT " <<
" moves these subunits:";
393 TR <<
"MULTICOMPONENT " <<
" moved by dofs:";
394 for(std::map< Size, SymDof >::const_iterator j = symm_info.
get_dofs().begin(); j != symm_info.
get_dofs().end(); ++j){
400 if( std::find(compchild.begin(),compchild.end(),*i) == compchild.end() )
continue;
401 TR <<
" " << dofname;
403 TR << std::endl <<
"MULTICOMPONENT " <<
" contains virtuals:";
405 if(j->second != *i)
continue;
406 TR <<
" " << j->first;
427 for (
Size i=1; i<= f.num_jump(); ++i ) {
429 symm_conf->set_jump( i, conf.
jump( i ) );
441 TR <<
"=================== SYM FOLD TREE, jump notation: =symfixed= *indep* #symdof# jump[=follows] ========================\n"
454 std::map< int, char > src_conf2pdb_chain
457 std::map<char,std::pair<Size,Size> >
const chain2range =
get_chain2range(src_conformation,src_conf2pdb_chain);
459 using namespace kinematics;
460 FoldTree f, f_orig = src_conformation.
fold_tree();
464 Size num_res_subunit( src_conformation.
size() );
466 Size num_cuts_subunit( f_orig.num_cutpoint() );
469 Size num_res_real( num_res_subunit*subunits );
473 if ( anchor > num_res_subunit ) {
474 utility_exit_with_message(
"Anchor outside the subunit..." );
480 Size num_jumps_subunit( f_orig.num_jump() );
484 Size total_num_cuts( num_cuts_subunit*subunits + subunits + num_virtuals - 1 );
485 Size total_num_jumps( num_jumps_subunit*subunits + num_virtual_connects );
489 ObjexxFCL::FArray1D_int cuts( total_num_cuts );
490 ObjexxFCL::FArray2D_int jump_points_subunit( 2, num_jumps_subunit ),
491 jumps( 2, total_num_jumps );
493 for (
Size i = 1; i<= f_orig.num_jump(); ++i ) {
494 jump_points_subunit(1,i) = f_orig.upstream_jump_residue(i);
495 jump_points_subunit(2,i) = f_orig.downstream_jump_residue(i);
499 for (
Size i = 0; i < subunits; ++i ) {
500 for (
Size j = 1; j <= num_jumps_subunit; ++j ) {
502 int new_cut_pos( i*num_res_subunit + cuts_subunit.at( j ) );
503 cuts( njumps ) = new_cut_pos;
504 int new_jump_pos1( i*num_res_subunit + jump_points_subunit(1,j) );
505 int new_jump_pos2( i*num_res_subunit + jump_points_subunit(2,j) );
506 jumps(1, njumps ) = std::min(new_jump_pos1,new_jump_pos2);
507 jumps(2, njumps ) = std::max(new_jump_pos1,new_jump_pos2);
512 std::map< std::string, std::pair< std::string, std::string > >
const virtual_connect( symmdata.
get_virtual_connects() );
517 std::map< std::string, std::pair< std::string, std::string > >::const_iterator it_start = virtual_connect.begin();
518 std::map< std::string, std::pair< std::string, std::string > >::const_iterator it_end = virtual_connect.end();
519 for ( std::map<
std::string, std::pair< std::string, std::string > >::const_iterator it = it_start; it != it_end; ++it ) {
520 std::pair< std::string, std::string > connect( it->second );
523 if ( pos_id2 ==
"SUBUNIT" ) {
524 int subunit = virtual_id_to_subunit.find( pos_id1 )->second;
526 cuts( njumps ) = num_res_subunit*subunit;
527 int jump_pos1( ( subunit-1 )*num_res_subunit + anchor );
528 int jump_pos2( num_res_real + virtual_id_to_num.find( pos_id1 )->second );
529 jumps(1, njumps ) = std::min(jump_pos1,jump_pos2);
530 jumps(2, njumps ) = std::max(jump_pos1,jump_pos2);
539 for ( std::map<
std::string, std::pair< std::string, std::string > >::const_iterator it = it_start; it != it_end; ++it ) {
540 std::pair< std::string, std::string > connect( it->second );
544 if ( pos_id2 ==
"SUBUNIT" )
continue;
547 assert( virtual_id_to_num.find( pos_id1 ) != virtual_id_to_num.end() && virtual_id_to_num.find( pos_id2 ) != virtual_id_to_num.end() );
548 Size pos1 ( virtual_id_to_num.find( pos_id1 )->second );
549 Size pos2 ( virtual_id_to_num.find( pos_id2 )->second );
550 cuts( njumps ) = num_res_real + pos;
551 jumps(1, njumps ) = num_res_real + std::min(pos1,pos2);
552 jumps(2, njumps ) = num_res_real + std::max(pos1,pos2);
556 f.tree_from_jumps_and_cuts( num_res_real + num_virtuals, njumps, jumps, cuts );
557 f.reorder( num_res_real + 1 );
561 std::map<int,std::string> downstream_res_to_jump_atom;
562 for(
Size i = 1; i <= f_orig.num_jump(); ++i){
563 downstream_res_to_jump_atom[f_orig.downstream_jump_residue(i)] = f_orig.downstream_atom(i);
565 for(
Size i = 1; i <= f.num_jump(); ++i){
566 int upres = f.upstream_jump_residue(i);
567 int dnres = f.downstream_jump_residue(i);
568 int upres1 = (upres-1) % num_res_subunit + 1;
569 int dnres1 = (dnres-1) % num_res_subunit + 1;
570 if( dnres > (
int)num_res_real )
continue;
571 if( downstream_res_to_jump_atom.find(dnres1) == downstream_res_to_jump_atom.end() )
continue;
572 if( downstream_res_to_jump_atom[dnres1] ==
"" )
continue;
574 std::string dnatom = downstream_res_to_jump_atom[dnres1];
575 TR <<
"set SYM jump atoms: " << upres <<
":" << upatom <<
" " << dnres <<
":" << dnatom << std::endl;
576 f.set_jump_atoms(i, upatom, dnatom );
589 using std::make_pair;
590 using ObjexxFCL::fmt::I;
595 Size njumps( 0 ), ncuts(0);
596 Size total_num_cuts( num_cuts_subunit*subunits + subunits + num_virtuals - 1 );
597 Size total_num_jumps( num_jumps_subunit*subunits + num_virtual_connects );
599 ObjexxFCL::FArray2D_int jumps( 2, total_num_jumps );
602 ObjexxFCL::FArray2D_int jump_points_subunit( 2, num_jumps_subunit );
604 for (
Size i = 1; i<= f_orig.num_jump(); ++i ) {
605 Size const up = f_orig.upstream_jump_residue(i);
606 Size const dn = f_orig.downstream_jump_residue(i);
608 if(!up_and_dn_within_component) {
609 TR <<
"this intrasub jump will be replaced with a SUBUNIT jump " << up <<
" " << dn << endl;
613 jump_points_subunit(1,nsubjump) = up;
614 jump_points_subunit(2,nsubjump) = dn;
616 if(nsubjump != num_jumps_subunit){
620 utility_exit_with_message(
"intra-subunit jump mismatch!");
624 for (
Size i = 0; i < subunits; ++i ) {
625 for (
Size j = 1; j <= nsubjump; ++j ) {
627 int new_jump_pos1( i*num_res_subunit + jump_points_subunit(1,j) );
628 int new_jump_pos2( i*num_res_subunit + jump_points_subunit(2,j) );
629 jumps(1, njumps ) = std::min(new_jump_pos1,new_jump_pos2);
630 jumps(2, njumps ) = std::max(new_jump_pos1,new_jump_pos2);
635 std::map< std::string, std::pair< std::string, std::string > >
const & virtual_connect( symmdata.
get_virtual_connects() );
648 for(map<string,char>::const_iterator it = virtual_id_to_subunit_chain.begin(); it != virtual_id_to_subunit_chain.end(); ++it) {
649 string virt = it->first;
650 char chain = it->second;
651 if( chain == (
char)0 ) chain = src_conf2pdb_chain.count(1) ? src_conf2pdb_chain[1] :
'A';
652 if(chain2range.find(chain)==chain2range.end()){
653 std::cerr <<
"missing chain in pdb: " << chain << std::endl;
654 utility_exit_with_message(
"missing chain in symfile/pdb");
656 Size beg = chain2range.find(chain)->second.first;
657 Size end = chain2range.find(chain)->second.second;
659 if( !( beg <= resi && resi <= end ) ) {
660 TR <<
"SUBUNIT chain " << chain <<
" assertion fail: " << beg <<
" <= " << resi <<
" <= " << end << endl;
661 utility_exit_with_message(
"requested residue out of bounds: "+virtual_id_to_subunit_residue.find(virt)->second);
666 std::map< std::string, std::pair< std::string, std::string > >::const_iterator it_start = virtual_connect.begin();
667 std::map< std::string, std::pair< std::string, std::string > >::const_iterator it_end = virtual_connect.end();
668 for ( std::map<
std::string, std::pair< std::string, std::string > >::const_iterator it = it_start; it != it_end; ++it ) {
669 std::pair< std::string, std::string > connect( it->second );
672 if ( pos_id2 ==
"SUBUNIT" ) {
673 char chain = virtual_id_to_subunit_chain.find(pos_id1)->second;
674 if( chain == (
char)0 ) chain = src_conf2pdb_chain.count(1) ? src_conf2pdb_chain[1] :
'A';
675 Size beg = chain2range.find(chain)->second.first;
676 Size end = chain2range.find(chain)->second.second;
679 int subunit = virtual_id_to_subunit.find( pos_id1 )->second;
681 Size this_anchor = resi ? resi : anchor;
682 if( this_anchor < beg || end < this_anchor) utility_exit_with_message(
"bad anchor "+virtual_id_to_subunit_residue.find(pos_id1)->second);
685 int jump_pos1( (subunit-1)*num_res_subunit + this_anchor );
686 int jump_pos2( num_res_real + virtual_id_to_num.find( pos_id1 )->second );
687 jumps(1, njumps ) = std::min(jump_pos1,jump_pos2);
688 jumps(2, njumps ) = std::max(jump_pos1,jump_pos2);
697 for ( std::map<
std::string, std::pair< std::string, std::string > >::const_iterator it = it_start; it != it_end; ++it ) {
698 std::pair< std::string, std::string > connect( it->second );
702 if ( pos_id2 ==
"SUBUNIT" )
continue;
705 assert( virtual_id_to_num.find( pos_id1 ) != virtual_id_to_num.end() && virtual_id_to_num.find( pos_id2 ) != virtual_id_to_num.end() );
706 Size pos1 ( virtual_id_to_num.find( pos_id1 )->second );
707 Size pos2 ( virtual_id_to_num.find( pos_id2 )->second );
708 jumps(1, njumps ) = num_res_real + std::min(pos1,pos2);
709 jumps(2, njumps ) = num_res_real + std::max(pos1,pos2);
712 ObjexxFCL::FArray1D_int cuts( total_num_cuts );
713 for (
Size i = 0; i < subunits; ++i ) {
714 for(
Size j = 1; j <= f_orig.num_jump(); ++j) {
715 cuts( ++ncuts ) = i*num_res_subunit + cuts_subunit.at(j);
717 cuts(++ncuts) = num_res_subunit*(i+1);
719 for(
Size i = 1; i < num_virtuals; ++i) {
720 cuts(++ncuts) = i+num_res_real;
729 f.tree_from_jumps_and_cuts( num_res_real + num_virtuals, njumps, jumps, cuts, num_res_real+1 );
730 f.reorder( num_res_real + 1 );
734 std::map<int,std::string> downstream_res_to_jump_atom;
735 for(
Size i = 1; i <= f_orig.num_jump(); ++i){
736 downstream_res_to_jump_atom[f_orig.downstream_jump_residue(i)] = f_orig.downstream_atom(i);
738 for(
Size i = 1; i <= f.num_jump(); ++i){
739 int upres = f.upstream_jump_residue(i);
740 int dnres = f.downstream_jump_residue(i);
741 int upres1 = (upres-1) % num_res_subunit + 1;
742 int dnres1 = (dnres-1) % num_res_subunit + 1;
743 if( dnres > (
int)num_res_real )
continue;
744 if( downstream_res_to_jump_atom.find(dnres1) == downstream_res_to_jump_atom.end() )
continue;
745 if( downstream_res_to_jump_atom[dnres1] ==
"" )
continue;
747 std::string dnatom = downstream_res_to_jump_atom[dnres1];
748 TR <<
"set SYM jump atoms: " << upres <<
":" << upatom <<
" " << dnres <<
":" << dnatom << std::endl;
749 f.set_jump_atoms(i, upatom, dnatom );
757 utility_exit_with_message(
"BAD num_componints");
771 using namespace kinematics;
772 FoldTree f=symm_f, f_new=monomer_f;
781 for (
Size i = 0; i < subunits; ++i ) {
782 int begin ( i*num_res_subunit+1 );
783 int end ( (i+1)*num_res_subunit );
784 f.delete_segment( begin, end );
803 for (
Size i = 1; i <= src_conformation.
size(); ++i ) {
818 using namespace core::conformation::symmetry;
822 dynamic_cast<SymmetricConformation & > ( conformation ) );
825 std::map< Size, SymDof > dofs ( symm_conf.
Symmetry_Info()->get_dofs() );
826 std::map< Size, SymDof > dofs_shifted;
827 std::map< Size, SymDof >::iterator it;
828 std::map< Size, SymDof >::iterator it_begin = dofs.begin();
829 std::map< Size, SymDof >::iterator it_end = dofs.end();
831 for ( it = it_begin; it != it_end; ++it ) {
832 int jump_nbr ( (*it).first + shift );
833 dofs_shifted.insert( std::make_pair( jump_nbr, (*it).second ) );
835 symm_info->set_dofs( dofs_shifted );
851 Size nres_subunit ( symm_info->num_independent_residues() );
854 if ( it->start() <= (
int)nres_subunit && it->stop() <=(
int)nres_subunit ) {
856 }
else if ( it->stop() <= (
int)nres_subunit ) {
858 e_new.
start() = nres_subunit + 1;
886 dynamic_cast<conformation::symmetry::SymmetricConformation const & > ( conf ) );
888 Size nres_subunit ( symm_info->num_independent_residues() );
889 Size nsubunits ( symm_info->subunits() );
890 Size num_nonvrt = symm_info->num_total_residues_without_pseudo();
900 if ( up > nres_subunit ) {
902 TR <<
"symmetrize_fold_tree(): setting anchor to " << new_anchor << std::endl;
905 for (
Size j=0; j<nsubunits; ++j) {
907 new_jumps.push_back( std::pair<int,int>( j*nres_subunit+down, j*nres_subunit+up ) );
914 for (
Size i = 0; i<nsubunits; ++i) {
915 for (
Size j = 1; j<=cuts_vector.size(); ++j ) {
916 if (i*nres_subunit + cuts_vector[j] != num_nonvrt)
917 new_cuts.push_back( i*nres_subunit + cuts_vector[j] );
928 if ( up > num_nonvrt && down > num_nonvrt) {
929 new_jumps.push_back( std::pair<Size,Size>(up,down) );
932 if ( up > num_nonvrt && down <= num_nonvrt) {
933 int subunit_i = symm_info->subunit_index(down);
934 new_jumps.push_back( std::pair<Size,Size>( up, (subunit_i-1)*nres_subunit + new_anchor ) );
937 if ( up <= num_nonvrt && down > num_nonvrt) {
938 int subunit_i = symm_info->subunit_index(up);
939 new_jumps.push_back( std::pair<Size,Size>( (subunit_i-1)*nres_subunit + new_anchor , down ) );
945 for (
Size i = 1; i<=cuts_vector.size(); ++i ) {
946 if ( cuts_vector[i] >= (
int) num_nonvrt)
947 new_cuts.push_back( cuts_vector[i] );
951 ObjexxFCL::FArray1D_int cuts( new_cuts.size() );
952 ObjexxFCL::FArray2D_int jumps( 2, new_jumps.size() );
954 for (
Size i = 1; i<= new_jumps.size(); ++i ) {
955 jumps(1,i) = std::min( (
int)new_jumps[i].first, (
int)new_jumps[i].second);
956 jumps(2,i) = std::max( (
int)new_jumps[i].first, (
int)new_jumps[i].second);
960 for (
Size i = 1; i<= new_cuts.size(); ++i ) {
961 cuts(i) = (
int)new_cuts[i];
996 for (
int i=start; i<=
stop; ++i ) {
1006 center /= (stop-start+1);
1021 Real min_dist = 9999.9;
1023 for (
int i=begin; i<=
end; ++i )
1033 Real tmp_dist( ca_pos.length_squared() );
1034 if ( tmp_dist < min_dist ) {
1036 min_dist = tmp_dist;
1046 std::map<
char,std::pair<Size,Size> >
const & chain2range
1050 Size nreal = nsub * nres_monomer;
1053 std::map<Size,std::string> labels;
1054 for(std::map<
char,std::pair<Size,Size> >::const_iterator i = chain2range.begin(); i != chain2range.end(); ++i) {
1055 for(
Size is = 1; is <= nsub; ++is) {
1056 for(
Size ir = i->second.first; ir <= i->second.second; ++ir) {
1057 labels[(is-1)*nres_monomer+ir] =
std::string(
"Sub") + ObjexxFCL::string_of(is) +
std::string(
"") + i->first;
1064 labels[i->first+Nreal] = i->second;
1066 std::map<Size,char> mark_jump_to_res;
1067 for(
Size i = 1; i <= symm_conf.
fold_tree().num_jump(); ++i) {
1069 mark_jump_to_res[symm_conf.
fold_tree().downstream_jump_residue(i)] =
'*';
1072 for(
Size i = 1; i <= symm_conf.
fold_tree().num_jump(); ++i) {
1075 if( symm_conf.
Symmetry_Info()->jump_is_independent(i) && up > nreal && dn > nreal ) {
1076 mark_jump_to_res[symm_conf.
fold_tree().downstream_jump_residue(i)] =
'=';
1079 std::map<Size,SymDof> dofs( symm_conf.
Symmetry_Info()->get_dofs() );
1080 for(std::map<Size,SymDof>::const_iterator i = dofs.begin(); i != dofs.end(); ++i) {
1082 mark_jump_to_res[symm_conf.
fold_tree().downstream_jump_residue(i->first)] =
'#';
1084 std::map<Size,Size> jump_follows;
1085 for(
Size i = 1; i <= symm_conf.
fold_tree().num_jump(); ++i){
1087 jump_follows[i] = symm_conf.
Symmetry_Info()->jump_follows(i);