Rosetta 3.5
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
RotamericSingleResidueDunbrackLibrary.tmpl.hh
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/dunbrack/RotamericSingleResidueDunbrackLibrary.hh
11 /// @brief Declaration of rotameric rotamer libraries from Jun08 (as opposed to semi-rotameric)
12 /// @author Andrew Leaver-Fay
13 
14 
15 #ifndef INCLUDED_core_pack_dunbrack_RotamericSingleResidueDunbrackLibrary_tmpl_hh
16 #define INCLUDED_core_pack_dunbrack_RotamericSingleResidueDunbrackLibrary_tmpl_hh
17 
18 #if (defined WIN32) && (!defined WIN_PYROSETTA)
19  #define ZLIB_WINAPI // REQUIRED FOR WINDOWS
20 #endif
21 
22 // Unit Headers
24 
25 // Package Headers
30 
31 // Project Headers
34 #include <core/graph/Graph.hh>
37 
38 #include <core/pose/Pose.hh>
39 #include <basic/basic.hh>
40 #include <basic/interpolate.hh>
41 #include <basic/options/option.hh>
42 #include <basic/options/keys/corrections.OptionKeys.gen.hh>
43 
44 // ObjexxFCL Headers
45 #include <ObjexxFCL/FArray2D.hh>
46 #include <ObjexxFCL/FArray3D.hh>
47 
48 // Utility Headers
49 #include <utility/exit.hh>
50 #include <utility/io/izstream.hh>
51 #include <utility/io/ozstream.hh>
52 #include <utility/LexicographicalIterator.hh>
53 
54 // Numeric Headers
55 #include <numeric/random/random.hh>
56 #include <numeric/xyz.functions.hh>
57 #include <numeric/interpolation/spline/Bicubic_spline.hh>
58 
59 // Boost Headers
60 #include <boost/cstdint.hpp>
61 
62 //Auto Headers
63 #include <platform/types.hh>
64 #include <core/types.hh>
65 #include <core/chemical/AA.hh>
67 #include <core/chemical/Adduct.hh>
84 #include <core/chemical/types.hh>
97 #include <core/graph/Graph.fwd.hh>
99 #include <core/id/AtomID.fwd.hh>
100 #include <core/id/DOF_ID.fwd.hh>
104 #include <core/id/TorsionID.fwd.hh>
123 #include <core/pose/PDBInfo.fwd.hh>
125 #include <core/pose/Pose.fwd.hh>
136 #include <utility/Bound.fwd.hh>
137 #include <utility/Bound.hh>
138 #include <utility/LexicographicalIterator.fwd.hh>
139 #include <utility/assert.hh>
140 #include <utility/down_cast.hh>
141 #include <utility/fixedsizearray1.fwd.hh>
142 #include <utility/fixedsizearray1.hh>
143 #include <utility/stream_util.hh>
144 #include <utility/string_util.hh>
145 #include <utility/vector1.fwd.hh>
146 #include <utility/vector1.hh>
147 #include <utility/vector1_bool.hh>
148 #include <utility/vectorL.fwd.hh>
149 #include <utility/vectorL.hh>
150 #include <utility/vectorL_Selector.hh>
151 #include <utility/vectorL_bool.hh>
152 #include <utility/file/FileName.fwd.hh>
153 #include <utility/file/FileName.hh>
154 #include <utility/file/PathName.fwd.hh>
155 #include <utility/file/PathName.hh>
156 #include <utility/file/gzip_util.hh>
157 #include <utility/io/irstream.fwd.hh>
158 #include <utility/io/irstream.hh>
159 #include <utility/io/izstream.fwd.hh>
160 #include <utility/io/mpistream.hh>
161 #include <utility/io/mpistream.ipp>
162 #include <utility/io/orstream.fwd.hh>
163 #include <utility/io/orstream.hh>
164 #include <utility/io/ozstream.fwd.hh>
165 #include <utility/io/zipstream.hpp>
166 #include <utility/io/zipstream.ipp>
167 #include <utility/keys/AutoKey.fwd.hh>
168 #include <utility/keys/AutoKey.hh>
169 #include <utility/keys/Key.fwd.hh>
170 #include <utility/keys/Key.hh>
171 #include <utility/keys/Key2Tuple.fwd.hh>
172 #include <utility/keys/Key2Tuple.hh>
173 #include <utility/keys/Key3Tuple.fwd.hh>
174 #include <utility/keys/Key3Tuple.hh>
175 #include <utility/keys/Key4Tuple.fwd.hh>
176 #include <utility/keys/Key4Tuple.hh>
177 #include <utility/keys/KeyLess.fwd.hh>
178 #include <utility/keys/KeyLookup.fwd.hh>
179 #include <utility/keys/KeyLookup.hh>
180 #include <utility/keys/NoClient.fwd.hh>
181 #include <utility/keys/NoClient.hh>
182 #include <utility/keys/SmallKeyVector.fwd.hh>
183 #include <utility/keys/SmallKeyVector.hh>
184 #include <utility/keys/UserKey.fwd.hh>
185 #include <utility/keys/VariantKey.fwd.hh>
186 #include <utility/keys/VariantKey.hh>
187 #include <utility/options/AnyOption.fwd.hh>
188 #include <utility/options/AnyOption.hh>
189 #include <utility/options/AnyVectorOption.fwd.hh>
190 #include <utility/options/AnyVectorOption.hh>
191 #include <utility/options/BooleanOption.fwd.hh>
192 #include <utility/options/BooleanOption.hh>
193 #include <utility/options/BooleanVectorOption.fwd.hh>
194 #include <utility/options/BooleanVectorOption.hh>
195 #include <utility/options/FileOption.fwd.hh>
196 #include <utility/options/FileOption.hh>
197 #include <utility/options/FileVectorOption.fwd.hh>
198 #include <utility/options/FileVectorOption.hh>
199 #include <utility/options/IntegerOption.fwd.hh>
200 #include <utility/options/IntegerOption.hh>
201 #include <utility/options/IntegerVectorOption.fwd.hh>
202 #include <utility/options/IntegerVectorOption.hh>
203 #include <utility/options/Option.fwd.hh>
204 #include <utility/options/Option.hh>
205 #include <utility/options/OptionCollection.fwd.hh>
206 #include <utility/options/OptionCollection.hh>
207 #include <utility/options/PathOption.fwd.hh>
208 #include <utility/options/PathOption.hh>
209 #include <utility/options/PathVectorOption.fwd.hh>
210 #include <utility/options/PathVectorOption.hh>
211 #include <utility/options/RealOption.fwd.hh>
212 #include <utility/options/RealOption.hh>
213 #include <utility/options/RealVectorOption.fwd.hh>
214 #include <utility/options/RealVectorOption.hh>
215 #include <utility/options/ScalarOption.fwd.hh>
216 #include <utility/options/ScalarOption.hh>
217 #include <utility/options/ScalarOption_T_.fwd.hh>
218 #include <utility/options/ScalarOption_T_.hh>
219 #include <utility/options/StringOption.fwd.hh>
220 #include <utility/options/StringOption.hh>
221 #include <utility/options/StringVectorOption.fwd.hh>
222 #include <utility/options/StringVectorOption.hh>
223 #include <utility/options/VariantOption.fwd.hh>
224 #include <utility/options/VariantOption.hh>
225 #include <utility/options/VectorOption.fwd.hh>
226 #include <utility/options/VectorOption.hh>
227 #include <utility/options/VectorOption_T_.fwd.hh>
228 #include <utility/options/VectorOption_T_.hh>
229 #include <utility/options/mpi_stderr.hh>
230 #include <utility/options/keys/AnyOptionKey.fwd.hh>
231 #include <utility/options/keys/AnyOptionKey.hh>
232 #include <utility/options/keys/AnyVectorOptionKey.fwd.hh>
233 #include <utility/options/keys/AnyVectorOptionKey.hh>
234 #include <utility/options/keys/BooleanOptionKey.fwd.hh>
235 #include <utility/options/keys/BooleanOptionKey.hh>
236 #include <utility/options/keys/BooleanVectorOptionKey.fwd.hh>
237 #include <utility/options/keys/BooleanVectorOptionKey.hh>
238 #include <utility/options/keys/FileOptionKey.fwd.hh>
239 #include <utility/options/keys/FileOptionKey.hh>
240 #include <utility/options/keys/FileVectorOptionKey.fwd.hh>
241 #include <utility/options/keys/FileVectorOptionKey.hh>
242 #include <utility/options/keys/IntegerOptionKey.fwd.hh>
243 #include <utility/options/keys/IntegerOptionKey.hh>
244 #include <utility/options/keys/IntegerVectorOptionKey.fwd.hh>
245 #include <utility/options/keys/IntegerVectorOptionKey.hh>
246 #include <utility/options/keys/OptionKey.fwd.hh>
247 #include <utility/options/keys/OptionKey.hh>
248 #include <utility/options/keys/OptionKeys.hh>
249 #include <utility/options/keys/PathOptionKey.fwd.hh>
250 #include <utility/options/keys/PathOptionKey.hh>
251 #include <utility/options/keys/PathVectorOptionKey.fwd.hh>
252 #include <utility/options/keys/PathVectorOptionKey.hh>
253 #include <utility/options/keys/RealOptionKey.fwd.hh>
254 #include <utility/options/keys/RealOptionKey.hh>
255 #include <utility/options/keys/RealVectorOptionKey.fwd.hh>
256 #include <utility/options/keys/RealVectorOptionKey.hh>
257 #include <utility/options/keys/ScalarOptionKey.fwd.hh>
258 #include <utility/options/keys/ScalarOptionKey.hh>
259 #include <utility/options/keys/StringOptionKey.fwd.hh>
260 #include <utility/options/keys/StringOptionKey.hh>
261 #include <utility/options/keys/StringVectorOptionKey.fwd.hh>
262 #include <utility/options/keys/StringVectorOptionKey.hh>
263 #include <utility/options/keys/VectorOptionKey.fwd.hh>
264 #include <utility/options/keys/VectorOptionKey.hh>
265 #include <utility/options/keys/all.hh>
266 #include <utility/pointer/ReferenceCount.fwd.hh>
267 #include <utility/pointer/ReferenceCount.hh>
268 #include <utility/pointer/access_ptr.fwd.hh>
269 #include <utility/pointer/access_ptr.hh>
270 #include <utility/pointer/owning_ptr.functions.hh>
271 #include <utility/pointer/owning_ptr.fwd.hh>
272 #include <utility/pointer/owning_ptr.hh>
273 #include <utility/signals/BufferedSignalHub.fwd.hh>
274 #include <utility/signals/BufferedSignalHub.hh>
275 #include <utility/signals/Link.fwd.hh>
276 #include <utility/signals/Link.hh>
277 #include <utility/signals/LinkUnit.fwd.hh>
278 #include <utility/signals/LinkUnit.hh>
279 #include <utility/signals/SignalHub.fwd.hh>
280 #include <utility/signals/SignalHub.hh>
281 #include <numeric/NumericTraits.hh>
282 #include <numeric/constants.hh>
283 #include <numeric/conversions.hh>
284 #include <numeric/numeric.functions.hh>
285 #include <numeric/sphericalVector.fwd.hh>
286 #include <numeric/sphericalVector.hh>
287 #include <numeric/trig.functions.hh>
288 #include <numeric/types.hh>
289 #include <numeric/xyz.functions.fwd.hh>
290 #include <numeric/xyzMatrix.fwd.hh>
291 #include <numeric/xyzMatrix.hh>
292 #include <numeric/xyzVector.fwd.hh>
293 #include <numeric/xyzVector.hh>
294 #include <numeric/internal/ColPointers.hh>
295 #include <numeric/internal/ColVectors.hh>
296 #include <numeric/internal/ColsPointer.hh>
297 #include <numeric/internal/RowPointers.hh>
298 #include <numeric/internal/RowVectors.hh>
299 #include <numeric/internal/RowsPointer.hh>
300 #include <numeric/random/random.fwd.hh>
301 #include <numeric/random/uniform.fwd.hh>
302 #include <numeric/random/uniform.hh>
303 #include <ObjexxFCL/Dimension.fwd.hh>
304 #include <ObjexxFCL/Dimension.hh>
305 #include <ObjexxFCL/DimensionExpression.hh>
306 #include <ObjexxFCL/DynamicIndexRange.fwd.hh>
307 #include <ObjexxFCL/DynamicIndexRange.hh>
308 #include <ObjexxFCL/FArray.all.fwd.hh>
309 #include <ObjexxFCL/FArray.fwd.hh>
310 #include <ObjexxFCL/FArray.hh>
311 #include <ObjexxFCL/FArray1.all.fwd.hh>
312 #include <ObjexxFCL/FArray1.fwd.hh>
313 #include <ObjexxFCL/FArray1A.fwd.hh>
314 #include <ObjexxFCL/FArray1D.fwd.hh>
315 #include <ObjexxFCL/FArray1P.fwd.hh>
316 #include <ObjexxFCL/FArray2.all.fwd.hh>
317 #include <ObjexxFCL/FArray2.fwd.hh>
318 #include <ObjexxFCL/FArray2.hh>
319 #include <ObjexxFCL/FArray2A.fwd.hh>
320 #include <ObjexxFCL/FArray2A.hh>
321 #include <ObjexxFCL/FArray2D.fwd.hh>
322 #include <ObjexxFCL/FArray2P.fwd.hh>
323 #include <ObjexxFCL/FArray2P.hh>
324 #include <ObjexxFCL/FArray3.all.fwd.hh>
325 #include <ObjexxFCL/FArray3.fwd.hh>
326 #include <ObjexxFCL/FArray3.hh>
327 #include <ObjexxFCL/FArray3A.fwd.hh>
328 #include <ObjexxFCL/FArray3D.fwd.hh>
329 #include <ObjexxFCL/FArray3P.fwd.hh>
330 #include <ObjexxFCL/FArray4.all.fwd.hh>
331 #include <ObjexxFCL/FArray4.fwd.hh>
332 #include <ObjexxFCL/FArray4A.fwd.hh>
333 #include <ObjexxFCL/FArray4D.fwd.hh>
334 #include <ObjexxFCL/FArray4P.fwd.hh>
335 #include <ObjexxFCL/FArray5.all.fwd.hh>
336 #include <ObjexxFCL/FArray5.fwd.hh>
337 #include <ObjexxFCL/FArray5A.fwd.hh>
338 #include <ObjexxFCL/FArray5D.fwd.hh>
339 #include <ObjexxFCL/FArray5P.fwd.hh>
340 #include <ObjexxFCL/FArray6.all.fwd.hh>
341 #include <ObjexxFCL/FArray6.fwd.hh>
342 #include <ObjexxFCL/FArray6A.fwd.hh>
343 #include <ObjexxFCL/FArray6D.fwd.hh>
344 #include <ObjexxFCL/FArray6P.fwd.hh>
345 #include <ObjexxFCL/FArrayInitializer.fwd.hh>
346 #include <ObjexxFCL/FArrayInitializer.hh>
347 #include <ObjexxFCL/FArraySection.fwd.hh>
348 #include <ObjexxFCL/FArraySection.hh>
349 #include <ObjexxFCL/FArrayTraits.fwd.hh>
350 #include <ObjexxFCL/FArrayTraits.hh>
351 #include <ObjexxFCL/Fmath.hh>
352 #include <ObjexxFCL/IndexRange.fwd.hh>
353 #include <ObjexxFCL/IndexRange.hh>
354 #include <ObjexxFCL/InitializerSentinel.hh>
355 #include <ObjexxFCL/KeyFArray1D.fwd.hh>
356 #include <ObjexxFCL/KeyFArray2D.fwd.hh>
357 #include <ObjexxFCL/KeyFArray3D.fwd.hh>
358 #include <ObjexxFCL/KeyFArray4D.fwd.hh>
359 #include <ObjexxFCL/KeyFArray5D.fwd.hh>
360 #include <ObjexxFCL/KeyFArray6D.fwd.hh>
361 #include <ObjexxFCL/Observer.fwd.hh>
362 #include <ObjexxFCL/Observer.hh>
363 #include <ObjexxFCL/ObserverMulti.hh>
364 #include <ObjexxFCL/ObserverSingle.hh>
365 #include <ObjexxFCL/ProxySentinel.hh>
366 #include <ObjexxFCL/SetWrapper.fwd.hh>
367 #include <ObjexxFCL/Star.fwd.hh>
368 #include <ObjexxFCL/Star.hh>
369 #include <ObjexxFCL/StaticIndexRange.fwd.hh>
370 #include <ObjexxFCL/StaticIndexRange.hh>
371 #include <ObjexxFCL/TypeTraits.hh>
372 #include <ObjexxFCL/char.functions.hh>
373 #include <ObjexxFCL/proxy_const_assert.hh>
374 #include <ObjexxFCL/string.functions.hh>
375 #include <algorithm>
376 #include <cassert>
377 #include <cmath>
378 #include <cstddef>
379 #include <cstdio>
380 #include <cstdlib>
381 #include <fstream>
382 #include <iomanip>
383 #include <ios>
384 #include <iosfwd>
385 #include <iostream>
386 #include <istream>
387 #include <iterator>
388 #include <limits>
389 #include <list>
390 #include <map>
391 #include <ostream>
392 #include <set>
393 #include <sstream>
394 #include <string>
395 #include <typeinfo>
396 #include <utility>
397 #include <vector>
398 #include <basic/MetricValue.fwd.hh>
399 #include <basic/datacache/BasicDataCache.fwd.hh>
400 #include <basic/options/keys/OptionKeys.hh>
401 #include <basic/options/option.hh>
402 #include <boost/algorithm/string/erase.hpp>
403 #include <boost/bind.hpp>
404 #include <boost/config.hpp>
405 #include <boost/function.hpp>
406 #include <boost/pool/detail/mutex.hpp>
407 #include <boost/pool/poolfwd.hpp>
408 #include <zlib/zlib.h>
409 #include <zlib/zutil.h>
410 
411 namespace core {
412 namespace pack {
413 namespace dunbrack {
414 
415 template < Size T >
416 Real const RotamericSingleResidueDunbrackLibrary< T >::PHIPSI_BINRANGE = 10.0;
417 
418 template < Size T >
420  AA const aa_in,
421  bool dun02
422 ) :
423  parent( aa_in, T, dun02 )
424  //max_rotprob_( N_PHIPSI_BINS, N_PHIPSI_BINS, 0.0 )
425 {}
426 
427 template < Size T >
429 {}
430 
431 
432 template < Size T >
433 Real
435  conformation::Residue const & rsd,
437 ) const
438 {
439  return eval_rotameric_energy_deriv( rsd, scratch, false );
440 }
441 
442 
443 template < Size T >
444 Real
446  conformation::Residue const & rsd,
448 ) const
449 {
450  /// most of the work is done in this call
451  Real score = eval_rotameric_energy_deriv( rsd, scratch, true );
452 
453  if ( score != score ) { // NaN check
454  score = 0;
455  std::cerr << "NaN at residue rsd: " << rsd.seqpos() << " " << rsd.name() << std::endl;
456  }
457 
458  if ( score > 1e16 ) { // inf check
459  std::cerr << "inf at residue rsd: " << rsd.seqpos() << " " << rsd.name() << " " << score << std::endl;
460  score = 0;
461  }
462 
463 
464  /// sum derivatives.
465  Real3 & dE_dbb( scratch.dE_dbb() );
466  Real3 & dE_dbb_dev( scratch.dE_dbb_dev() );
467  Real3 & dE_dbb_rot( scratch.dE_dbb_rot() );
468  Real4 & dE_dchi( scratch.dE_dchi() );
469  Real4 & dE_dchi_dev( scratch.dE_dchi_dev() );
470 
471  // p0 - the base probability -- not modified by the chi-dev penalty
472 
473  Size const nbb( std::min( (Size)rsd.mainchain_torsions().size(), DUNBRACK_MAX_BBTOR) );
474 
475  Real const rotprob( scratch.rotprob() );
476  Real const invp( ( rotprob == Real( 0.0 ) ) ? 0.0 : -1.0 / rotprob );
477 
478  for ( Size i=1; i<= nbb; ++i ) {
479  if ( basic::options::option[ basic::options::OptionKeys::corrections::score::use_bicubic_interpolation ] ) {
480  dE_dbb[ i ] = scratch.dneglnrotprob_dbb()[ i ] + scratch.dchidevpen_dbb()[ i ];
481  dE_dbb_dev[ i ] = scratch.dchidevpen_dbb()[ i ];
482  dE_dbb_rot[ i ] = scratch.dneglnrotprob_dbb()[ i ];
483  } else {
484  dE_dbb[ i ] = invp * scratch.drotprob_dbb()[ i ] + scratch.dchidevpen_dbb()[ i ];
485  dE_dbb_dev[ i ] = scratch.dchidevpen_dbb()[ i ];
486  dE_dbb_rot[ i ] = invp * scratch.drotprob_dbb()[ i ];
487  }
488  }
489 
490  for ( Size i=1; i<= T; ++i ) {
491  dE_dchi[ i ] = scratch.dchidevpen_dchi()[ i ];
492  dE_dchi_dev[ i ] = scratch.dchidevpen_dchi()[ i ];
493  }
494 
495  correct_termini_derivatives( rsd, scratch );
496 
497  return score;
498 }
499 
500 template < Size T >
501 Real
503  conformation::Residue const & rsd,
504  RotamerLibraryScratchSpace & scratch,
505  bool eval_deriv
506 ) const
507 {
508 
509  assert( rsd.aa() == aa() );
510 
511  // Grab data from rsd
512  //Size const nbb ( rsd.mainchain_torsions().size() );
513  //Size const nchi( rsd.nchi() );
514  ChiVector const & chi( rsd.chi() );
515  //Real phi( get_phi_from_rsd( rsd ) );
516  //Real psi( get_psi_from_rsd( rsd ) );
517 
518  //Fang-Chieh Chou: Turning the assertion off so the code can be applied to beta-3-amino acids
519  //assert( nbb == 3 && chi.size() == nchi );
520 
521  Real4 & chimean( scratch.chimean() );
522  Real4 & chisd( scratch.chisd() );
523  Real4 & chidev( scratch.chidev() );
524  Real4 & chidevpen( scratch.chidevpen() );
525  Real3 & drotprob_dbb( scratch.drotprob_dbb() );
526  Real3 & dneglnrotprob_dbb( scratch.dneglnrotprob_dbb() ); // for bicubic interpolation
527  Real3 & dchidevpen_dbb( scratch.dchidevpen_dbb() );
528  Real4 & dchidevpen_dchi(scratch.dchidevpen_dchi() );
529  Real4 & dchimean_dphi( scratch.dchimean_dphi() );
530  Real4 & dchimean_dpsi( scratch.dchimean_dpsi() );
531  Real4 & dchisd_dphi( scratch.dchisd_dphi() );
532  Real4 & dchisd_dpsi( scratch.dchisd_dpsi() );
533 
534  std::fill( chimean.begin(), chimean.end(), 0.0 );
535  std::fill( chisd.begin(), chisd.end(), 0.0 );
536  std::fill( chidev.begin(), chidev.end(), 0.0 );
537  std::fill( chidevpen.begin(), chidevpen.end(), 0.0 );
538  std::fill( drotprob_dbb.begin(), drotprob_dbb.end(), 0.0 );
539  std::fill( dneglnrotprob_dbb.begin(), dneglnrotprob_dbb.end(), 0.0 );
540  std::fill( dchidevpen_dbb.begin(), dchidevpen_dbb.end(), 0.0 );
541  std::fill( dchidevpen_dchi.begin(), dchidevpen_dchi.end(), 0.0 );
542  std::fill( dchimean_dphi.begin(), dchimean_dphi.end(), 0.0 );
543  std::fill( dchimean_dpsi.begin(), dchimean_dpsi.end(), 0.0 );
544  std::fill( dchisd_dphi.begin(), dchisd_dphi.end(), 0.0 );
545  std::fill( dchisd_dpsi.begin(), dchisd_dpsi.end(), 0.0 );
546 
547  scratch.fa_dun_tot() = 0;
548  scratch.fa_dun_rot() = 0;
549  scratch.fa_dun_semi() = 0;
550  scratch.fa_dun_dev() = 0;
551 
552 
553  // compute rotamer number from chi
554  Size4 & rotwell( scratch.rotwell() );
555 
556  /// Don't use derived class's version of this function.
557  //std::cout << "RSD " << rsd.seqpos() << " ";
559 
560  Size packed_rotno( rotwell_2_packed_rotno( rotwell ));
561  if ( packed_rotno == 0 ) {
562  // panic! Extremely unlikely rotamer found. Find another rotamer that has at least some probability,
563  // and move this rotamer toward it -- do so in a predictable manner so that the score function is continuous
564  // as it tries to move from this rotamer to another.
565  packed_rotno = find_another_representative_for_unlikely_rotamer( rsd, rotwell );
566  }
567 
568  PackedDunbrackRotamer< T, Real > interpolated_rotamer;
569  interpolate_rotamers( rsd, scratch, packed_rotno, interpolated_rotamer );
570 
571  if ( dun02() ) {
572  for ( Size ii = 1; ii <= T; ++ii ) { chidev[ ii ] = subtract_chi_angles( chi[ ii ], chimean[ ii ], aa(), ii ); }
573  } else {
574  for ( Size ii = 1; ii <= T; ++ii ) { chidev[ ii ] = basic::periodic_range( chi[ ii ] - chimean[ ii ], 360 ); }
575  }
576 
577  //if ( aa() == chemical::aa_arg && rsd.seqpos() == 72 ) {
578  // std::cout << "chimean: ";
579  // for ( Size ii = 1; ii <= T; ++ii ) { std::cout << chimean[ ii ] << " "; }
580  // std::cout << " chisd: ";
581  // for ( Size ii = 1; ii <= T; ++ii ) { std::cout << chisd[ ii ] << " "; }
582  // std::cout << " chidiff: ";
583  // for ( Size ii = 1; ii <= T; ++ii ) { std::cout << chidev[ ii ] << " "; }
584  // std::cout << std::endl;
585  //}
586 
587  for ( Size ii = 1; ii <= T; ++ii ) {
588  /// chidev penalty: define a gaussian with a height of 1 and a standard deviation of chisd[ ii ];
589  /// exp( -1 * (chi_i - chi_mean_i )**2 / ( 2 * chisd_ii**2 ) )
590  /// Pretend this gaussian defines a probability for having an angle at a certain deviation from the mean.
591  /// Convert that probability into an energy:
592  /// -ln p = -ln exp( -1* (chi_i - chi_mean_i)**2/(2 chisd_i**2) ) = (chi_i - chi_mean_i)**2/(2 chisd_i**2)
593  chidevpen[ ii ] = chidev[ ii ]*chidev[ ii ] / ( 2 * chisd[ ii ] * chisd[ ii ] );
594 
595  /// Add in gaussian height normalization
596  /// p = prod( i, 1/(stdv_i*sqrt(2*pi)) * exp( -1* (chi_i - chi_mean_i)**2/(2 chisd_i**2) ) )
597  /// -ln(p) == sum( i, (chi_i - chi_mean_i)**2/(2 chisd_i**2) + log(stdv_i*sqrt(2*pi)) )
598  /// == sum( i, (chi_i - chi_mean_i)**2/(2 chisd_i**2) + log(stdv_i) + log(sqrt(2*pi))) <-- where sum(i,sqrt2pi) is just a constant per amino acid
599  /// and can be treated as part of the reference energies.
600  if ( basic::options::option[ basic::options::OptionKeys::corrections::score::dun_normsd ] ) {
601  chidevpen[ ii ] += /*chidev[ ii ]*chidev[ ii ] / ( 2 * chisd[ ii ] * chisd[ ii ] ) +*/ std::log(chisd[ii]);
602  }
603 
604  }
605  Real chidevpensum( 0.0 );
606  for ( Size ii = 1; ii <= T; ++ii ) {
607  chidevpensum += chidevpen[ ii ];
608  }
609 
610  if ( basic::options::option[ basic::options::OptionKeys::corrections::score::use_bicubic_interpolation ] ) {
611  scratch.fa_dun_tot() = scratch.negln_rotprob() + chidevpensum;
612  scratch.fa_dun_rot() = scratch.negln_rotprob();
613  scratch.fa_dun_dev() = chidevpensum;
614  } else {
615  scratch.fa_dun_rot() = -std::log(scratch.rotprob());
616  scratch.fa_dun_tot() = scratch.fa_dun_rot() + chidevpensum;
617  scratch.fa_dun_dev() = chidevpensum;
618  }
619 
620 
621  Real const score( scratch.fa_dun_tot() );
622 
623  if ( ! eval_deriv ) return score;
624 
625  dchidevpen_dbb[ RotamerLibraryScratchSpace::AA_PHI_INDEX ] = 0.0;
626  dchidevpen_dbb[ RotamerLibraryScratchSpace::AA_PSI_INDEX ] = 0.0;
627  for ( Size ii = 1; ii <= T; ++ii ) {
628 
629  /// Backbone derivatives for chi-dev penalty.
630  /// Xmean_i and sd_i both depend on phi and psi.
631  /// Let: f = (X_i-Xmean_i)**2
632  /// Let: g = 2 sd_i**2
633  /// Then, chidevpen = f/g
634  /// and, dchidevpen = (f'g - fg')/(gg)
635  Real const f = chidev[ ii ]*chidev[ ii ];
636  Real const fprime = -2*chidev[ ii ];
637  Real const g = 2*chisd[ ii ]*chisd[ ii ];
638  Real const gprime = 4*chisd[ ii ];
639  Real const invgg = 1 / (g*g);
640 
641  /// also need to add in derivatives for log(stdv) height normalization
642  /// dE/dphi = (above) + 1/stdv * dstdv/dphi
643  dchidevpen_dbb[ RotamerLibraryScratchSpace::AA_PHI_INDEX ] +=
644  ( g*fprime*dchimean_dphi[ ii ] - f*gprime*dchisd_dphi[ ii ] ) * invgg;
645  scratch.dE_dphi_dev()[ ii ] =
646  ( g*fprime*dchimean_dphi[ ii ] - f*gprime*dchisd_dphi[ ii ] ) * invgg;
647 
648  // Derivatives for the change in the Gaussian height normalization due to sd changing as a function of phi
649  if ( basic::options::option[ basic::options::OptionKeys::corrections::score::dun_normsd ] ) {
650  dchidevpen_dbb[ RotamerLibraryScratchSpace::AA_PHI_INDEX ] += 1/chisd[ii]*dchisd_dphi[ii];
651  scratch.dE_dphi_dev()[ ii ] += 1/chisd[ii]*dchisd_dphi[ii];
652  }
653 
654  dchidevpen_dbb[ RotamerLibraryScratchSpace::AA_PSI_INDEX ] +=
655  ( g*fprime*dchimean_dpsi[ ii ] - f*gprime*dchisd_dpsi[ ii ] ) * invgg;
656  scratch.dE_dpsi_dev()[ ii ] =
657  ( g*fprime*dchimean_dpsi[ ii ] - f*gprime*dchisd_dpsi[ ii ] ) * invgg;
658 
659  // Derivatives for the change in the Gaussian height normalization due to sd changing as a function of psi
660  if ( basic::options::option[ basic::options::OptionKeys::corrections::score::dun_normsd ] ) {
661  dchidevpen_dbb[ RotamerLibraryScratchSpace::AA_PSI_INDEX ] += 1/chisd[ii]*dchisd_dpsi[ii];
662  scratch.dE_dpsi_dev()[ ii ] += 1/chisd[ii]*dchisd_dpsi[ii];
663  }
664 
665  dchidevpen_dchi[ ii ] = chidev[ ii ] / ( chisd[ ii ] * chisd[ ii ] );
666  }
667 
668  return score;
669 }
670 
671 template < Size T >
672 void
674  conformation::Residue const & rsd,
675  RotamerLibraryScratchSpace & scratch,
676  numeric::random::RandomGenerator & RG,
677  ChiVector & new_chi_angles,
678  bool perturb_from_rotamer_center
679 ) const
680 {
681  Size packed_rotno( 0 );
682  assign_random_rotamer( rsd, scratch, RG, new_chi_angles, perturb_from_rotamer_center, packed_rotno );
683 }
684 
685 template < Size T >
686 void
688  conformation::Residue const & rsd,
689  RotamerLibraryScratchSpace & scratch,
690  numeric::random::RandomGenerator & RG,
691  ChiVector & new_chi_angles,
692  bool perturb_from_rotamer_center,
693  Size & packed_rotno
694 ) const
695 {
696  Real random_prob = RG.uniform();
697 
698  Real const phi( get_phi_from_rsd( rsd ) );
699  Real const psi( get_psi_from_rsd( rsd ) );
700 
701  Size phibin, psibin, phibin_next, psibin_next;
702  Real phi_alpha, psi_alpha;
703  get_phipsi_bins( phi, psi, phibin, psibin, phibin_next, psibin_next,phi_alpha, psi_alpha );
704 
705  PackedDunbrackRotamer< T, Real > interpolated_rotamer;
706 
707  /// Go through rotamers in decreasing order by probability and stop when the
708  Size count = 0;
709  while ( random_prob > 0 ) {
710  packed_rotno = rotamers_( phibin, psibin, ++count ).packed_rotno();
711  interpolate_rotamers( scratch, packed_rotno,
712  phibin, psibin, phibin_next, psibin_next,phi_alpha, psi_alpha,
713  interpolated_rotamer );
714  random_prob -= interpolated_rotamer.rotamer_probability();
715  PackedDunbrackRotamer< T, Real > interpolated_rotamer;
716  //loop condition might end up satisfied even if we've walked through all possible rotamers
717  // if the chosen random number was nearly 1
718  // (and interpolation introduced a tiny bit of numerical noise).
719  if ( count == rotamers_.size3() ) break;
720  }
721  assign_chi_for_interpolated_rotamer( interpolated_rotamer, rsd, RG, new_chi_angles, perturb_from_rotamer_center );
722 
723 }
724 
725 template < Size T >
726 void
728  PackedDunbrackRotamer< T, Real > const & interpolated_rotamer,
729  conformation::Residue const & rsd,
730  numeric::random::RandomGenerator & RG,
731  ChiVector & new_chi_angles,
732  bool perturb_from_rotamer_center
733 ) const
734 {
735  new_chi_angles.resize( rsd.nchi() );
736  if ( ! perturb_from_rotamer_center ) {
737  for ( Size ii = 1; ii <= T; ++ii ) {
738  new_chi_angles[ ii ] = interpolated_rotamer.chi_mean( ii );
739  }
740  } else {
741  for ( Size ii = 1; ii <= T; ++ii ) {
742  new_chi_angles[ ii ] = interpolated_rotamer.chi_mean(ii) + RG.gaussian() * interpolated_rotamer.chi_sd(ii);
743  }
744  }
745 
746  /// Set any remaining chi uniformly? ( proton chi)
747  for ( Size ii = T + 1; ii <= rsd.nchi(); ++ii ) {
748  new_chi_angles[ ii ] = RG.uniform()*360.0 - 180.0;
749  }
750 
751 }
752 
753 
754 /// @details The new rotamer library represents only 75 of 81 possible arginine rotamers,
755 /// and 75 of 81 lysine rotamers. In the unlikely event that a rotamer is encountered
756 /// that's not represented in the library, find another rotamer to represent it.
757 /// Ideally, this stand-in rotamer would be closest to the input rotamer in physical geometry.
758 /// (sidechain atom rms, e.g.)
759 /// The following code instead first looks through all possible rotamers with a Hamming distance
760 /// of one from input rotamer trying to find one that works, looking first for rotamers from
761 /// the furthest chi toward the closest chi. If no such rotamer may be found, it gives up and
762 /// returns the most-probable rotamer for a phi-psi bin.
763 ///
764 /// This function modifies the "rotwell" assigned to this rotamer so that later code that relies
765 /// on the consistency of the rotwell and packed_rotno information will behave correctly.
766 template < Size T >
767 Size
769  conformation::Residue const & rsd,
770  Size4 & rotwell
771 ) const
772 {
773  /// Start from the furthest chi and work inwards trying to find another rotamer that could work
774  for ( Size ii = T; ii >= 1; --ii ) {
775  Size ii_orig_value = rotwell[ ii ];
776  for ( Size jj = 1; jj <= 3; ++jj ) { /// 3 == NUMBER OF ROTAMERIC CHI BINS
777  if ( jj == ii_orig_value ) continue;
778  rotwell[ ii ] = jj;
779  Size new_packed_rotno = rotwell_2_packed_rotno( rotwell );
780  if ( new_packed_rotno != 0 ) {
781  return new_packed_rotno;
782  }
783  }
784  /// didn't find one for chi_ii, reset rotwell to original value
785  rotwell[ ii ] = ii_orig_value;
786  }
787 
788  // At this point, we've examined all the rotamer wells with a Hamming distance of 1 from
789  // the input rotamer well and have come up empty.
790  // Just go for the most likely rotamer in this well -- no guarantee that as the rotamer swings from the
791  // current rotamer well to the target rotamer well that it doesn't first swing through some other
792 
793  Size phibin, psibin, phibin_next, psibin_next;
794  Real phi_alpha, psi_alpha;
795  get_phipsi_bins(
796  get_phi_from_rsd( rsd ), get_psi_from_rsd( rsd ),
797  phibin, psibin, phibin_next, psibin_next,phi_alpha, psi_alpha );
798 
799  Size packed_rotno = rotamers_( phibin, psibin, 1 ).packed_rotno();
800  packed_rotno_2_rotwell( packed_rotno, rotwell );
801  return packed_rotno;
802 
803 }
804 
805 template < Size T >
806 void
808  conformation::Residue const & rsd,
810 ) const
811 {
812  // mt: for the termini, these derivatives are 0, because these "pseudo"
813  // mt: torsions are kept fixed.
814  if ( rsd.is_lower_terminus() ) {
819  }
820  if ( rsd.is_upper_terminus() ) {
825  }
826 
827 
828 }
829 
830 /// @brief Returns the energy of the lowest-energy rotamer accessible to the given residue
831 /// (based on e.g. its current phi and psi values).
832 /// If curr_rotamer_only is true, then consider only the idealized version of the
833 /// residue's current rotamer (local optimum); otherwise, consider all rotamers (global optimum).
834 template < Size T >
835 Real
837  conformation::Residue const & rsd,
838  bool curr_rotamer_only,
840 ) const
841 {
842 
843  Real maxprob( 0 );
844  if ( curr_rotamer_only ) {
845  Size4 & rotwell( scratch.rotwell() );
847  Size const packed_rotno = rotwell_2_packed_rotno( rotwell );
848 
849  PackedDunbrackRotamer< T, Real > interpolated_rotamer;
850  interpolate_rotamers( rsd, scratch, packed_rotno, interpolated_rotamer );
851 
852  maxprob = interpolated_rotamer.rotamer_probability();
853  } else {
854  Real const phi( get_phi_from_rsd( rsd ) );
855  Real const psi( get_psi_from_rsd( rsd ) );
856 
857  Size phibin, psibin, phibin_next, psibin_next;
858  Real phi_alpha, psi_alpha;
859  get_phipsi_bins( phi, psi, phibin, psibin, phibin_next, psibin_next,phi_alpha, psi_alpha );
860 
861  utility::vector1< Size > packed_rotnos( 4, 0 );
862 
863  /// check all four bins...
864  packed_rotnos[ 1 ] = rotamers_( phibin, psibin, 1 ).packed_rotno();
865  packed_rotnos[ 2 ] = rotamers_( phibin_next, psibin, 1 ).packed_rotno();
866  packed_rotnos[ 3 ] = rotamers_( phibin, psibin_next, 1 ).packed_rotno();
867  packed_rotnos[ 4 ] = rotamers_( phibin_next, psibin_next, 1 ).packed_rotno();
868 
869  PackedDunbrackRotamer< T, Real > interpolated_rotamer;
870  for ( Size ii = 1; ii <= 4; ++ii ) {
871  interpolate_rotamers( rsd, scratch, packed_rotnos[ ii ], interpolated_rotamer );
872  maxprob = ( maxprob < interpolated_rotamer.rotamer_probability() ?
873  interpolated_rotamer.rotamer_probability() : maxprob );
874  }
875 
876  }
877 
878  //std::cout << "packed_rotno " << curr_rotamer_only << " " << packed_rotno <<
879  // " " << packed_rotno_2_sorted_rotno_( phibin, psibin, packed_rotno ) <<
880  // " " << packed_rotno_2_sorted_rotno_( phibin_next, psibin, packed_rotno ) <<
881  // " " << packed_rotno_2_sorted_rotno_( phibin, psibin_next, packed_rotno ) <<
882  // " " << packed_rotno_2_sorted_rotno_( phibin_next, psibin_next, packed_rotno ) << std::endl;
883 
884 
885  return -1 * std::log( maxprob );
886 }
887 
888 /// @details The Dunbrack library's phi/psi data for a grid point
889 /// (x,y) collects data in the neighborhood of (x,y). As an interpolation
890 /// point p moves toward a grid point (x,y), the (x,y) share in the
891 /// interpolated value goes to 1. This is distinct from having interpolation wells
892 /// where an interpolation in the center of a well produces the maximum contribution
893 /// from that well. Most of the basic::interpolation code is designed for
894 /// the second interpretation of interpolation, and so CTSA's Dunbrack library code did
895 /// funky thinks like shift by 5 degrees so that the basic::interpolation code could
896 /// shift it back by 5 degrees again. The code below makes no such shift.
897 ///
898 /// The alpha fraction is the distance along each axis that the interpolation point
899 /// has progressed from the lower grid point toward the upper grid point; it ranges
900 /// from 0 to 1.
901 template < Size T >
902 void
904  Real phi,
905  Real psi,
906  Size & phibin,
907  Size & psibin,
908  Size & phibin_next,
909  Size & psibin_next,
910  Real & phi_alpha,
911  Real & psi_alpha
912 ) const
913 {
914 
915  parent::bin_angle( -180.0, PHIPSI_BINRANGE, 360.0, N_PHIPSI_BINS, basic::periodic_range( phi, 360 ), phibin, phibin_next, phi_alpha );
916  parent::bin_angle( -180.0, PHIPSI_BINRANGE, 360.0, N_PHIPSI_BINS, basic::periodic_range( psi, 360 ), psibin, psibin_next, psi_alpha );
917 
918  verify_phipsi_bins( phi, psi, phibin, psibin, phibin_next, psibin_next );
919 }
920 
921 template < Size T >
922 void
924  Real phi,
925  Real psi,
926  Size & phibin,
927  Size & psibin
928 ) const
929 {
930  Size phibin_next, psibin_next;
931  Real phi_alpha, psi_alpha;
932  get_phipsi_bins( phi, psi, phibin, psibin, phibin_next, psibin_next, phi_alpha, psi_alpha );
933 }
934 
935 template < Size T >
936 void
938  conformation::Residue const & rsd,
939  RotamerLibraryScratchSpace & scratch,
940  Size const packed_rotno,
941  PackedDunbrackRotamer< T, Real > & interpolated_rotamer
942 ) const
943 {
944  Real phi( get_phi_from_rsd( rsd ) );
945  Real psi( get_psi_from_rsd( rsd ) );
946 
947  Size phibin, psibin, phibin_next, psibin_next;
948  Real phi_alpha, psi_alpha;
949  get_phipsi_bins( phi, psi, phibin, psibin, phibin_next, psibin_next,phi_alpha, psi_alpha );
950 
951  interpolate_rotamers( scratch, packed_rotno, phibin, psibin,
952  phibin_next, psibin_next,phi_alpha, psi_alpha,
953  interpolated_rotamer );
954 
955  /// TEMP!
956  /*Real delta = 1e-12;
957  RotamerLibraryScratchSpace tmpscratch;
958  PackedDunbrackRotamer< T, Real > tmprot;
959  get_phipsi_bins( phi-delta/10, psi, phibin, psibin, phibin_next, psibin_next,phi_alpha, psi_alpha );
960  interpolate_rotamers( tmpscratch, packed_rotno, phibin,psibin,phibin_next, psibin_next, phi_alpha-delta/10, psi_alpha, tmprot );
961  Real Edphim = tmpscratch.negln_rotprob();
962  get_phipsi_bins( phi+delta/10, psi, phibin, psibin, phibin_next, psibin_next,phi_alpha, psi_alpha );
963  interpolate_rotamers( tmpscratch, packed_rotno, phibin,psibin,phibin_next, psibin_next, phi_alpha+delta/10, psi_alpha, tmprot );
964  Real Edphip = tmpscratch.negln_rotprob();
965  get_phipsi_bins( phi, psi-delta/10, phibin, psibin, phibin_next, psibin_next,phi_alpha, psi_alpha );
966  interpolate_rotamers( tmpscratch, packed_rotno, phibin,psibin,phibin_next, psibin_next, phi_alpha, psi_alpha-delta/10, tmprot );
967  Real Edpsim = tmpscratch.negln_rotprob();
968  get_phipsi_bins( phi, psi+delta/10, phibin, psibin, phibin_next, psibin_next,phi_alpha, psi_alpha );
969  interpolate_rotamers( tmpscratch, packed_rotno, phibin,psibin,phibin_next, psibin_next, phi_alpha, psi_alpha+delta/10, tmprot );
970  Real Edpsip = tmpscratch.negln_rotprob();
971 
972  int start_precision = std::cout.precision();
973  std::cout.precision(16);
974  std::cout << "interpolate rotamers: " << aa() << " dE/dphi analytic " << scratch.dneglnrotprob_dbb()[1] << " vs numeric " << (Edphip-Edphim)/(2*delta) <<
975  " dE/dphi analytic " << scratch.dneglnrotprob_dbb()[2] << " vs numeric " << (Edpsip-Edpsim)/(2*delta) << std::endl;
976  std::cout.precision(start_precision);*/
977 }
978 
979 template < Size T >
980 void
982  RotamerLibraryScratchSpace & scratch,
983  Size const packed_rotno,
984  Size const phibin,
985  Size const psibin,
986  Size const phibin_next,
987  Size const psibin_next,
988  Real const phi_alpha,
989  Real const psi_alpha,
990  PackedDunbrackRotamer< T, Real > & interpolated_rotamer
991 ) const
992 {
993  using namespace basic;
994 
995  interpolated_rotamer.packed_rotno() = packed_rotno;
996  Size const
997  sorted_rotno_00( packed_rotno_2_sorted_rotno_( phibin , psibin , packed_rotno )),
998  sorted_rotno_01( packed_rotno_2_sorted_rotno_( phibin , psibin_next, packed_rotno )),
999  sorted_rotno_10( packed_rotno_2_sorted_rotno_( phibin_next, psibin , packed_rotno )),
1000  sorted_rotno_11( packed_rotno_2_sorted_rotno_( phibin_next, psibin_next, packed_rotno ));
1001 
1003  rot00( rotamers_( phibin , psibin , sorted_rotno_00 ) ),
1004  rot01( rotamers_( phibin , psibin_next, sorted_rotno_01 ) ),
1005  rot10( rotamers_( phibin_next, psibin , sorted_rotno_10 ) ),
1006  rot11( rotamers_( phibin_next, psibin_next, sorted_rotno_11 ) );
1007 
1008  /// Note: with bicubic splines to interpolate the energy for a rotamer, bilinear
1009  /// interpolation of the rotamer probabilities no longer serves a useful purpose
1010  /// for the 2002 library. However, the 2008 and 2010 libraries are not yet up to
1011  /// speed with cubic interpolation (requiring tricubic splines), so keep this value
1012  /// around for the moment. Also being preserved for the sake of backwards compatibility.
1013  basic::interpolate_bilinear_by_value(
1014  static_cast< Real > ( rot00.rotamer_probability()),
1015  static_cast< Real > ( rot10.rotamer_probability()),
1016  static_cast< Real > ( rot01.rotamer_probability()),
1017  static_cast< Real > ( rot11.rotamer_probability()),
1018  phi_alpha, psi_alpha, PHIPSI_BINRANGE, false, // treat as angles
1019  scratch.rotprob(),
1022  );
1023 
1024  if ( basic::options::option[ basic::options::OptionKeys::corrections::score::use_bicubic_interpolation ] ) {
1026  rot00.rotE(), rot00.rotE_dsecophi(), rot00.rotE_dsecopsi(), rot00.rotE_dsecophipsi(),
1027  rot01.rotE(), rot01.rotE_dsecophi(), rot01.rotE_dsecopsi(), rot01.rotE_dsecophipsi(),
1028  rot10.rotE(), rot10.rotE_dsecophi(), rot10.rotE_dsecopsi(), rot10.rotE_dsecophipsi(),
1029  rot11.rotE(), rot11.rotE_dsecophi(), rot11.rotE_dsecopsi(), rot11.rotE_dsecophipsi(),
1030  phi_alpha, psi_alpha,
1031  PHIPSI_BINRANGE, PHIPSI_BINRANGE,
1032  scratch.negln_rotprob(),
1035  );
1036  interpolated_rotamer.rotamer_probability() = std::exp( -scratch.negln_rotprob() );
1037  } else {
1038  interpolated_rotamer.rotamer_probability() = scratch.rotprob();
1039  }
1040 
1041  for ( Size ii = 1; ii <= T; ++ii ) {
1042 
1043  interpolate_bilinear_by_value(
1044  static_cast< Real > ( rot00.chi_mean(ii)),
1045  static_cast< Real > ( rot10.chi_mean(ii)),
1046  static_cast< Real > ( rot01.chi_mean(ii)),
1047  static_cast< Real > ( rot11.chi_mean(ii)),
1048  phi_alpha, psi_alpha, PHIPSI_BINRANGE, true /*treat_as_angles*/,
1049  scratch.chimean()[ii], scratch.dchimean_dphi()[ii], scratch.dchimean_dpsi()[ii] );
1050  interpolated_rotamer.chi_mean( ii ) = scratch.chimean()[ii];
1051 
1052  interpolate_bilinear_by_value(
1053  static_cast< Real > ( rot00.chi_sd(ii)),
1054  static_cast< Real > ( rot10.chi_sd(ii)),
1055  static_cast< Real > ( rot01.chi_sd(ii)),
1056  static_cast< Real > ( rot11.chi_sd(ii)),
1057  phi_alpha, psi_alpha, PHIPSI_BINRANGE, false /*treat_as_angles*/,
1058  scratch.chisd()[ii], scratch.dchisd_dphi()[ii], scratch.dchisd_dpsi()[ii] );
1059  interpolated_rotamer.chi_sd( ii ) = scratch.chisd()[ii];
1060 
1061  }
1062 
1063 }
1064 
1065 /// @details Handle lower-term residues by returning a "neutral" phi value
1066 template < Size T >
1067 Real
1069  conformation::Residue const & rsd
1070 ) const
1071 {
1072  assert( rsd.is_protein() );
1073  static Size const RSD_PHI_INDEX = 1; // this shouldn't be here
1074  if ( rsd.is_lower_terminus() ) return parent::NEUTRAL_PHI;
1075  else return rsd.mainchain_torsion( RSD_PHI_INDEX );
1076 }
1077 
1078 /// @details Handle upper-term residues by returning a "neutral" psi value
1079 template < Size T >
1080 Real
1082  conformation::Residue const & rsd
1083 ) const
1084 {
1085  assert( rsd.is_protein() );
1086  static Size const RSD_PSI_INDEX = 2; // this shouldn't be here
1087  if ( rsd.is_upper_terminus() ) return parent::NEUTRAL_PSI;
1088  else return rsd.mainchain_torsion( RSD_PSI_INDEX );
1089 }
1090 
1091 template < Size T >
1092 void
1094  pose::Pose const & pose,
1095  scoring::ScoreFunction const & scorefxn,
1096  pack::task::PackerTask const & task,
1097  graph::GraphCOP packer_neighbor_graph,
1098  chemical::ResidueTypeCOP concrete_residue,
1099  conformation::Residue const & existing_residue,
1100  utility::vector1< utility::vector1< Real > > const & extra_chi_steps,
1101  bool buried,
1102  RotamerVector & rotamers
1103 ) const
1104 {
1106 
1107  /// Save backbone interpolation data for reuse
1108  Real phi( get_phi_from_rsd( existing_residue ) );
1109  Real psi( get_psi_from_rsd( existing_residue ) );
1110  Size phibin, psibin, phibin_next, psibin_next;
1111  Real phi_alpha, psi_alpha;
1112  get_phipsi_bins( phi, psi, phibin, psibin, phibin_next, psibin_next, phi_alpha, psi_alpha );
1113 
1114  Real const requisit_probability = probability_to_accumulate_while_building_rotamers( buried ); // ( buried ? 0.98 : 0.95 )
1115  Real accumulated_probability( 0.0 );
1116 
1117  Size const max_rots_that_can_be_built = n_packed_rots();
1118  Size count_rotamers_built = 0;
1119  while ( accumulated_probability < requisit_probability ) {
1120  // Iterate through rotamaers in decreasing order of probabilities, stopping once the requisit probility is hit.
1121  ++count_rotamers_built;
1122 
1123  Size const packed_rotno00 = rotamers_( phibin, psibin, count_rotamers_built ).packed_rotno();
1124 
1125  PackedDunbrackRotamer< T, Real > interpolated_rotamer;
1127  scratch, packed_rotno00,
1128  phibin, psibin,
1129  phibin_next, psibin_next,phi_alpha, psi_alpha,
1130  interpolated_rotamer );
1131 
1132  build_rotamers(
1133  pose, scorefxn, task, packer_neighbor_graph,
1134  concrete_residue, existing_residue, extra_chi_steps, buried, rotamers,
1135  interpolated_rotamer );
1136 
1137  accumulated_probability += interpolated_rotamer.rotamer_probability();
1138  if ( count_rotamers_built == max_rots_that_can_be_built ) break; // this shouldn't happen...
1139  }
1140 }
1141 
1142 template < Size T >
1145  Real phi,
1146  Real psi
1147 ) const
1148 {
1150 
1151  Size phibin, psibin, phibin_next, psibin_next;
1152  Real phi_alpha, psi_alpha;
1153  get_phipsi_bins( phi, psi, phibin, psibin, phibin_next, psibin_next, phi_alpha, psi_alpha );
1154 
1155  Size const n_rots = n_packed_rots();
1157  all_rots.reserve( n_rots );
1158 
1159  for ( Size ii = 1; ii <= n_rots; ++ii ) {
1160  // Iterate through rotamaers in decreasing order of probabilities
1161  Size const packed_rotno00 = rotamers_( phibin, psibin, ii ).packed_rotno();
1162 
1163  PackedDunbrackRotamer< T, Real > interpolated_rotamer;
1165  scratch, packed_rotno00,
1166  phibin, psibin,
1167  phibin_next, psibin_next,phi_alpha, psi_alpha,
1168  interpolated_rotamer );
1169 
1170  DunbrackRotamerSampleData sample( false );
1171  sample.set_nchi( T );
1172  sample.set_rotwell( parent::packed_rotno_2_rotwell( interpolated_rotamer.packed_rotno() ));
1173  for ( Size jj = 1; jj <= T; ++jj ) sample.set_chi_mean( jj, interpolated_rotamer.chi_mean( jj ) );
1174  for ( Size jj = 1; jj <= T; ++jj ) sample.set_chi_sd( jj, interpolated_rotamer.chi_sd( jj ) );
1175  sample.set_prob( interpolated_rotamer.rotamer_probability() );
1176 
1177  all_rots.push_back( sample );
1178  }
1179  return all_rots;
1180 }
1181 
1182 template < Size T >
1183 Real
1185  Real phi,
1186  Real psi,
1187  Size rot_ind
1188 ) const
1189 {
1190  Size phibin, psibin, phibin_next, psibin_next;
1191  Real phi_alpha, psi_alpha;
1192  get_phipsi_bins( phi, psi, phibin, psibin, phibin_next, psibin_next, phi_alpha, psi_alpha );
1193 
1194  PackedDunbrackRotamer< T > const & rot00( rotamers_( phibin, psibin, rot_ind ) );
1195  Size const packed_rotno00 = rot00.packed_rotno();
1196 
1197  Size const
1198  sorted_rotno_01( packed_rotno_2_sorted_rotno_( phibin , psibin_next, packed_rotno00 )),
1199  sorted_rotno_10( packed_rotno_2_sorted_rotno_( phibin_next, psibin , packed_rotno00 )),
1200  sorted_rotno_11( packed_rotno_2_sorted_rotno_( phibin_next, psibin_next, packed_rotno00 ));
1201 
1203  rot01( rotamers_( phibin , psibin_next, sorted_rotno_01 ) ),
1204  rot10( rotamers_( phibin_next, psibin , sorted_rotno_10 ) ),
1205  rot11( rotamers_( phibin_next, psibin_next, sorted_rotno_11 ) );
1206 
1207  Real rot_prob, dummy1, dummy2;
1208 
1209  basic::interpolate_bilinear_by_value(
1210  static_cast< Real > ( rot00.rotamer_probability()),
1211  static_cast< Real > ( rot10.rotamer_probability()),
1212  static_cast< Real > ( rot01.rotamer_probability()),
1213  static_cast< Real > ( rot11.rotamer_probability()),
1214  phi_alpha, psi_alpha, PHIPSI_BINRANGE, false /*treat_as_angles*/,
1215  rot_prob, dummy1, dummy2
1216  );
1217  return rot_prob;
1218 }
1219 
1220 template < Size T >
1223  Real phi,
1224  Real psi,
1225  Size rot_ind
1226 ) const
1227 {
1229 
1230  Size phibin, psibin, phibin_next, psibin_next;
1231  Real phi_alpha, psi_alpha;
1232  get_phipsi_bins( phi, psi, phibin, psibin, phibin_next, psibin_next, phi_alpha, psi_alpha );
1233 
1234  PackedDunbrackRotamer< T > const & rot00( rotamers_( phibin, psibin, rot_ind ) );
1235  Size const packed_rotno00 = rot00.packed_rotno();
1236  PackedDunbrackRotamer< T, Real > interpolated_rotamer;
1238  scratch, packed_rotno00,
1239  phibin, psibin,
1240  phibin_next, psibin_next,phi_alpha, psi_alpha,
1241  interpolated_rotamer );
1242 
1243  DunbrackRotamerSampleData sample( false );
1244  sample.set_nchi( T );
1245  sample.set_rotwell( parent::packed_rotno_2_rotwell( interpolated_rotamer.packed_rotno() ));
1246  for ( Size jj = 1; jj <= T; ++jj ) sample.set_chi_mean( jj, interpolated_rotamer.chi_mean( jj ) );
1247  for ( Size jj = 1; jj <= T; ++jj ) sample.set_chi_sd( jj, interpolated_rotamer.chi_sd( jj ) );
1248  sample.set_prob( interpolated_rotamer.rotamer_probability() );
1249 
1250  return sample;
1251 }
1252 
1253 
1254 template < Size T >
1255 Size
1257 {
1258  return T;
1259 }
1260 
1261 template < Size T >
1262 Size
1264 {
1265  return parent::n_possible_rots();
1266 }
1267 
1268 
1269 /// @details Load interpolated rotamer data into a RotamericData object on the stack
1270 /// so that it can be handed into the enumerate_chi_sets method, which itself relies
1271 /// on the "template method" chisamples_for_rotamer_and_chi. Enumerate the chi samples,
1272 /// and build rotamers from these chi samples.
1273 ///
1274 /// "template method" is a design pattern where a base class calls a polymorphic method
1275 /// that can be overloaded by a derived class, usually in the middle of a function that
1276 /// does a lot of work. See "Design Patterns," Gamma et al.
1277 template < Size T >
1278 void
1280  pose::Pose const & pose,
1281  scoring::ScoreFunction const & scorefxn,
1282  pack::task::PackerTask const & task,
1283  graph::GraphCOP packer_neighbor_graph,
1284  chemical::ResidueTypeCOP concrete_residue,
1285  conformation::Residue const& existing_residue,
1286  utility::vector1< utility::vector1< Real > > const & extra_chi_steps,
1287  bool buried,
1288  RotamerVector & rotamers,
1289  PackedDunbrackRotamer< T, Real > const & interpolated_rotamer
1290 ) const
1291 {
1292  DunbrackRotamer< T, Real > interpolated_rot( packed_rotamer_2_regular_rotamer( interpolated_rotamer ));
1293  RotamericData< T > rotameric_rotamer_building_data( interpolated_rot );
1294 
1295  // now build the chi sets derived from this base rotamer
1296  utility::vector1< ChiSetOP > chi_set_vector;
1297  enumerate_chi_sets(
1298  *concrete_residue, task, existing_residue.seqpos(), buried,
1299  rotameric_rotamer_building_data,
1300  extra_chi_steps, chi_set_vector );
1301 
1302  create_rotamers_from_chisets(
1303  pose, scorefxn, task,
1304  packer_neighbor_graph, concrete_residue, existing_residue,
1305  chi_set_vector, rotamers );
1306 }
1307 
1308 template < Size T >
1309 void
1311  Real phi,
1312  Real psi,
1313  Size const phibin,
1314  Size const psibin,
1315  Size const phibin_next,
1316  Size const psibin_next
1317 ) const
1318 {
1319  if (( phibin < 1 || phibin > 36 ) || (psibin < 1 || psibin > 36 ) ||
1320  ( phibin_next < 1 || phibin_next > 36 ) || (psibin_next < 1 || psibin_next > 36 )) {
1321  std::cerr << "ERROR: phi/psi bin out of range: " <<
1322  aa() << " " << phi << " " << psi;
1323  std::cerr << phibin << " " << phibin_next << " " << psibin << " " << psibin_next << std::endl;
1324  utility_exit();
1325  }
1326 }
1327 
1328 /// @details once a list of chi samples has been enumerated, this function
1329 /// instantiates Residue objectes and give them the correct geometry.
1330 template < Size T >
1331 void
1333  pose::Pose const & pose,
1334  scoring::ScoreFunction const & scorefxn,
1335  pack::task::PackerTask const & task,
1336  graph::GraphCOP packer_neighbor_graph,
1337  chemical::ResidueTypeCOP concrete_residue,
1338  conformation::Residue const& existing_residue,
1339  utility::vector1< ChiSetOP > const & chi_set_vector,
1340  RotamerVector & rotamers
1341 ) const
1342 {
1343  using namespace utility;
1344  pack::task::ResidueLevelTask const & rtask( task.residue_task( existing_residue.seqpos() ) );
1345 
1346  // construct real rotamers
1347  for ( vector1< ChiSetOP >::const_iterator chi_set( chi_set_vector.begin() );
1348  chi_set != chi_set_vector.end(); ++chi_set ) {
1350  *concrete_residue, existing_residue, pose.conformation(), rtask.preserve_c_beta() );
1351  for ( Size jj = 1; jj <= (*chi_set)->chi.size(); ++jj ) {
1352  rotamer->set_chi( jj, (*chi_set)->chi[ jj ] );
1353  }
1354  // apply an operation (or a filter) to this rotamer at build time
1355  bool reject(false);
1356  for ( pack::rotamer_set::RotamerOperations::const_iterator
1357  op( rtask.rotamer_operations().begin() );
1358  op != rtask.rotamer_operations().end(); ++op ) {
1359  reject |= ! (**op)( rotamer, pose, scorefxn, rtask, packer_neighbor_graph, *chi_set );
1360  }
1361  if ( !reject ) rotamers.push_back( rotamer );
1362  }
1363 }
1364 
1365 template< Size T >
1366 template< class P >
1369  PackedDunbrackRotamer< T, P > const & packedrot
1370 ) const
1371 {
1372  DunbrackRotamer< T, P > dunrot;
1373  for ( Size ii = 1; ii <= T; ++ii ) {
1374  dunrot.chi_mean( ii ) = packedrot.chi_mean( ii );
1375  dunrot.chi_sd( ii ) = packedrot.chi_sd( ii );
1376  dunrot.rotwell( ii ) = packed_rotno_2_rotwell( packedrot.packed_rotno() )[ ii ];
1377  }
1378  dunrot.rotamer_probability() = packedrot.rotamer_probability();
1379  return dunrot;
1380 }
1381 
1382 
1383 template < Size T >
1384 void
1386  chemical::ResidueType const & rsd_type,
1387  pack::task::PackerTask const & task,
1388  Size const seqpos,
1389  bool buried,
1390  RotamericData< T > const & rotamer_data,
1391  utility::vector1< utility::vector1< Real > > const & extra_chi_steps,
1392  utility::vector1< ChiSetOP > & chi_set_vector
1393 ) const
1394 {
1395  Real const base_probability( rotamer_data.rotamer().rotamer_probability() );
1396 
1397  using namespace utility;
1398 
1399  Size const nchi( rsd_type.nchi() );
1400 
1401  vector1< vector1< Real > > total_chi( nchi );
1402  vector1< vector1< int > > total_rot( nchi );
1403  vector1< vector1< Real > > total_ex_steps( nchi ); // remember which extra chi steps were used for each rotamer
1404  vector1< vector1< Real > > chisample_prob( nchi ); // let derived class define sample probability
1405 
1406  pack::task::ResidueLevelTask const & rtask( task.residue_task( seqpos ) );
1407  /// List all chi samples for each chi
1408  for ( Size ii = 1; ii <= nchi; ++ii ) {
1409  chisamples_for_rotamer_and_chi(
1410  rsd_type, rtask, buried, ii, rotamer_data, extra_chi_steps[ ii ],
1411  total_chi[ ii ], total_rot[ ii ], total_ex_steps[ ii ], chisample_prob[ ii ]
1412  );
1413  }
1414 
1415  // now convert from total_chi to chisets....
1416 
1417  Size exchi_product = 1;
1418  utility::vector1< Size > lex_sizes( total_chi.size() );
1419  for ( Size ii = 1; ii <= nchi; ++ii ) {
1420  lex_sizes[ ii ] = total_chi[ii].size();
1421  exchi_product *= total_chi[ii].size();
1422  }
1423 
1424  chi_set_vector.reserve( exchi_product );
1425 
1426  // previously named min_extrachi_rot_prob in rosetta++
1427  Real const minimum_probability_for_extra_rotamers = 0.001; // make this a virtual function call...
1428 
1429  bool first_rotamer( true );
1430  for ( utility::LexicographicalIterator lex( lex_sizes ); ! lex.at_end(); ++lex ) {
1431  Real chi_set_prob = base_probability;
1432 
1433  runtime_assert( nchi <= lex.size() );
1434  runtime_assert( nchi <= chisample_prob.size() );
1435 
1436  for ( Size ii = 1; ii <= nchi; ++ii ) {
1437  if( chisample_prob[ ii ].size() >= lex[ ii ] ){
1438  chi_set_prob *= chisample_prob[ ii ][ lex[ ii ] ];
1439  }
1440  }
1441  if ( ! first_rotamer && chi_set_prob < minimum_probability_for_extra_rotamers ) {
1442  continue;
1443  }
1444  first_rotamer = false;
1445 
1446  ChiSetOP chi_set = new ChiSet( nchi );
1447  for ( Size ii = 1; ii <= nchi; ++ii ) {
1448  chi_set->chi[ ii ] = total_chi[ ii ][ lex[ ii ] ];
1449  chi_set->ex_chi_steps[ ii ] = total_ex_steps[ ii ][ lex[ ii ] ];
1450  chi_set->rot[ ii ] = total_rot[ ii ][ lex[ ii ] ];
1451  }
1452  chi_set_vector.push_back( chi_set );
1453  }
1454 }
1455 
1456 
1457 
1458 template < Size T >
1459 void
1461  chemical::ResidueType const & rsd_type,
1462  pack::task::ResidueLevelTask const & rtask,
1463  bool buried,
1464  Size const chi_index,
1465  RotamericData< T > const & rotamer_data,
1466  utility::vector1< Real > const & extra_steps,
1467  utility::vector1< Real > & total_chi,
1468  utility::vector1< int > & total_rot,
1469  utility::vector1< Real > & total_ex_steps,
1470  utility::vector1< Real > & chisample_prob
1471 ) const
1472 {
1473  //assert( dynamic_cast< RotamericData const & > ( rotamer_data ) );
1474  //RotamericData const & rotameric_data( static_cast< RotamericData const & > ( rotamer_data ) );
1475 
1476  // setting this value to zero disables the small-standdev filter -- is that what we want?
1477  DunbrackReal const min_extrachi_sd( 0.0 );
1478 
1479 
1480  if ( chi_index > T ) {
1481  // chi angle not present in dunbrack library, eg. ser,thr,tyr Hchi
1482 
1483  utility::vector1< std::pair< Real, Real > > const & chi_rotamers( rsd_type.chi_rotamers( chi_index ) );
1484  if ( ! chi_rotamers.empty() ) {
1485  // use the rotamer info encoded in the residue
1486  for ( Size j=1; j<= chi_rotamers.size(); ++j ) {
1487  Real const rot_chi_mean( chi_rotamers[j].first );
1488  Real const rot_chi_sdev( chi_rotamers[j].second );
1489  total_chi.push_back( rot_chi_mean );
1490  total_ex_steps.push_back( 0. );
1491  total_rot.push_back( j );
1492  for ( Size k=1; k<= extra_steps.size(); ++k ) {
1493  total_chi.push_back( rot_chi_mean + extra_steps[k] * rot_chi_sdev );
1494  total_ex_steps.push_back( extra_steps[k] );
1495  total_rot.push_back( j );
1496  chisample_prob.push_back( 1.0 ); // assume perfectly likely rotamer sample?
1497  }
1498  }
1499  } else if ( rsd_type.is_proton_chi( chi_index ) ) {
1500  pack::task::ExtraRotSample ex_samp_level = rtask.extrachi_sample_level( buried, chi_index, &rsd_type );
1501 
1502  //std::cout << "chi_index: " << chi_index << " ex_samp_level " << ex_samp_level << std::endl;
1503  bool const skip_extra_proton_chi_samples = ( ex_samp_level == pack::task::NO_EXTRA_CHI_SAMPLES );
1504 
1505  Size const proton_chi_index = rsd_type.chi_2_proton_chi( chi_index );
1506  utility::vector1< Real > const & samples = rsd_type.proton_chi_samples( proton_chi_index );
1507  utility::vector1< Real > const & extra_samples = rsd_type.proton_chi_extra_samples( proton_chi_index );
1508  for ( Size ii = 1; ii <= samples.size(); ++ii ) {
1509  total_chi.push_back( samples[ ii ] );
1510  total_ex_steps.push_back( 0.0 );
1511  total_rot.push_back( 1 );
1512  chisample_prob.push_back( 1.0 );
1513 
1514  if ( skip_extra_proton_chi_samples ) continue;
1515 
1516  for ( Size jj = 1; jj <= extra_samples.size(); ++jj ) {
1517  total_chi.push_back( samples[ ii ] + extra_samples[ jj ] );
1518  total_ex_steps.push_back( 0.0 );
1519  total_rot.push_back( 1 );
1520  chisample_prob.push_back( 1.0 );
1521 
1522  total_chi.push_back( samples[ ii ] - extra_samples[ jj ] );
1523  total_ex_steps.push_back( 0.0 );
1524  total_rot.push_back( 1 );
1525  chisample_prob.push_back( 1.0 );
1526  }
1527  }
1528 
1529  } else {
1530  // just use the chi of the platonic residue -- this could be made faster, but chi is not part of rsdtype intrfc
1531  // Is this code ever executed? It's not going to be executed for any amino acid...
1532  Real const icoor_chi( numeric::dihedral(
1533  rsd_type.atom( rsd_type.chi_atoms( chi_index )[1] ).ideal_xyz(),
1534  rsd_type.atom( rsd_type.chi_atoms( chi_index )[2] ).ideal_xyz(),
1535  rsd_type.atom( rsd_type.chi_atoms( chi_index )[3] ).ideal_xyz(),
1536  rsd_type.atom( rsd_type.chi_atoms( chi_index )[4] ).ideal_xyz()
1537  ));
1538  total_chi.push_back( icoor_chi );
1539  total_ex_steps.push_back( 0. );
1540  total_rot.push_back( 1 );
1541  chisample_prob.push_back( 1.0 );
1542  }
1543  } else {
1544  // use the dunbrack data
1545 
1546  total_chi.push_back( rotamer_data.rotamer().chi_mean( chi_index ) );
1547  total_ex_steps.push_back( 0. );
1548  total_rot.push_back( rotamer_data.rotamer().rotwell( chi_index ) );
1549  chisample_prob.push_back( 1.0 );
1550 
1551  // ctsa - eliminate extra chi angles with insignificant sd's
1552  if ( rotamer_data.rotamer().chi_sd( chi_index ) <= min_extrachi_sd ) return;
1553 
1554  for ( Size k=1; k<= extra_steps.size(); ++k ) {
1555  total_chi.push_back( rotamer_data.rotamer().chi_mean( chi_index )
1556  + extra_steps[k] * rotamer_data.rotamer().chi_sd( chi_index ) );
1557  total_ex_steps.push_back( extra_steps[k] );
1558  total_rot.push_back( rotamer_data.rotamer().rotwell( chi_index ) );
1559  /// prob = exp( -( x - xmean )**2 / 2sd**2). Since we're sampling at intrvals of sd,
1560  /// prob = exp( -( step * sd )**2 / 2sd**2 ) = exp( - step**2/2 ).
1561  /// of course, a true gaussian probability would be scaled by 1/sd(2p)**0.5...
1562  chisample_prob.push_back( std::exp( -0.5 * (extra_steps[ k ]*extra_steps[ k ])) );
1563 
1564  }
1565  }
1566 }
1567 
1568 //XRW_B_T1
1569 /*
1570 template < Size T >
1571 SingleResidueRotamerLibraryOP
1572 RotamericSingleResidueDunbrackLibrary< T >::coarsify(coarse::Translator const & map) const
1573 {
1574  utility_exit_with_message("Unimplemented!");
1575  return 0;
1576 }
1577 */
1578 //XRW_E_T1
1579 
1580 template < Size T >
1581 void
1582 RotamericSingleResidueDunbrackLibrary< T >::write_to_file( utility::io::ozstream & /*out*/ ) const
1583 {
1584  utility_exit_with_message("Unimplemented!");
1585 }
1586 
1587 template < Size T >
1588 void
1590 {
1591  using namespace boost;
1592 
1593  parent::write_to_binary( out );
1594 
1595  /// 1. rotamers_
1596  {
1597  Size const ntotalrot = N_PHIPSI_BINS * N_PHIPSI_BINS * parent::n_packed_rots();
1598  Size const ntotalchi = ntotalrot * T;
1599  ///a. means
1600  DunbrackReal * rotamer_means = new DunbrackReal[ ntotalchi ];
1601  // b. standard deviations
1602  DunbrackReal * rotamer_stdvs = new DunbrackReal[ ntotalchi ];
1603  // c. rotamer probabilities
1604  DunbrackReal * rotamer_probs = new DunbrackReal[ ntotalrot ];
1605  // d. bicubic polynomial parameters
1606  DunbrackReal * rotamer_neglnprobs = new DunbrackReal[ ntotalrot ];
1607  DunbrackReal * rotamer_neglnprob_d2dphi2 = new DunbrackReal[ ntotalrot ];
1608  DunbrackReal * rotamer_neglnprob_d2dpsi2 = new DunbrackReal[ ntotalrot ];
1609  DunbrackReal * rotamer_neglnprob_d4dphi2psi2 = new DunbrackReal[ ntotalrot ];
1610  // e. packed rotamer numbers
1611  DunbrackReal * packed_rotnos = new DunbrackReal[ ntotalrot ];
1612  Size count_chi( 0 ), count_rots( 0 );
1613  for ( Size ii = 1; ii <= parent::n_packed_rots(); ++ii ) {
1614  for ( Size jj = 1; jj <= N_PHIPSI_BINS; ++jj ) {
1615  for ( Size kk = 1; kk <= N_PHIPSI_BINS; ++kk ) {
1616  for ( Size ll = 1; ll <= T; ++ll ) {
1617  rotamer_means[ count_chi ] = rotamers_( kk, jj, ii ).chi_mean( ll );
1618  rotamer_stdvs[ count_chi ] = rotamers_( kk, jj, ii ).chi_sd( ll );
1619  ++count_chi;
1620  }
1621  rotamer_probs[ count_rots ] = rotamers_( kk, jj, ii ).rotamer_probability();
1622  rotamer_neglnprobs[ count_rots ] = rotamers_( kk, jj, ii ).rotE();
1623  rotamer_neglnprob_d2dphi2[ count_rots ] = rotamers_( kk, jj, ii ).rotE_dsecophi();
1624  rotamer_neglnprob_d2dpsi2[ count_rots ] = rotamers_( kk, jj, ii ).rotE_dsecopsi();
1625  rotamer_neglnprob_d4dphi2psi2[ count_rots ] = rotamers_( kk, jj, ii ).rotE_dsecophipsi();
1626  packed_rotnos[ count_rots ] = rotamers_( kk, jj, ii ).packed_rotno();
1627  ++count_rots;
1628  }
1629  }
1630  }
1631  out.write( (char*) rotamer_means, ntotalchi * sizeof( DunbrackReal ));
1632  out.write( (char*) rotamer_stdvs, ntotalchi * sizeof( DunbrackReal ));
1633  out.write( (char*) rotamer_probs, ntotalrot * sizeof( DunbrackReal ));
1634  out.write( (char*) rotamer_neglnprobs, ntotalrot * sizeof( DunbrackReal ));
1635  out.write( (char*) rotamer_neglnprob_d2dphi2, ntotalrot * sizeof( DunbrackReal ));
1636  out.write( (char*) rotamer_neglnprob_d2dpsi2, ntotalrot * sizeof( DunbrackReal ));
1637  out.write( (char*) rotamer_neglnprob_d4dphi2psi2, ntotalrot * sizeof( DunbrackReal ));
1638  out.write( (char*) packed_rotnos, ntotalrot * sizeof( DunbrackReal ));
1639  delete [] rotamer_means;
1640  delete [] rotamer_stdvs;
1641  delete [] rotamer_probs;
1642  delete [] rotamer_neglnprobs;
1643  delete [] rotamer_neglnprob_d2dphi2;
1644  delete [] rotamer_neglnprob_d2dpsi2;
1645  delete [] rotamer_neglnprob_d4dphi2psi2;
1646  delete [] packed_rotnos;
1647  }
1648 
1649  /// 2. packed_rotno_to_sorted_rotno_
1650  {
1651  Size const ntotalpackedrots = N_PHIPSI_BINS * N_PHIPSI_BINS * parent::n_packed_rots();
1652  boost::int32_t * packed_rotno_2_sorted_rotno = new boost::int32_t[ ntotalpackedrots ];
1653  Size count( 0 );
1654  for ( Size ii = 1; ii <= parent::n_packed_rots(); ++ii ) {
1655  for ( Size jj = 1; jj <= N_PHIPSI_BINS; ++jj ) {
1656  for ( Size kk = 1; kk <= N_PHIPSI_BINS; ++kk ) {
1657  packed_rotno_2_sorted_rotno[ count ] = packed_rotno_2_sorted_rotno_( kk, jj, ii );
1658  ++count;
1659  }
1660  }
1661  }
1662  out.write( (char*) packed_rotno_2_sorted_rotno, ntotalpackedrots * sizeof( boost::int32_t ) );
1663  delete [] packed_rotno_2_sorted_rotno;
1664  }
1665 }
1666 
1667 template < Size T >
1668 void
1670 {
1671  parent::read_from_binary( in );
1672  /// 1. rotamers_
1673  {
1674  Size const ntotalrot = N_PHIPSI_BINS * N_PHIPSI_BINS * parent::n_packed_rots();
1675  Size const ntotalchi = ntotalrot * T;
1676  rotamers_.dimension( N_PHIPSI_BINS, N_PHIPSI_BINS, parent::n_packed_rots() );
1677  ///a. means
1678  DunbrackReal * rotamer_means = new DunbrackReal[ ntotalchi ];
1679  // b. standard deviations
1680  DunbrackReal * rotamer_stdvs = new DunbrackReal[ ntotalchi ];
1681  // c. rotamer probabilities
1682  DunbrackReal * rotamer_probs = new DunbrackReal[ ntotalrot ];
1683  // d. bicubic polynomial parameters
1684  DunbrackReal * rotamer_neglnprobs = new DunbrackReal[ ntotalrot ];
1685  DunbrackReal * rotamer_neglnprob_d2dphi2 = new DunbrackReal[ ntotalrot ];
1686  DunbrackReal * rotamer_neglnprob_d2dpsi2 = new DunbrackReal[ ntotalrot ];
1687  DunbrackReal * rotamer_neglnprob_d4dphi2psi2 = new DunbrackReal[ ntotalrot ];
1688  // e. packed rotamer numbers
1689  DunbrackReal * packed_rotnos = new DunbrackReal[ ntotalrot ];
1690 
1691  in.read( (char*) rotamer_means, ntotalchi * sizeof( DunbrackReal ));
1692  in.read( (char*) rotamer_stdvs, ntotalchi * sizeof( DunbrackReal ));
1693  in.read( (char*) rotamer_probs, ntotalrot * sizeof( DunbrackReal ));
1694  in.read( (char*) rotamer_neglnprobs, ntotalrot * sizeof( DunbrackReal ));
1695  in.read( (char*) rotamer_neglnprob_d2dphi2, ntotalrot * sizeof( DunbrackReal ));
1696  in.read( (char*) rotamer_neglnprob_d2dpsi2, ntotalrot * sizeof( DunbrackReal ));
1697  in.read( (char*) rotamer_neglnprob_d4dphi2psi2, ntotalrot * sizeof( DunbrackReal ));
1698  in.read( (char*) packed_rotnos, ntotalrot * sizeof( DunbrackReal ));
1699 
1700  Size count_chi( 0 ), count_rots( 0 );
1701  for ( Size ii = 1; ii <= parent::n_packed_rots(); ++ii ) {
1702  for ( Size jj = 1; jj <= N_PHIPSI_BINS; ++jj ) {
1703  for ( Size kk = 1; kk <= N_PHIPSI_BINS; ++kk ) {
1704  for ( Size ll = 1; ll <= T; ++ll ) {
1705  rotamers_( kk, jj, ii ).chi_mean( ll ) = rotamer_means[ count_chi ];
1706  rotamers_( kk, jj, ii ).chi_sd( ll ) = rotamer_stdvs[ count_chi ];
1707  ++count_chi;
1708  }
1709  rotamers_( kk, jj, ii ).rotamer_probability() = rotamer_probs[ count_rots ];
1710  rotamers_( kk, jj, ii ).rotE() = rotamer_neglnprobs[ count_rots ];
1711  rotamers_( kk, jj, ii ).rotE_dsecophi() = rotamer_neglnprob_d2dphi2[ count_rots ];
1712  rotamers_( kk, jj, ii ).rotE_dsecopsi() = rotamer_neglnprob_d2dpsi2[ count_rots ];
1713  rotamers_( kk, jj, ii ).rotE_dsecophipsi() = rotamer_neglnprob_d4dphi2psi2[ count_rots ];
1714  rotamers_( kk, jj, ii ).packed_rotno() = ( Size ) packed_rotnos[ count_rots ];
1715  ++count_rots;
1716  }
1717  }
1718  }
1719  delete [] rotamer_means;
1720  delete [] rotamer_stdvs;
1721  delete [] rotamer_probs;
1722  delete [] rotamer_neglnprobs;
1723  delete [] rotamer_neglnprob_d2dphi2;
1724  delete [] rotamer_neglnprob_d2dpsi2;
1725  delete [] rotamer_neglnprob_d4dphi2psi2;
1726  delete [] packed_rotnos;
1727  }
1728 
1729  /// 2. packed_rotno_to_sorted_rotno_
1730  {
1731  Size const ntotalpackedrots = N_PHIPSI_BINS * N_PHIPSI_BINS * parent::n_packed_rots();
1732  boost::int32_t * packed_rotno_2_sorted_rotno = new boost::int32_t[ ntotalpackedrots ];
1733  in.read( (char*) packed_rotno_2_sorted_rotno, ntotalpackedrots * sizeof( boost::int32_t ) );
1734  Size count( 0 );
1735  packed_rotno_2_sorted_rotno_.dimension( N_PHIPSI_BINS, N_PHIPSI_BINS, parent::n_packed_rots() );
1736  for ( Size ii = 1; ii <= parent::n_packed_rots(); ++ii ) {
1737  for ( Size jj = 1; jj <= N_PHIPSI_BINS; ++jj ) {
1738  for ( Size kk = 1; kk <= N_PHIPSI_BINS; ++kk ) {
1739  packed_rotno_2_sorted_rotno_( kk, jj, ii ) = packed_rotno_2_sorted_rotno[ count ];
1740  ++count;
1741  }
1742  }
1743  }
1744  delete [] packed_rotno_2_sorted_rotno;
1745  }
1746 }
1747 
1748 /// @details Returns the three letter string of the next amino acid specified in the
1749 /// input library.
1750 template < Size T >
1753  utility::io::izstream & infile,
1754  bool first_line_three_letter_code_already_read
1755 )
1756 {
1757  std::string const my_name( chemical::name_from_aa( aa() ) );
1758  std::string next_name; // empty string to start
1759 
1760  /// Read all the data from the first phi/psi bin and keep it temporarily.
1761  /// Note all the rotamer wells encountered along the way; then declare_all_rotwells_encountered,
1762  /// allocate the big tables, transfer the data in the temporary arrays into the big table,
1763  typename utility::vector1< DunbrackRotamer< T > > first_phipsibin_data;
1764  first_phipsibin_data.reserve( n_possible_rots() );
1765 
1766  DunbrackReal phi(0.0), psi(0.0), probability(0.0);
1767  Size phibin(0), psibin(0), lastphibin(0), lastpsibin(0), count(0);
1768  bool very_first_rotamer( true );
1769  bool finished_first_phipsi_bin( false );
1770  Size count_in_this_phipsi_bin( 1 );
1774  std::string three_letter_code;
1775  Size count_read_rotamers(0);
1776 
1777  while ( infile ) { // if the file should suddenly end, we'd be in trouble.
1778 
1779  /// 1. peek at the line; if it starts with #, skip to the next line.
1780  char first_char = infile.peek();
1781  if ( first_char == '#' ) {
1782  std::string line;
1783  infile.getline( line );
1784  continue;
1785  }
1786 
1787  /// 2. Read the line. Format is:
1788  /// a. three-letter-code,
1789  /// b. phi,
1790  /// c. psi,
1791  /// d. count
1792  /// e..h r1..r4
1793  /// i. probability
1794  /// j..m chimean1..chimean4
1795  /// n..q chisd1..chisd4
1796 
1797  if ( first_line_three_letter_code_already_read ) {
1798  /// The last library to read from this file already ate my three letter code;
1799  /// skip directly to reading phi/psi values...
1800  first_line_three_letter_code_already_read = false;
1801  } else {
1802  infile >> three_letter_code;
1803  if ( three_letter_code != my_name ) {
1804  next_name = three_letter_code;
1805  initialize_bicubic_splines();
1806  return next_name;
1807  }/// else, we're still reading data for the intended amino acid, so let's continue...
1808  }
1809 
1810 
1811  infile >> phi >> psi >> count;
1812  infile >> rotwell[ 1 ] >> rotwell[ 2 ] >> rotwell[ 3 ] >> rotwell[ 4 ];
1813  infile >> probability;
1814  infile >> chimean[ 1 ] >> chimean[ 2 ] >> chimean[ 3 ] >> chimean[ 4 ];
1815  infile >> chisd[ 1 ] >> chisd[ 2 ] >> chisd[ 3 ] >> chisd[ 4 ];
1816 
1817  if ( phi == 180 || psi == 180 ) continue; // duplicated data...
1818  ++count_read_rotamers;
1819 
1820  /// AVOID INF!
1821  for ( Size ii = 1; ii <= T; ++ii ) {
1822  if ( chisd[ ii ] == 0.0 ) {
1823  chisd[ ii ] = 5; // bogus!
1824  }
1825  }
1826  if ( probability == 0.0 ) {
1827  probability = 1e-4;
1828  /// APL -- On the advice of Roland Dunbrack, modifying the minimum probability to the
1829  /// resolution of the library. This helps avoid overwhelmingly unfavorable energies
1830  /// (5 log-units difference between 1e-4 and 1e-9) for rare rotamers.
1831  }
1832 
1833  get_phipsi_bins( phi, psi, phibin, psibin );
1834  if ( finished_first_phipsi_bin ) {
1835  Size const packed_rotno = rotwell_2_packed_rotno( rotwell );
1836  if ( packed_rotno < 1 || packed_rotno > parent::n_packed_rots() ) {
1837  std::cerr << "ERROR in converting rotwell to packed rotno: ";
1838  for ( Size ii = 1; ii <= T; ++ii ) std::cerr << " " << rotwell[ ii ];
1839  std::cerr << " " << packed_rotno << std::endl;
1840  utility_exit();
1841  }
1842  PackedDunbrackRotamer< T > rotamer( chimean, chisd, probability, packed_rotno );
1843  if ( phibin != lastphibin || psibin != lastpsibin ) {
1844  count_in_this_phipsi_bin = 1;
1845  }
1846  //std::cout << "reading rotamer " << packed_rotno << " " << count_in_this_phipsi_bin << " " << phi << " " << psi << " " << phibin << " " << psibin << " " << chimean[1] << " " << chisd[1] << " " << probability << std::endl;
1847 
1848  rotamers_( phibin, psibin, count_in_this_phipsi_bin ) = rotamer;
1849  packed_rotno_2_sorted_rotno_( phibin, psibin, packed_rotno ) = count_in_this_phipsi_bin;
1850 
1851  ++count_in_this_phipsi_bin;
1852  lastphibin = phibin; lastpsibin = psibin;
1853  } else {
1854  if ( !very_first_rotamer && (phibin != lastphibin || psibin != lastpsibin )) {
1855  // We have now read all rotamers from this phi/psi bin.
1856  // 1. Declare all existing rotwells encountered
1857  // 2. Allocate space for rotamer data
1858  // 3. Store data from first rotwell.
1859  // 4. Store the data from the rotamer we just read.
1860 
1861  // 1.
1862  declare_all_existing_rotwells_encountered();
1863  // 2.
1864  rotamers_.dimension( N_PHIPSI_BINS, N_PHIPSI_BINS, n_packed_rots() );
1865  packed_rotno_2_sorted_rotno_.dimension( N_PHIPSI_BINS, N_PHIPSI_BINS, n_packed_rots() );
1866  // 3.
1867  utility::vector1< Size > first_bin_rotwell( DUNBRACK_MAX_SCTOR, 0 );
1868  for ( Size ii = 1; ii <= first_phipsibin_data.size(); ++ii ) {
1869  for ( Size jj = 1; jj <= T; ++jj ) {
1870  first_bin_rotwell[ jj ] = first_phipsibin_data[ ii ].rotwell( jj );
1871  }
1872  Size const packed_rotno = rotwell_2_packed_rotno( first_bin_rotwell );
1873 
1874  if ( packed_rotno < 1 || packed_rotno > parent::n_packed_rots() ) {
1875  std::cerr << "ERROR in converting rotwell to packed rotno: ";
1876  for ( Size ii = 1; ii <= T; ++ii ) std::cerr << " " << rotwell[ ii ];
1877  std::cerr << " " << packed_rotno << std::endl;
1878  utility_exit();
1879  }
1880 
1881 
1882  rotamers_( lastphibin, lastpsibin, ii ) = PackedDunbrackRotamer< T >( first_phipsibin_data[ ii ], packed_rotno );
1883  packed_rotno_2_sorted_rotno_( lastphibin, lastpsibin, packed_rotno ) = ii;
1884  }
1885 
1886  // 4.
1887  assert( count_in_this_phipsi_bin == 1 );
1888  Size const packed_rotno = rotwell_2_packed_rotno( rotwell );
1889  PackedDunbrackRotamer< T > rotamer( chimean, chisd, probability, packed_rotno );
1890  rotamers_( phibin, psibin, count_in_this_phipsi_bin ) = rotamer;
1891  packed_rotno_2_sorted_rotno_( phibin, psibin, packed_rotno ) = count_in_this_phipsi_bin;
1892  ++count_in_this_phipsi_bin;
1893  lastphibin = phibin; lastpsibin = psibin;
1894 
1895  finished_first_phipsi_bin = true;
1896  } else {
1897  very_first_rotamer = false;
1898  mark_rotwell_exists( rotwell );
1899  first_phipsibin_data.push_back( DunbrackRotamer< T >( chimean, chisd, probability, rotwell ) );
1900  lastphibin = phibin; lastpsibin = psibin;
1901  }
1902  }
1903  }
1904  initialize_bicubic_splines();
1905  return next_name; // if we arived here, we got to the end of the file, so return the empty string.
1906 }
1907 
1908 template < Size T >
1909 void
1911 {
1912  //std::cout << "creating bicubic splines for " << aa() << std::endl;
1913  for ( Size ii = 1; ii <= n_packed_rots(); ++ii ) {
1914  using namespace numeric;
1915  using namespace numeric::interpolation::spline;
1916 
1917  BicubicSpline rotEspline;
1918  MathMatrix< Real > energy_vals( N_PHIPSI_BINS, N_PHIPSI_BINS );
1919  for ( Size jj = 0; jj < N_PHIPSI_BINS; ++jj ) {
1920  for ( Size kk = 0; kk < N_PHIPSI_BINS; ++kk ) {
1921  Size sortedrotno = packed_rotno_2_sorted_rotno_( jj+1, kk+1, ii );
1922  PackedDunbrackRotamer< T > & rot = rotamers_( jj+1, kk+1, sortedrotno );
1923  DunbrackReal rotamer_energy = -std::log( rot.rotamer_probability() );
1924  rot.rotE() = rotamer_energy;
1925  energy_vals( jj, kk ) = rotamer_energy;
1926  }
1927  }
1928  BorderFlag periodic_boundary[2] = { e_Periodic, e_Periodic };
1929  Real start_vals[2] = {0.0, 0.0}; // grid is placed on the ten-degree marks
1930  Real deltas[2] = {10.0, 10.0}; // grid is 10 degrees wide
1931  bool lincont[2] = {false,false}; //meaningless argument for a bicubic spline with periodic boundary conditions
1932  std::pair< Real, Real > unused[2];
1933  unused[0] = std::make_pair( 0.0, 0.0 );
1934  unused[1] = std::make_pair( 0.0, 0.0 );
1935  rotEspline.train( periodic_boundary, start_vals, deltas, energy_vals, lincont, unused );
1936  for ( Size jj = 0; jj < N_PHIPSI_BINS; ++jj ) {
1937  for ( Size kk = 0; kk < N_PHIPSI_BINS; ++kk ) {
1938  Size sortedrotno = packed_rotno_2_sorted_rotno_( jj+1, kk+1, ii );
1939  PackedDunbrackRotamer< T > & rot = rotamers_( jj+1, kk+1, sortedrotno );
1940  rot.rotE_dsecophi() = rotEspline.get_dsecox()( jj, kk );
1941  rot.rotE_dsecopsi() = rotEspline.get_dsecoy()( jj, kk );
1942  rot.rotE_dsecophipsi() = rotEspline.get_dsecoxy()( jj, kk );
1943  }
1944  }
1945  }
1946 
1947 }
1948 
1949 /// @details called only if the library is actually an RSRDL<T> object. Derived classes
1950 /// should not call this function or recurse. Accounts for the statically allocated data
1951 /// that's part of this class.
1952 template < Size T >
1954 {
1956 }
1957 
1958 /// @details Measures the amount of dynamically allocated data in this class. Must recurse to parent
1959 /// to count parent's dynamically allocated data.
1960 template < Size T >
1962 {
1963  Size total = parent::memory_usage_dynamic(); // recurse to parent.
1964  total += rotamers_.size() * sizeof( PackedDunbrackRotamer< T > );
1965  total += packed_rotno_2_sorted_rotno_.size() * sizeof( Size ); // could make these shorts or chars!
1966  //total += max_rotprob_.size() * sizeof( DunbrackReal );
1967  return total;
1968 }
1969 
1970 template < Size T >
1971 void
1973  ChiVector const & chi,
1974  RotVector & rot
1975 ) const
1976 {
1977  Size4 rot4;
1978  get_rotamer_from_chi_static( chi, rot4 );
1979  rot.resize( chi.size() );
1980  for ( Size ii = 1; ii <= T; ++ii ) rot[ ii ] = rot4[ ii ];
1981  for ( Size ii = T+1; ii <= chi.size(); ++ii ) rot[ ii ] = 0;
1982 }
1983 
1984 template < Size T >
1985 void
1987  ChiVector const & chi,
1988  Size4 & rot
1989 ) const
1990 {
1991  Real4 chi4;
1992  for ( Size ii = 1; ii <= T; ++ii ) chi4[ ii ] = chi[ ii ];
1993  get_rotamer_from_chi_static( chi4, rot );
1994 }
1995 
1996 template < Size T >
1997 void
1999  Real4 const & chi,
2000  Size4 & rot
2001 ) const
2002 {
2003  if ( dun02() ) { rotamer_from_chi_02( chi, aa(), T, rot ); return; }
2004 
2005  assert( chi.size() >= T );
2006 
2007  /// compiler will unroll this loop
2008  for ( Size ii = 1; ii <= T; ++ii ) {
2009  rot[ ii ] = bin_rotameric_chi( basic::periodic_range( chi[ ii ], 360 ), ii );
2010  }
2011 }
2012 
2013 
2014 } // namespace dunbrack
2015 } // namespace scoring
2016 } // namespace core
2017 
2018 #endif // INCLUDED_core_pack_dunbrack_RotamericSingleResidueDunbrackLibrary_TMPL_HH