Rosetta 3.5
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
MembranePotential.cc
Go to the documentation of this file.
1 // -*- mode:c++;tab-width:2;indent-tabs-mode:t;show-trailing-whitespace:t;rm-trailing-spaces:t -*-
2 // vi: set ts=2 noet:
3 //
4 // (c) Copyright Rosetta Commons Member Institutions.
5 // (c) This file is part of the Rosetta software suite and is made available under license.
6 // (c) The Rosetta software is developed by the contributing members of the Rosetta Commons.
7 // (c) For more information, see http://www.rosettacommons.org. Questions about this can be
8 // (c) addressed to University of Washington UW TechTransfer, email: license@u.washington.edu.
9 
10 /// @file core/scoring/methods/EnvPairPotential.cc
11 /// @brief Membrane Potential
12 /// @author Bjorn Wallner
13 ///
14 
15 
16 // Unit headers
20 
21 // Package headers
22 
23 // AUTO-REMOVED #include <core/scoring/EnergyGraph.hh>
25 
26 // Project headers
27 #include <core/chemical/AA.hh>
31 #include <basic/database/open.hh>
32 #include <core/pose/Pose.hh>
34 #include <basic/datacache/BasicDataCache.hh>
35 
36 //symmetry
38 // AUTO-REMOVED #include <core/conformation/symmetry/util.hh>
39 
42 
43 //options
44 #include <basic/options/option.hh>
45 #include <basic/options/keys/membrane.OptionKeys.gen.hh>
46 #include <basic/options/keys/in.OptionKeys.gen.hh>
47 
48 // Utility headers
49 #include <utility/io/izstream.hh>
50 #include <core/types.hh>
51 
52 
53 #include <utility/vector1.hh>
54 #include <numeric/xyzVector.hh>
55 #include <numeric/xyz.functions.hh>
56 #include <numeric/random/random.hh>
57 #include <numeric/conversions.hh>
58 
59 #include <basic/Tracer.hh>
60 #include <ObjexxFCL/FArray1D.hh>
61 #include <ObjexxFCL/FArray2D.hh>
62 #include <ObjexxFCL/format.hh>
63 
64 namespace core {
65 namespace scoring {
66 static numeric::random::RandomGenerator RG(280628); // <- Magic number, do not change it!
67 static basic::Tracer TR("core.scoring.MembranePotential");
68 
70  CacheableData()
71 {
72  depth_=src.depth_;
73  center_=src.center_;
74  penalty_=src.penalty_;
75  normal_=src.normal_;
76  spanning_=src.spanning_;
78 }
79 
80 void
82 {
83  Size const nres( pose.total_residue() );
84  depth_.resize(nres,0.0);
85  std::fill(depth_.begin(),depth_.end(),30.0); //bw why not?
86  center_.assign(0,0,0);
87  normal_.assign(0,0,1);
88 }
89 
90 
91 
92 
94  //cems transition regions between environment bins
95  //cems transition is from +/- sqrt(36+pad6) +/- sqrt(100+pad10) etc
96  cen_dist5_pad( 0.5 ),
97  cen_dist6_pad( 0.6 ),
98  cen_dist7_pad( 0.65 ),
99  cen_dist10_pad( 1.0 ),
100  cen_dist12_pad( 1.2 ),
101 
102  cen_dist5_pad_plus ( cen_dist5_pad + 25.0 ),
103  cen_dist6_pad_plus( cen_dist6_pad + 36.0 ),
104  cen_dist7_pad_plus ( cen_dist7_pad + 56.25 ),
105  cen_dist10_pad_plus( cen_dist10_pad + 100.0 ),
106  cen_dist12_pad_plus( cen_dist12_pad + 144.0 ),
107 
108  cen_dist5_pad_minus ( cen_dist5_pad - 25.0 ),
109  cen_dist7_pad_minus ( cen_dist7_pad - 56.25 ),
110  cen_dist10_pad_minus( cen_dist10_pad - 100.0 ),
111  cen_dist12_pad_minus( cen_dist12_pad - 144.0 ),
112 
113  cen_dist5_pad_hinv ( 0.5 / cen_dist5_pad ),
114  cen_dist6_pad_hinv ( 0.5 / cen_dist6_pad ),
115  cen_dist7_pad_hinv ( 0.5 / cen_dist7_pad ),
116  cen_dist10_pad_hinv( 0.5 / cen_dist10_pad ),
117  cen_dist12_pad_hinv( 0.5 / cen_dist12_pad ),
118  calculated_(false)
119 
120 {
121  // load the data
122  Size const max_aa( 20 ); // just the standard aa's for now
123  Size const env_log_table_cen6_bins( 15 );
124  Size const env_log_table_cen10_bins( 40 );
125  Size const pair_log_table_size( 5 );
126  Size const cbeta_den_table_size( 45 );
127  Size const max_mem_layers( 3 );
128  Size const min_mem_layers( 2 );
129 
130  //init some variables from command line
131  membrane_normal_cycles_=basic::options::option[basic::options::OptionKeys::membrane::normal_cycles]();
132  membrane_normal_magnitude_=numeric::conversions::radians(basic::options::option[ basic::options::OptionKeys::membrane::normal_mag ]());
133  membrane_center_magnitude_=basic::options::option[ basic::options::OptionKeys::membrane::center_mag ]();
134  smooth_move_frac_=basic::options::option[ basic::options::OptionKeys::membrane::smooth_move_frac ]();
135  no_interpolate_Mpair_=basic::options::option[ basic::options::OptionKeys::membrane::no_interpolate_Mpair ]();
136  Menv_penalties_=basic::options::option[ basic::options::OptionKeys::membrane::Menv_penalties ]();
137  Membed_init_=basic::options::option[ basic::options::OptionKeys::membrane::Membed_init ]();
138  memb_center_search_=basic::options::option[ basic::options::OptionKeys::membrane::center_search ]();
139  memb_normal_search_=basic::options::option[ basic::options::OptionKeys::membrane::normal_search ]();
140  membrane_center_max_delta_=basic::options::option[basic::options::OptionKeys::membrane::center_max_delta]();
141  membrane_normal_start_angle_=basic::options::option[basic::options::OptionKeys::membrane::normal_start_angle]();
142  membrane_normal_delta_angle_=basic::options::option[basic::options::OptionKeys::membrane::normal_delta_angle]();
143  membrane_normal_max_angle_=basic::options::option[basic::options::OptionKeys::membrane::normal_max_angle]();
144  std::string tag,line;
145  chemical::AA aa;
146 
147  { // mem_env_cen6:
148  mem_env_log6_.dimension( max_aa, max_mem_layers,env_log_table_cen6_bins );
149  utility::io::izstream stream;
150  basic::database::open( stream, "scoring/score_functions/MembranePotential/CEN6_mem_env_log.txt" );
151  for ( Size i=1; i<= max_aa; ++i ){
152  getline( stream, line );
153  std::istringstream l(line);
154  l >> tag >> aa;
155  if ( l.fail() || tag != "MEM_ENV_LOG_CEN6:" ) utility_exit_with_message("bad format for scoring/score_functions/MembranePotential/CEN6_mem_env_log.txt (cen6)");
156  for( Size j=1;j<=max_mem_layers;++j) {
157  for( Size k=1;k<=env_log_table_cen6_bins;++k) {
158  l >> mem_env_log6_(aa,j,k);
159  }
160  }
161  }
162  }
163  { // mem_env_cen10:
164  mem_env_log10_.dimension( max_aa, max_mem_layers,env_log_table_cen10_bins );
165 
166  utility::io::izstream stream;
167  basic::database::open( stream, "scoring/score_functions/MembranePotential/CEN10_mem_env_log.txt" );
168  for ( Size i=1; i<= max_aa; ++i ){
169  getline( stream, line );
170  std::istringstream l(line);
171  l >> tag >> aa;
172  if ( l.fail() || tag != "MEM_ENV_LOG_CEN10:" ) utility_exit_with_message("bad format for scoring/score_functions/MembranePotential/CEN10_mem_env_log.txt (cen10)");
173  for( Size j=1;j<=max_mem_layers;++j) {
174  for( Size k=1;k<=env_log_table_cen10_bins;++k) {
175  l >> mem_env_log10_(aa,j,k);
176  }
177  }
178  }
179  }
180 
181  { // cbeta_den_6/12
182  mem_cbeta_den6_.dimension( cbeta_den_table_size );
183  mem_cbeta_den12_.dimension( cbeta_den_table_size );
184  mem_cbeta_2TM_den6_.dimension( cbeta_den_table_size );
185  mem_cbeta_2TM_den12_.dimension( cbeta_den_table_size );
186  mem_cbeta_4TM_den6_.dimension( cbeta_den_table_size );
187  mem_cbeta_4TM_den12_.dimension( cbeta_den_table_size );
188 
189  utility::io::izstream stream;
190  basic::database::open( stream, "scoring/score_functions/MembranePotential/memcbeta_den.txt" );
191 
192  { // den6
193  getline( stream, line );
194  {
195  std::istringstream l(line);
196  l >> tag;
197  for ( Size i=1; i<= cbeta_den_table_size; ++i ){
198  l >>mem_cbeta_den6_(i);
199  }
200  if ( l.fail() || tag != "MEMCBETA_DEN6:" ) utility_exit_with_message("bad format for scoring/score_functions/MembranePotential/memcbeta_den.txt (DEN6)");
201  }
202  getline( stream, line );
203  {
204  std::istringstream l(line);
205  l >> tag;
206  for ( Size i=1; i<= cbeta_den_table_size; ++i ){
207  l >> mem_cbeta_2TM_den6_(i);
208  }
209  if ( l.fail() || tag != "MEMCBETA_2TM_DEN6:" ) utility_exit_with_message("bad format for scoring/score_functions/MembranePotential/memcbeta_den.txt (2TM_DEN6)");
210  }
211  getline( stream, line );
212  {
213  std::istringstream l(line);
214  l >> tag;
215  for ( Size i=1; i<= cbeta_den_table_size; ++i ){
216  l >> mem_cbeta_4TM_den6_(i);
217  }
218  if ( l.fail() || tag != "MEMCBETA_4TM_DEN6:" ) utility_exit_with_message("bad format for scoring/score_functions/MembranePotential/memcbeta_den.txt (4TM_DEN6)");
219  }
220  }
221 
222  {
223  { // den12
224  getline( stream, line );
225  std::istringstream l(line);
226  l >> tag;
227  for ( Size i=1; i<= cbeta_den_table_size; ++i ){
228  l >> mem_cbeta_den12_(i);
229  }
230  if ( l.fail() || tag != "MEMCBETA_DEN12:" ) utility_exit_with_message("bad format for scoring/score_functions/MembranePotential/memcbeta_den.txt (DEN12)");
231  }
232  getline( stream, line );
233  {
234  std::istringstream l(line);
235  l >> tag;
236  for ( Size i=1; i<= cbeta_den_table_size; ++i ){
237  l >> mem_cbeta_2TM_den12_(i);
238  }
239  if ( l.fail() || tag != "MEMCBETA_2TM_DEN12:" ) utility_exit_with_message("bad format for scoring/score_functions/MembranePotential/memcbeta_den.txt (2TM_DEN12)");
240  }
241  getline( stream, line );
242  {
243  std::istringstream l(line);
244  l >> tag;
245  for ( Size i=1; i<= cbeta_den_table_size; ++i ){
246  l >> mem_cbeta_4TM_den12_(i);
247  }
248  if ( l.fail() || tag != "MEMCBETA_4TM_DEN12:" ) utility_exit_with_message("bad format for scoring/score_functions/MembranePotential/memcbeta_den.txt (4TM_DEN12)");
249  }
250 
251  }
252  }
253 
254  { // pair_log
255  mem_pair_log_.dimension( min_mem_layers,pair_log_table_size,max_aa, max_aa );
256 
257  utility::io::izstream stream;
258  basic::database::open( stream, "scoring/score_functions/MembranePotential/mem_pair_log.txt" );
259  for ( Size i=1; i<= min_mem_layers;++i) {
260  for ( Size j=1; j<= pair_log_table_size; ++j ) {
261  for ( Size k=1; k<= max_aa; ++k ) {
262  getline( stream, line );
263  std::istringstream l(line);
264  Size ii,jj;
265  l >> tag >> ii >> jj >> aa;
266  assert( Size(aa) == k );
267  for ( Size n=1;n<=max_aa;++n)
268  {
269  l >> mem_pair_log_(i,j,aa,n);
270  }
271  if ( l.fail() || ii != i || jj != j || tag != "MEM_PAIR_LOG:" ) utility_exit_with_message("scoring/score_functions/MembranePotential/mem_pair_log.txt");
272  }
273 
274  }
275  }
276  }
277 }
278 
279 void
281 {
282  CenListInfo & cenlist( nonconst_cenlist_from_pose( pose ));
283  cenlist.calculated() = false;
284  MembraneEmbed & membrane_embed( nonconst_MembraneEmbed_from_pose( pose ));
285  membrane_embed.calculated() = false;
286 }
287 
288 ////////////////////////////////////////////////////////////////////////////////////
289 void
290 MembranePotential::evaluate_env( //_and_cbeta_scores(
291  pose::Pose const & pose,
292  conformation::Residue const & rsd,
293  Real & membrane_env_score
294 ) const
295 {
296  if(MembraneEmbed_from_pose( pose ).spanning()) {
297  Real termini_pen(0);
298  Real const MembraneDepth (MembraneEmbed_from_pose( pose ).depth(rsd.seqpos() ) );
299  evaluate_env(pose,rsd,MembraneDepth,membrane_env_score);
300  Vector const normal(MembraneEmbed_from_pose( pose ).normal());
301  Vector const center(MembraneEmbed_from_pose( pose ).center());
302  if(Menv_penalties_ && ( rsd.seqpos()==1 || rsd.seqpos()==pose.total_residue() ) ) {
303  Vector const & xyz( pose.residue(rsd.seqpos()).atom( 2 ).xyz() );
304  Real depth=dot(xyz-center,normal)+30;
305  if(depth>18 &&
306  depth<42) {
307  termini_pen++;
308  }
309  membrane_env_score+=50*termini_pen;
310  }
311  }
312  else {
313  //TR << "YS debug: membrane env is 100" << std::endl;
314  membrane_env_score=100;
315  }
316 }
317 
318 ////////////////////////////////////////////////////////////////////////////////////
319 void
320 MembranePotential::evaluate_env( //_and_cbeta_scores(
321  pose::Pose const & pose,
322  conformation::Residue const & rsd,
323  Real const MembraneDepth,
324  Real & membrane_env_score
325 ) const
326 {
327  Real t2 = 2.0;
328  Real t3 = 2.0;
329  int s2 = 14;
330  int s3 = 14;
331  int layer1, layer2, layer/*, B_layer*/; // B_layer will be removed just keep it for now...
332  Real f, z, zn, low;
333 
334  Real const env6_weight=1.0;
335  Real const env10_weight=1.0;
336 
337  Real fcen6 ( cenlist_from_pose( pose ).fcen6( rsd.seqpos() ) );
338  Real fcen10 ( cenlist_from_pose( pose ).fcen10( rsd.seqpos() ) );
339 
340  // in rare cases, the density is over 15 within 6Ã…
341  if (fcen6 > 15) fcen6 = 15 ;
342  if (fcen10 > 40) fcen10 = 40;
343 
344  if ( rsd.is_protein() ) {
345 
346  if ( ( MembraneDepth < 11.0 ) || ( MembraneDepth > 49.0 ) ) {
347  //pure water layer
348  layer = 3;
349  //B_layer = 1; // set but never used ~Labonte
350  Real score6 (env6_weight*mem_env_log6_( rsd.aa(), layer, static_cast< int >( fcen6 ) ));
351  Real score10 (env10_weight* mem_env_log10_( rsd.aa(), layer, static_cast< int >( fcen10 ) ) );
352  membrane_env_score = score6 + score10;
353 
354  }
355  else if ( ( MembraneDepth >= 11.0 && MembraneDepth <= 13.0 ) || ( MembraneDepth >= 47.0 && MembraneDepth <= 49.0 ) ) {
356  //interpolate between water and interface phases
357  layer1 = 2; //interface layer
358  layer2 = 3; //water layer
359  //B_layer = 1; // set but never used ~Labonte
360 
361  if ( MembraneDepth <= 13.0 ) {
362  low = 13.0;
363  } else {
364  low = 47.0;
365  }
366  z = 2*std::abs( (MembraneDepth - low) ) / t2;
367  zn = std::pow( z, s2 );
368  f = zn/(1 + zn);
369 
370  Real score6_layer2( env6_weight*mem_env_log6_( rsd.aa(), layer2, static_cast< int >( fcen6 ) ) );
371  Real score10_layer2( env10_weight* mem_env_log10_( rsd.aa(), layer2, static_cast< int >( fcen10 ) ) );
372  Real score6_layer1( env6_weight*mem_env_log6_( rsd.aa(), layer1, static_cast< int >( fcen6 ) ) );
373  Real score10_layer1( env10_weight*mem_env_log10_( rsd.aa(), layer1, static_cast< int >( fcen10 ) ) );
374 
375  membrane_env_score = f * ( score6_layer2 + score10_layer2 ) + ( 1 - f ) * ( score6_layer1 + score10_layer1 );
376 
377  if ( MembraneDepth <= 12.0 || MembraneDepth >= 48.0 ) {
378  layer = 2;
379  } else {
380  layer = 3;
381  }
382 
383  }
384  else if ( ( MembraneDepth > 13.0 && MembraneDepth < 17.0 ) || ( MembraneDepth > 43.0 && MembraneDepth < 47.0 ) ) {
385  //pure interface phase
386  layer = 2; //interface layer
387  //B_layer = 1; // set but never used ~Labonte
388  Real score6 ( env6_weight*mem_env_log6_( rsd.aa(), layer, static_cast< int >( fcen6 ) ) );
389  Real score10 ( env10_weight*mem_env_log10_( rsd.aa(), layer, static_cast< int >( fcen10 ) ) );
390  membrane_env_score = score6 + score10;
391  }
392  else if ( ( MembraneDepth >= 17.0 && MembraneDepth <= 19.0 ) || ( MembraneDepth >= 41.0 && MembraneDepth <= 43.0 ) ) {
393  //interpolate between interface and hydrophobic phases
394  layer1 = 1; //hydrophobic layer
395  layer2 = 2; //interface layer
396 
397  if ( MembraneDepth <= 19.0 ) {
398  low = 19.0;
399  } else {
400  low = 41.0;
401  }
402  z = 2*std::abs( (MembraneDepth - low) ) / t3;
403  zn = std::pow( z, s3 );
404  f = zn/(1 + zn);
405 
406  Real score6_layer2(env6_weight*mem_env_log6_( rsd.aa(), layer2, static_cast< int >( fcen6 )));
407  Real score10_layer2( env10_weight*mem_env_log10_( rsd.aa(), layer2, static_cast< int >( fcen10 ) ) );
408  Real score6_layer1( env6_weight*mem_env_log6_( rsd.aa(), layer1, static_cast< int >( fcen6 ) ) );
409  Real score10_layer1( env10_weight*mem_env_log10_( rsd.aa(), layer1, static_cast< int >( fcen10 ) ) );
410 
411  membrane_env_score = f * ( score6_layer2 + score10_layer2 ) + ( 1 - f ) * ( score6_layer1 + score10_layer1 );
412 
413  if ( MembraneDepth <= 18.0 || MembraneDepth >= 42.0 ) {
414  layer = 2;
415  //B_layer = 1; // set but never used ~Labonte
416  } else {
417  layer = 1;
418  //B_layer = 2; // set but never used ~Labonte
419  }
420 
421  }
422  else {
423  //pure hydrophobic phase
424  layer = 1;
425  //B_layer = 2; // set but never used ~Labonte
426 
427  Real score6 (env6_weight *mem_env_log6_( rsd.aa(), layer, static_cast< int >( fcen6 ) ));
428  Real score10 (env10_weight*mem_env_log10_( rsd.aa(), layer, static_cast< int >( fcen10 ) ));
429  membrane_env_score = score6+score10;
430  }
431 
432  membrane_env_score*=0.5; //bw membrane_embed_weight...
433 
434  } else { // amino acid check
435  membrane_env_score = 0.0;
436  }
437 }
438 
439 ///////////////////////////////////////////////////////////////////////////////////////////////
440 void
442  pose::Pose const & pose,
443  conformation::Residue const & rsd,
444  Real & membrane_cb_score
445  ) const
446 {
447  membrane_cb_score=0;
448  Real const fcen6 ( cenlist_from_pose( pose ).fcen6( rsd.seqpos() ) );
449  Real const fcen12 ( cenlist_from_pose( pose ).fcen12( rsd.seqpos() ) );
450 
451  Real membrane_cb_score6,membrane_cb_score12;
452 
453  Size const TMHs (MembraneTopology_from_pose( pose ).tmh_inserted() );
454  // interp1 rounds down to nearest (non-negative) integer.
455  int const interp1 = static_cast< int >( fcen6 );
456  int const interp3 = static_cast< int >( fcen12 );
457  // note cen6 is always at least 1.0
458  // fraction remainder after nearest lower integer is removed
459  Real const interp2 = fcen6-interp1;
460  Real const interp4 = fcen12-interp3;
461  if ( TMHs <= 2 ) {
462  membrane_cb_score6 =
463  ( 1.0-interp2 ) * mem_cbeta_2TM_den6_( interp1 )+
464  interp2 * mem_cbeta_2TM_den6_( interp1+1 );
465 
466  } else if ( TMHs <= 4 ) {
467  membrane_cb_score6 =
468  (1.0-interp2) * mem_cbeta_4TM_den6_( interp1 )+
469  interp2 * mem_cbeta_4TM_den6_( interp1+1 );
470 
471  } else {
472  membrane_cb_score6 =
473  (1.0-interp2) * mem_cbeta_den6_( interp1 )+
474  interp2 * mem_cbeta_den6_( interp1+1 );
475  }
476  membrane_cb_score12 =
477  (1.0-interp4) * mem_cbeta_den12_( interp3 )+
478  interp4 * mem_cbeta_den12_( interp3+1 );
479 
480  membrane_cb_score = (membrane_cb_score6+membrane_cb_score12);
481 }
482 
483 ///////////////////////////////////////////////////////////////////////////////////////////////
484 void
486  pose::Pose const & pose,
487  conformation::Residue const & rsd1,
488  conformation::Residue const & rsd2,
489  Real const cendist,
490  Real & membrane_pair_score
491  ) const
492 {
493 
494  membrane_pair_score = 0.0;
495 
496  if ( !rsd1.is_protein() || !rsd2.is_protein() ) return;
497 
498  chemical::AA const aa1( rsd1.aa() );
499  chemical::AA const aa2( rsd2.aa() );
500 
501  //CAR no pair score if a disulfide
502  if ( aa1 == chemical::aa_cys && aa2 == chemical::aa_cys &&
503  rsd1.is_bonded( rsd2 ) && rsd1.polymeric_sequence_distance( rsd2 ) > 1 &&
505 
506  // no pair score for residues closer than 9 in sequence
507  if ( rsd1.polymeric_sequence_distance( rsd2 ) /* j - i */ <= 8 ) return;
508 
509  //$$$ we now try to find which bin the pair distance lies in
510  //$$$ I note this could in principle be calculated and updatded
511  //$$$ just like cen_dist is if there is a need for speed.
512  //$$$ this function interpolates between bins.
513  //$$$ An important(!) requirement on pair_log is that the
514  //$$$ value should approach zero as the radius increases.
515  //$$$ this fact permits us not to have to compute and score pairs are larger
516  //$$$ than cen_dist > cutoff.
517 
518  int icon = 5;
519  Real interp2( 0.0 );
520  //Real interp1( 0.0);
521  Real const MembraneDepth1 (MembraneEmbed_from_pose( pose ).depth(rsd1.seqpos() ) );
522  Real const MembraneDepth2 (MembraneEmbed_from_pose( pose ).depth(rsd2.seqpos() ) );
523 
524  int hydro_layer=1; //1 not_hydrophobic_core 2 hydrophobic core
525  Real AverageDepth=(MembraneDepth1+MembraneDepth2)/2;
526  if(MembraneDepth1 > 18 &&
527  MembraneDepth1 < 42 &&
528  MembraneDepth2 >18 &&
529  MembraneDepth2 <42) //bw currently both residues have to be in the hydrophobic core
530  {
531  hydro_layer=2;
532  }
533 
534  if ( cendist > cen_dist10_pad_plus ) {
535  icon = 4;
536  interp2 = ( cendist + cen_dist12_pad_minus ) * cen_dist12_pad_hinv;
537  } else {
538  if ( cendist > cen_dist7_pad_plus ) {
539  icon = 3;
540  interp2 = ( cendist + cen_dist10_pad_minus ) * cen_dist10_pad_hinv;
541  } else {
542  if ( cendist > cen_dist5_pad_plus ) {
543  icon = 2;
544  interp2 = ( cendist + cen_dist7_pad_minus ) * cen_dist7_pad_hinv;
545  } else {
546  icon = 1;
547  interp2 = ( cendist + cen_dist5_pad_minus ) * cen_dist5_pad_hinv;
548  }
549  }
550  }
551  if ( interp2 < 0.0 ) interp2 = 0.0;
552 
553  // note in theory this will never happen but in practice round off
554  // error can cause problem
555  if ( interp2 > 1.0 ) interp2 = 1.0;
556  // handle last bin specially since icon+1 would be past array end
557  Real f(0);
558  if ( icon != 5 ) {
559  if(!no_interpolate_Mpair_) { //bw new mini specfic, true by default.
560 
561  if( std::abs(AverageDepth - 18)<4)
562  {
563  f=1/(1+std::exp(1.5*(18-AverageDepth)));
564  membrane_pair_score = ( ( 1.0f - interp2 ) * ((1-f)*mem_pair_log_( 1, icon , aa1, aa2 ) + f*mem_pair_log_( 2, icon , aa1, aa2 )) +
565  ( interp2 ) * ((1-f)*mem_pair_log_( 1, icon+1, aa1, aa2 ) + f*mem_pair_log_( 2, icon+1, aa1, aa2 )));
566  } else if(std::abs(AverageDepth - 42)<4) {
567 
568  f=1/(1+std::exp(1.5*(AverageDepth-42)));
569 
570  membrane_pair_score = ( ( 1.0f - interp2 ) * ((1-f)*mem_pair_log_( 1, icon , aa1, aa2 ) + f*mem_pair_log_( 2, icon , aa1, aa2 )) +
571  ( interp2 ) * ((1-f)*mem_pair_log_( 1, icon+1, aa1, aa2 ) + f*mem_pair_log_( 2, icon+1, aa1, aa2 )));
572 
573  } else {
574 
575  membrane_pair_score = ( ( 1.0f - interp2 ) * mem_pair_log_( hydro_layer, icon , aa1, aa2 ) +
576  ( interp2 ) * mem_pair_log_( hydro_layer, icon+1, aa1, aa2 ));
577  }
578  } else {
579  membrane_pair_score = ( ( 1.0f - interp2 ) * mem_pair_log_( hydro_layer, icon , aa1, aa2 ) +
580  ( interp2 ) * mem_pair_log_( hydro_layer, icon+1, aa1, aa2 ));
581  }
582  } else {
583  membrane_pair_score = ( 1.0f - interp2 ) * mem_pair_log_( hydro_layer,icon , aa1, aa2 );
584  }
585  membrane_pair_score*=2.019;
586  return;
587 }
588 
589 void
591 const
592 {
593  using namespace basic::options;
594  using namespace basic::options::OptionKeys;
595  MembraneEmbed & membrane_embed(nonconst_MembraneEmbed_from_pose( pose ));
596 
597  //pba
598  if ( !nonconst_cenlist_from_pose( pose ).calculated() ) {
599  nonconst_cenlist_from_pose( pose ).initialize( pose );
600  }
601 
602  //pba
604  if ( !topology.initialized() ) {
605  if(option[in::file::spanfile].user()) {
606  std::string spanfile(option[OptionKeys::in::file::spanfile]());
607  TR << "Reading spanfile " << spanfile << std::endl;
608  topology.initialize(spanfile);
609  } else {
610  std::cerr << "spanfile missing ... " << std::endl;
611  }
612  }
613 
614  if(!membrane_embed.calculated())
615  {
616  membrane_embed.initialize( pose );
617  Vector init_normal,init_center;
618  init_membrane_center_normal(pose,init_normal,init_center);
619  Real score(0),best_score(999999),accepted_score(99999);
620  Real temperature=2.0;
621  Vector trial_normal(init_normal);
622  Vector trial_center(init_center);
623  Vector orig_trial_center(init_center);
624  Vector orig_trial_normal(init_normal);
625  Vector best_normal(init_normal);
626  Vector best_center(init_center);
627  Vector accepted_center(init_center);
628  Vector accepted_normal(init_normal);
629  score_normal_center(pose,trial_normal,trial_center,best_score);
630  accepted_score=best_score;
631  bool spanning(check_spanning(pose,trial_normal,trial_center));
632  bool best_spanning(spanning);
633  bool debug=option[ membrane::debug ]();
634  Real normal_mag=membrane_normal_magnitude_; //bw tmp
635  Real center_mag=membrane_center_magnitude_; //bw tmp
636  int max_delta_center=membrane_center_max_delta_; //vmyy default 5 A
637  Size alpha_start=membrane_normal_start_angle_; //vmyy default 10 degrees
638  Size delta_alpha=membrane_normal_delta_angle_; //vmyy default 10 degrees
639  Size max_alpha=membrane_normal_max_angle_; //vmyy default 40 degrees
640  Size nres=pose.total_residue();
641  Size counter=0;
642  Size accepted=0;
643  Size thermally_accepted=0;
644 
645  if ( basic::options::option[basic::options::OptionKeys::membrane::fixed_membrane] ) {
646  for ( Size i = 1; i <= nres; ++i ) {
647  Vector const & xyz( pose.residue( i ).atom( 2 ).xyz());
648  membrane_embed.depth(i)=dot(xyz-best_center,best_normal)+30; //bw check that the values used are shifted 30.
649  }
650  membrane_embed.set_normal(best_normal); // defined by init_membrane_center_normal()
651  membrane_embed.set_center(best_center);
652  membrane_embed.spanning()=true; // =best_spanning, temporarily fixed due to the KcsA case, need to figure out a more consistent way (or abadon spanning checking completely) - YS
653  membrane_embed.calculated()=true;
654  return;
655  }
656 
657 
658  //if ( core::pose::symmetry::is_symmetric( pose ) ) {
659  // trial_normal = core::pose::symmetry::get_symm_axis( pose );
660  // orig_trial_normal = trial_normal;
661  //}
662 
664  for ( int delta_center = -max_delta_center; delta_center <= max_delta_center; ++delta_center ) {
665 
666  if ( Membed_init_ ) break; //pba no mb embed optimization; just intial guess
667 
668  trial_center=orig_trial_center;
669  search_memb_center (trial_center,trial_normal,delta_center);
670 
671  if(!check_spanning(pose,trial_normal,trial_center)){
672  if(debug)
673  TR << "delta_center= " << delta_center << " not spanning" << std::endl ;
674  trial_center=accepted_center;
675  trial_normal=accepted_normal;
676  continue;
677  }
678 
679  score_normal_center(pose,trial_normal,trial_center,score);
680 
681  if(score<accepted_score)
682  {
683  if(score<best_score)
684  {
685  best_score=score;
686  best_center=trial_center;
687  best_normal=trial_normal;
688  best_spanning=true;
689  }
690  accepted_score=score;
691  accepted_center=trial_center;
692  accepted_normal=trial_normal;
693  }
694  }
695  //save best projection...
696  for ( Size i = 1; i <= nres; ++i ) {
697  Vector const & xyz( pose.residue( i ).atom( 2 ).xyz());
698  membrane_embed.depth(i)=dot(xyz-best_center,best_normal)+30; //bw check that the values used are shifted 30.
699  }
700  membrane_embed.set_normal(best_normal);
701  membrane_embed.set_center(best_center);
702  membrane_embed.spanning()=best_spanning;
703  membrane_embed.calculated()=true;
704  }
705 
706  if ( memb_normal_search_ ) {
707  for( Size alpha=alpha_start; alpha<= max_alpha; alpha+=delta_alpha ) {
708  for( Size theta=0; theta<360; theta+=60 ) {
709  if ( Membed_init_ ) break; //pba no mb embed optimization; just intial guess
710  trial_normal=orig_trial_normal;
711  search_memb_normal(trial_normal,alpha,theta);
712  if(!check_spanning(pose,trial_normal,trial_center)){
713  if(debug)
714  TR << "alpha = " << alpha << " not spanning" << std::endl ;
715  trial_center=accepted_center;
716  trial_normal=accepted_normal;
717  continue;
718  }
719 
720  score_normal_center(pose,trial_normal,trial_center,score);
721 
722  if(score<accepted_score)
723  {
724  if(score<best_score)
725  {
726  best_score=score;
727  best_center=trial_center;
728  best_normal=trial_normal;
729  best_spanning=true;
730  }
731  accepted_score=score;
732  accepted_center=trial_center;
733  accepted_normal=trial_normal;
734  }
735  }
736  }
737  //save best projection...
738  for ( Size i = 1; i <= nres; ++i ) {
739  Vector const & xyz( pose.residue( i ).atom( 2 ).xyz());
740  membrane_embed.depth(i)=dot(xyz-best_center,best_normal)+30; //bw check that the values used are shifted 30.
741  }
742  membrane_embed.set_normal(best_normal);
743  membrane_embed.set_center(best_center);
744  membrane_embed.spanning()=best_spanning;
745  membrane_embed.calculated()=true;
746  }
747 
749  for( Size cycles=1;cycles<=membrane_normal_cycles_;++cycles)
750  {
751  if ( Membed_init_ ) break; //pba no mb embed optimization; just intial guess
752  temperature = 2.0/cycles;
753  if(RG.uniform()<0.5) // change center
754  {
755  rigid_perturb_vector(trial_center,center_mag);
756  }
757  else // change normal
758  {
759  rot_perturb_vector(trial_normal,normal_mag);
760  }
761  if(!check_spanning(pose,trial_normal,trial_center)){
762  if(debug)
763  TR << "Cycle " << cycles << " not spanning" << std::endl ;
764  trial_center=accepted_center;
765  trial_normal=accepted_normal;
766  continue;
767  }
768  score_normal_center(pose,trial_normal,trial_center,score);
769  if(score<accepted_score)
770  {
771  if(score<best_score)
772  {
773  best_score=score;
774  best_center=trial_center;
775  best_normal=trial_normal;
776  best_spanning=true; //bw if you are here it is spanning....
777  }
778  accepted_score=score;
779  accepted_center=trial_center;
780  accepted_normal=trial_normal;
781  ++accepted;
782  }
783  else
784  {
785  ++counter;
786  Real const boltz_factor=(accepted_score-score)/temperature;
787  Real const probability = std::exp( std::min ((core::Real)40.0, std::max((core::Real)-40.0,boltz_factor)) );
788  if(RG.uniform()<probability)
789  {
790  accepted_score=score;
791  accepted_center=trial_center;
792  accepted_normal=trial_normal;
793  ++thermally_accepted;
794  ++accepted;
795  }
796  else
797  {
798  trial_center=accepted_center;
799  trial_normal=accepted_normal;
800  }
801  }
802  }
803  //save best projection...
804  for ( Size i = 1; i <= nres; ++i ) {
805  Vector const & xyz( pose.residue( i ).atom( 2 ).xyz());
806  membrane_embed.depth(i)=dot(xyz-best_center,best_normal)+30; //bw check that the values used are shifted 30.
807  }
808  membrane_embed.set_normal(best_normal);
809  membrane_embed.set_center(best_center);
810  membrane_embed.spanning()=best_spanning;
811  membrane_embed.calculated()=true;
812  }
813 
814  using namespace ObjexxFCL::fmt;
815  TR << "MembraneCenter " << F(8,3,best_center.x())<< F(8,3,best_center.y())<< F(8,3,best_center.z()) << std::endl;
816  TR << "MembraneNormal " << F(8,3,best_normal.x())<< F(8,3,best_normal.y())<< F(8,3,best_normal.z()) << std::endl;
817  TR << "ATOM 9999 X MEM A 999 " << F(8,3,best_center.x())<< F(8,3,best_center.y())<< F(8,3,best_center.z()) << std::endl;
818  TR << "ATOM 9999 Y MEM A 999 " << F(8,3,best_center.x()+15.*best_normal.x())<< F(8,3,best_center.y()+15.*best_normal.y())<< F(8,3,best_center.z()+15.*best_normal.z()) << std::endl;
819  TR << "ATOM 9999 Z MEM A 999 " << F(8,3,best_center.x()-15.*best_normal.x())<< F(8,3,best_center.y()-15.*best_normal.y())<< F(8,3,best_center.z()-15.*best_normal.z()) << std::endl;
820  }
821 
822 
823 }
824 
825 void
827  Vector & normal,
828  Vector & center) const
829 {
830  if ( basic::options::option[basic::options::OptionKeys::membrane::fixed_membrane] ) {
831  center.zero();
832  normal.zero();
833  normal.z() = 1.0;
834 
835  if ( basic::options::option[basic::options::OptionKeys::membrane::membrane_center].user() ) {
836  center.x() = basic::options::option[basic::options::OptionKeys::membrane::membrane_center]()[1];
837  center.y() = basic::options::option[basic::options::OptionKeys::membrane::membrane_center]()[2];
838  center.z() = basic::options::option[basic::options::OptionKeys::membrane::membrane_center]()[3];
839  }
840  if ( basic::options::option[basic::options::OptionKeys::membrane::membrane_normal].user() ) {
841  normal.x() = basic::options::option[basic::options::OptionKeys::membrane::membrane_normal]()[1];
842  normal.y() = basic::options::option[basic::options::OptionKeys::membrane::membrane_normal]()[2];
843  normal.z() = basic::options::option[basic::options::OptionKeys::membrane::membrane_normal]()[3];
844  }
845  return;
846  }
847 
848  MembraneTopology const & topology( MembraneTopology_from_pose(pose) );
849  //Define vectors for inside and outside cap residue
850  Vector inside(0);
851  Vector outside(0);
852  for(Size i=1;i<=topology.tmhelix();++i)
853  {
854  if(!topology.allow_tmh_scoring(i)) continue;
855  Vector const & start( pose.residue( topology.span_begin(i) ).atom( 2 ).xyz());
856  Vector const & end( pose.residue( topology.span_end(i) ).atom( 2 ).xyz());
857  // all odd helices goes from outside in (from c++)
858  if( topology.helix_id(i) % 2 == 0)
859  {
860  inside+=start;
861  outside+=end;
862  }
863  else
864  {
865  outside+=start;
866  inside+=end;
867  }
868  }
869  normal=outside-inside;
870  normal.normalize();
871  center=0.5*(outside+inside)/topology.tmh_inserted();
872 }
873 
874 void
876  Vector const & normal,
877  Vector const & center,
878  Real & score) const
879 {
880  Size const nres=pose.total_residue();
881  MembraneTopology const & topology( MembraneTopology_from_pose(pose) );
882  score=0;
883  Real residue_score(0);
884  Real tm_projection(0);
885  Real non_helix_pen(0);
886  Real termini_pen(0);
887  for ( Size i = 1; i <= nres; ++i ) {
888  Size rsdSeq(i);
889  if ( core::pose::symmetry::is_symmetric( pose ) ) {
890  using namespace core::conformation::symmetry;
891  SymmetricConformation const & symm_conf (
892  dynamic_cast< SymmetricConformation const & > ( pose.conformation() ) );
893  SymmetryInfoCOP symm_info( symm_conf.Symmetry_Info() );
894  if (!symm_info->bb_is_independent(pose.residue(i).seqpos())) {
895  rsdSeq = symm_info->bb_follows(pose.residue(i).seqpos());
896  }
897  if (symm_info->is_virtual(i)) {
898  rsdSeq = 0;
899  }
900  }
901  if (rsdSeq ==0 ) continue;
902 
903  //CA coords
904  if ( pose.residue(rsdSeq).aa() == core::chemical::aa_vrt ) continue;
905  if(!topology.allow_scoring(rsdSeq)) continue;
906 
907  Vector const & xyz( pose.residue( i ).atom( 2 ).xyz());
908  core::Real depth=dot(xyz-center,normal)+30;
909  evaluate_env(pose,pose.residue(i),depth,residue_score);
910  score+=residue_score;
911  }
912  if(Menv_penalties_) {
913  tm_projection_penalty(pose,normal,center,tm_projection);
914  non_helix_in_membrane_penalty(pose,normal,center,non_helix_pen);
915  termini_penalty(pose,normal,center,termini_pen);
916  score+=tm_projection+non_helix_pen+termini_pen; // bw skipping term_penalty+50.0*term_penalty; //bw 0.5*c++ version.
917  }
918 }
919 
920 void
922  Real const & alpha,
923  Real const & theta) const
924 {
925  Real r_alpha = numeric::conversions::radians(alpha);
926  Real r_theta = numeric::conversions::radians(theta);
927  Vector u(std::sin(r_alpha) * std::cos(r_theta), std::sin(r_alpha) * std::sin(r_theta), std::cos(r_alpha));
928  n=rotation_matrix_degrees(u,alpha)*n;
929 }
930 
931 void
933  Vector & n,
934  Real const & delta) const
935 {
936  c=c+delta*n;
937 }
938 
939 void
941  Real const & std_dev) const
942 {
943  Vector u(numeric::random::gaussian(),numeric::random::gaussian(),numeric::random::gaussian()); //bw rotation_matrix will normalize.
944  Real alpha(numeric::random::gaussian()*std_dev);
945  v=rotation_matrix(u,alpha)*v;
946 }
947 
948 void
950  Real const & std_dev) const
951 {
952  Vector u(numeric::random::gaussian(),numeric::random::gaussian(),numeric::random::gaussian());
953  u.normalize();
954  v=v+std_dev*u;
955 }
956 
957 bool
958 MembranePotential::check_spanning(pose::Pose const & pose, Vector const & normal,Vector const & center) const
959 {
960  MembraneTopology const & topology( MembraneTopology_from_pose(pose) );
961 
962  for(Size i=1;i<=topology.tmhelix()-1;++i)
963  {
964  if(!topology.allow_tmh_scoring(i)) continue;
965  Vector const & start_i( pose.residue( topology.span_begin(i) ).atom( 2 ).xyz());
966  bool start_i_side=(dot(start_i-center,normal) > 0);
967  bool span_check=false;
968  for(Size j=i+1;j<=topology.tmhelix();++j)
969  {
970  if(!topology.allow_tmh_scoring(j) || span_check) continue;
971  span_check=true;
972  Vector const & start_j( pose.residue( topology.span_begin(j) ).atom( 2 ).xyz());
973  bool start_j_side=(dot(start_j-center,normal) > 0);
974  bool coord_para=(start_i_side==start_j_side);
975  if(topology.helix_id(i)-topology.helix_id(j) % 2 == 0) // both should be on the same side (parallel)
976  {
977  if(!(coord_para))
978  {
979  return false;
980  }
981  }
982  else
983  { // should be on opposite sides.
984  if(coord_para)
985  {
986  return false;
987  }
988  }
989  }
990  }
991  return true;
992 }
993 
994 void
996 {
997  tm_proj=0.0;
998  if(!Menv_penalties_)
999  return;
1000  Vector const normal(MembraneEmbed_from_pose( pose ).normal());
1001  Vector const center(MembraneEmbed_from_pose( pose ).center());
1002  tm_projection_penalty(pose,normal,center,tm_proj);
1003 }
1004 
1005 void
1006 MembranePotential::tm_projection_penalty(pose::Pose const & pose, Vector const & normal,Vector const & center,Real & tm_proj) const
1007 {
1008  tm_proj=0.0;
1009  if(!Menv_penalties_)
1010  return;
1011  MembraneTopology const & topology( MembraneTopology_from_pose(pose) );
1012 
1013  //Define vectors for inside and outside cap residue
1014  Vector inside(0);
1015  Vector outside(0);
1016  tm_proj=0;
1017 
1018  for(Size i=1;i<=topology.tmhelix();++i)
1019  {
1020  if(!topology.allow_tmh_scoring(i)) continue;
1021  Vector const & start( pose.residue( topology.span_begin(i) ).atom( 2 ).xyz());
1022  Vector const & end( pose.residue( topology.span_end(i) ).atom( 2 ).xyz());
1023  Real tm_length=std::abs(dot(start-center,normal)-dot(end-center,normal));
1024  Real ratio=tm_length/(topology.span_end(i)-topology.span_begin(i)+1);
1025  if(tm_length<15)
1026  tm_proj++;
1027  if(ratio<1 || ratio > 1.5)
1028  tm_proj++;
1029  }
1030  tm_proj*=50; //total_embed weight is 0.5 in membrane_score_quick.cc
1031 }
1032 
1033 void
1035 {
1036  non_helix_pen=0.0;
1037  if(!Menv_penalties_)
1038  return;
1039  Vector const normal(MembraneEmbed_from_pose( pose ).normal());
1040  Vector const center(MembraneEmbed_from_pose( pose ).center());
1041  non_helix_in_membrane_penalty(pose,normal,center,non_helix_pen);
1042 }
1043 
1044 void
1045 MembranePotential::non_helix_in_membrane_penalty(pose::Pose const & pose, Vector const & normal,Vector const & center,Real & non_helix_pen) const
1046 {
1047  non_helix_pen=0.0;
1048  if(!Menv_penalties_)
1049  return;
1050  MembraneTopology const & topology( MembraneTopology_from_pose(pose) );
1051  for(Size i=1;i<=pose.total_residue();++i)
1052  {
1053  Size rsdSeq(i);
1054  if ( core::pose::symmetry::is_symmetric( pose ) ) {
1055  using namespace core::conformation::symmetry;
1056  SymmetricConformation const & symm_conf (
1057  dynamic_cast< SymmetricConformation const & > ( pose.conformation() ) );
1058  SymmetryInfoCOP symm_info( symm_conf.Symmetry_Info() );
1059  if (!symm_info->bb_is_independent(pose.residue(i).seqpos())) {
1060  rsdSeq = symm_info->bb_follows(pose.residue(i).seqpos());
1061  }
1062  if (symm_info->is_virtual(i)) {
1063  rsdSeq = 0;
1064  }
1065  }
1066  if (rsdSeq ==0 ) continue; // skip virtual residue
1067 
1068  if ( pose.residue(rsdSeq).aa() == core::chemical::aa_vrt ) continue;
1069  if(!topology.allow_scoring(rsdSeq)) continue;
1070  if(topology.tmregion(rsdSeq) && pose.conformation().secstruct(i)!='H') {
1071  Vector const & xyz( pose.residue( i ).atom( 2 ).xyz());
1072  Real depth=dot(xyz-center,normal)+30;
1073  if(depth>18 &&
1074  depth<42) {
1075  non_helix_pen++;
1076  }
1077  }
1078  }
1079  non_helix_pen*=10; //total_embed weight is 0.5 in c++
1080 }
1081 
1082 void
1083 MembranePotential::termini_penalty(pose::Pose const & pose, Real & termini_pen) const
1084 {
1085  termini_pen=0.0;
1086  if(!Menv_penalties_)
1087  return;
1088  Vector const normal(MembraneEmbed_from_pose( pose ).normal());
1089  Vector const center(MembraneEmbed_from_pose( pose ).center());
1090  termini_penalty(pose,normal,center,termini_pen);
1091 }
1092 
1093 void
1094 MembranePotential::termini_penalty(pose::Pose const & pose, Vector const & normal,Vector const & center,Real & termini_pen) const
1095 {
1096  termini_pen=0.0;
1097  if(!Menv_penalties_)
1098  return;
1099  MembraneTopology const & topology( MembraneTopology_from_pose(pose) );
1100 
1101  for(Size i=1;i<=pose.total_residue();++i) {
1102  if (!pose.residue(i).is_terminus()) continue;
1103 
1104  Size rsdSeq(i);
1105  if ( core::pose::symmetry::is_symmetric( pose ) ) {
1106  using namespace core::conformation::symmetry;
1107  SymmetricConformation const & symm_conf (
1108  dynamic_cast< SymmetricConformation const & > ( pose.conformation() ) );
1109  SymmetryInfoCOP symm_info( symm_conf.Symmetry_Info() );
1110  if (!symm_info->bb_is_independent(pose.residue(i).seqpos())) {
1111  rsdSeq = symm_info->bb_follows(pose.residue(i).seqpos());
1112  }
1113  if (symm_info->is_virtual(i)) {
1114  rsdSeq = 0;
1115  }
1116  }
1117  if (rsdSeq ==0 ) continue;
1118 
1119  if ( pose.residue(rsdSeq).aa() == core::chemical::aa_vrt ) continue;
1120  if(topology.allow_scoring(rsdSeq))
1121  {
1122  Vector const & xyz( pose.residue( i ).atom( 2 ).xyz());
1123  Real depth=dot(xyz-center,normal);
1124  if(depth>-12 &&
1125  depth<12) {
1126  termini_pen++;
1127  }
1128  }
1129  }
1130  termini_pen*=50;
1131 }
1132 
1133 /// @details Pose must already contain a cenlist object or this method will fail.
1134 MembraneEmbed const &
1136 {
1137  // ////using core::pose::datacache::CacheableDataType::MEMBRANE_EMBED;
1139  return *( static_cast< MembraneEmbed const * >( pose.data().get_const_ptr( core::pose::datacache::CacheableDataType::MEMBRANE_EMBED )() ));
1140 }
1141 
1142 /// @details Either returns a non-const reference to the cenlist object already stored
1143 /// in the pose, or creates a new cenist object, places it in the pose, and returns
1144 /// a non-const reference to it.
1145 MembraneEmbed &
1147 {
1148  // ////using core::pose::datacache::CacheableDataType::MEMBRANE_EMBED;
1149 
1151  return *( static_cast< MembraneEmbed * >( pose.data().get_ptr( core::pose::datacache::CacheableDataType::MEMBRANE_EMBED )() ));
1152  }
1153  // else
1154  MembraneEmbedOP membrane_embed = new MembraneEmbed;
1155  pose.data().set( core::pose::datacache::CacheableDataType::MEMBRANE_EMBED, membrane_embed );
1156  return *membrane_embed;
1157 }
1158 }
1159 }