diff --git a/doc/portableIO.rst b/doc/portableIO.rst
index b0097c0240a9e71befffc3cf096fd6cc889513a5..5c30639815477b7b579aa873361c3efa3d630795 100644
--- a/doc/portableIO.rst
+++ b/doc/portableIO.rst
@@ -389,7 +389,7 @@ The following binary files are currently in |project|:
 
   - :file:`bb_dep_lib.dat`
     (:class:`~promod3.sidechain.BBDepRotamerLib`)
-  - :file:`PenultimateLib.dat`
+  - :file:`lib.dat`
     (:class:`~promod3.sidechain.RotamerLib`)
 
 During the ``make`` process, portable versions of the files (stored in the
diff --git a/extras/data_generation/portable_binaries/convert_data.cc b/extras/data_generation/portable_binaries/convert_data.cc
index cecf7a1ab5718d9b01ebf169570c143221ae6602..20c0144cac447d21b360ba860fd67862eafc42b5 100644
--- a/extras/data_generation/portable_binaries/convert_data.cc
+++ b/extras/data_generation/portable_binaries/convert_data.cc
@@ -387,7 +387,7 @@ int main() {
   // convert_structure_db("structure_db.dat");
   // convert_structure_db("structure_db_small.dat", "structure_db_new.dat");
   // convert_BBDepRotamerLib("bb_dep_lib.dat");
-  // convert_RotamerLib("PenultimateLib.dat");
+  // convert_RotamerLib("lib.dat");
 
   /////////////////////////////////////////////////////////////
   // MAKE PORTABLE VERSIONS
@@ -410,8 +410,8 @@ int main() {
                         "p_data/portable_structure_db_small.dat");
   portable_BBDepRotamerLib("bb_dep_lib.dat",
                            "p_data/portable_bb_dep_lib.dat");
-  portable_RotamerLib("PenultimateLib.dat",
-                      "p_data/portable_PenultimateLib.dat");
+  portable_RotamerLib("lib.dat",
+                      "p_data/portable_lib.dat");
 
   return 0;
 }
diff --git a/extras/data_generation/rotamer_library/README b/extras/data_generation/rotamer_library/README
index bee2dab0295176eab69d1737b23dab1c208f17b4..4c90c94f656d79db65e5909edaab59941453ae57 100644
--- a/extras/data_generation/rotamer_library/README
+++ b/extras/data_generation/rotamer_library/README
@@ -10,54 +10,24 @@ we can read in are SimpleOpt1 and SimpleOpt2.
 Adapt the according path in CreateDunbrackLibrary.py and run it to read
 the provided file and dump it as a binary that can be read by ProMod3.
 
-###########################
-# The Penultimate Library #
-###########################
 
-The script create_penultimate.py reads in the values stored in penultimate.csv
-and dumps following RotamerLibs: 
+#################################
+# The ProMod3 Rotamer Libraries #
+#################################
 
- * Penultimate.dat
- * PenultimateAlpha.dat
- * PenultimateBeta.dat
- * PenultimateOther.dat
+ProMod3 comes with basic functionality to generate backbone dependent
+and backbone independent rotamer libraries. Both types of rotamer libraries are
+available in default binary versions and can directly be loaded by the user.
+The following sections guide you through the process of building such libraries. 
+Feel free to adapt any step to get your custom library.
 
-penultimate.csv contains the data listed in Table I of Lovell et al., 2000.
-The penultimate rotamer library.
 
-DO NOT ALTER ITS CONTENT AS create_penultimate.py WORKS WITH LINE NUMBERS
-(bad coding style I know...)
+####################
+# FETCH STRUCTURES #
+####################
 
-Penultimate.dat contains rotamers with data from following columns in the
-mentioned table:
-
- * %
- * chi1 mode 
- * chi2 mode
- * chi3 mode
- * chi4 mode 
- * 1/2 width at 1/2 height for all chi values (this value is assigned as sigma 
-                                               even though its conceptually 
-                                               different. More info in the 
-                                               publication)
-
-The only difference of PenultimateAlpha.dat etc. is the probability that is
-not taken from %, but rather from the columns named Alpha, Beta and Other.
-
-
-###############################
-# The ProMod3 Rotamer Library #
-###############################
-
-ProMod3 comes with some basic functionality to generate a backbone dependent
-rotamer library. The following sections guide you through the process of 
-building such a library. Feel free to adapt any step to get your custom 
-library.
-
-
-############################
-# Step 1: FETCH STRUCTURES #
-############################
+No matter whether you want to generate a backbone dependent or independent
+library: you need data
 
 ost fetch_data.py
 
@@ -69,7 +39,7 @@ and stores following information for each residue in a csv file:
  * phi / psi backbone dihedral angles in radians
  * sidechain dihedral angles in radians
  * the configuration of sidechain dihedral angles,
-   one of [GAUCHE_MINUS, GAUCHE_PLUS, NON_ROTAMERIC, INVALID]
+   one of [GAUCHE_MINUS, GAUCHE_PLUS, TRANS, NON_ROTAMERIC, INVALID]
 
 Residues from which you'll get data: 
 ARG, ASN, ASP, GLN, GLU, LYS, SER, CYH, CYD, CYS, MET, TRP, TYR, THR, VAL, ILE, 
@@ -96,10 +66,35 @@ Only data from residues will be dumped where everything is available,
 e.g. terminal residues without valid phi/psi or residues without
 all their sidechain atoms will be skipped. 
 
+####################################################
+# OPTION ONE: BACKBONE INDEPENDENT ROTAMER LIBRARY #
+####################################################
+
+ost do_lib.py <data> <out_file_name>
 
-###################################
-# STEP 2: BUILD A ROTAMER LIBRARY #
-###################################
+Loads csv generated by fetch_data.py, determines a set of rotamers for each 
+type of amino acids and dumps a full backbone independent library to disk.
+
+The general approach for each amino acid is to look at each possible 
+combination of rotameric configurations and obtain a rotamer by simply 
+calculating the mean and standard deviation of all datapoints with
+this particular configuration. The probability of that rotamer is the number 
+of data points with this configuration divided by the total number of 
+datapoints for this amino acid.
+
+The situation becomes more difficult for the so called non rotameric dihedral
+angles.
+Non rotameric dihedral angles are:  ASN(chi2), ASP(chi2), PHE(chi2), TYR(chi2), 
+HIS(chi2), TRP(chi2), GLN(chi3) and GLU(chi3).
+
+The approach used here is exaclty the same as described for option two:
+backbone dependent rotamer library with the exception that there is no
+weighted mean etc, each datapoint contributes equally to the mean and
+std.
+
+##################################################
+# OPTION TWO: BACKBONE DEPENDENT ROTAMER LIBRARY #
+##################################################
 
 ost do_bb_dep_lib.py <data> <aa_name>
 
@@ -195,20 +190,18 @@ with default parametrization, this gives a total of 12 possible chi2
 configurations. Each with a probability p_chi2_n, a mean m_chi2_n and a standard 
 deviation std_chi2_n. The probability of a certain rotamer n is then p*p_chi2_n.
 
-
-#######################################
-# STEP 3: DO THIS FOR ALL AMINO ACIDS #
-#######################################
+###############################
+# DO THIS FOR ALL AMINO ACIDS #
+###############################
 
 The file rotamer_lib_creation.cmd contains all commands required to generate the 
 rotamers for all amino acids. With a working ProMod3 installation and the csv 
-file generated in STEP 1, you can do:
+file generated at the very beginning, you can do:
 source rotamer_lib_creation.cmd
 
-
-######################
-# STEP 4: READ IT IN #
-######################
+##############
+# READ IT IN #
+##############
 
 You should now have a file for every amino acid... you can concatenate them 
 with the bash script: concatenate_library.sh
diff --git a/extras/data_generation/rotamer_library/create_penultimate.py b/extras/data_generation/rotamer_library/create_penultimate.py
deleted file mode 100644
index 0ea845b8e987a4b4ddd4d2c0c5f4da104733c602..0000000000000000000000000000000000000000
--- a/extras/data_generation/rotamer_library/create_penultimate.py
+++ /dev/null
@@ -1,1384 +0,0 @@
-from promod3 import sidechain
-import numpy as np
-import traceback
-
-def ToRadian(deg_angle):
-  return float(deg_angle)/180*np.pi
-
-lib = sidechain.RotamerLib()
-lib_alpha = sidechain.RotamerLib()
-lib_beta = sidechain.RotamerLib()
-lib_other = sidechain.RotamerLib()
-
-data = open("penultimate.csv",'r').readlines()
-
-
-#handling arginine
-
-print
-print
-print "ARG"
-
-for i in range(5,41):
-  temp = data[i].split(',')
-
-  chi1 = float('NaN')
-  chi2 = float('NaN')
-  chi3 = float('NaN')
-  chi4 = float('NaN')
-
-  sig1 = float('NaN')
-  sig2 = float('NaN')
-  sig3 = float('NaN')
-  sig4 = float('NaN')
-
-  try:
-    chi1 = int(temp[6])
-    chi2 = int(temp[8])
-    chi3 = int(temp[10])
-    chi4 = int(temp[12])
-
-    sig1 = int(temp[14])
-    sig2 = int(temp[15])
-    sig3 = int(temp[16])
-    sig4 = int(temp[17])
-  except:
-    #some rotamers have really low probability and consequently no
-    #no mode values. This results in int(' ') => error => neglect the shit
-    print "ARG fail..."
-    continue
-
-  p = 0.0
-  p_alpha = 0.0
-  p_beta = 0.0
-  p_other = 0.0
-
-  str_p = temp[2]
-  if "<1%" in str_p:
-    p = 0.5
-  else:
-    p = float(str_p.strip().strip('%').strip('<'))
-
-  str_p = temp[3]
-  if "<1%" in str_p:
-    p_alpha = 0.5
-  else:
-    p_alpha = float(str_p.strip().strip('%').strip('<'))
-
-  str_p = temp[4]
-  if "<1%" in str_p:
-    p_beta = 0.5
-  else:
-    p_beta = float(str_p.strip().strip('%').strip('<'))
-
-  str_p = temp[5]
-  if "<1%" in str_p:
-    p_other = 0.5
-  else:
-    p_other = float(str_p.strip().strip('%').strip('<'))
-
-  
-
-  entry = sidechain.RotamerLibEntry(p*0.01,ToRadian(chi1),ToRadian(chi2),ToRadian(chi3),ToRadian(chi4),
-                                    ToRadian(sig1),ToRadian(sig2),ToRadian(sig3),ToRadian(sig4))
-  entry_alpha = sidechain.RotamerLibEntry(p_alpha*0.01,ToRadian(chi1),ToRadian(chi2),ToRadian(chi3),ToRadian(chi4),
-                                          ToRadian(sig1),ToRadian(sig2),ToRadian(sig3),ToRadian(sig4))
-  entry_beta = sidechain.RotamerLibEntry(p_beta*0.01,ToRadian(chi1),ToRadian(chi2),ToRadian(chi3),ToRadian(chi4),
-                                         ToRadian(sig1),ToRadian(sig2),ToRadian(sig3),ToRadian(sig4))
-  entry_other = sidechain.RotamerLibEntry(p_other*0.01,ToRadian(chi1),ToRadian(chi2),ToRadian(chi3),ToRadian(chi4),
-                                          ToRadian(sig1),ToRadian(sig2),ToRadian(sig3),ToRadian(sig4))
-
-  print p, p_alpha, p_beta, p_other, chi1,chi2,chi3,chi4,sig1,sig2,sig3,sig4
-
-  lib.AddRotamer(sidechain.ARG,entry)
-  lib_alpha.AddRotamer(sidechain.ARG,entry_alpha)
-  lib_beta.AddRotamer(sidechain.ARG,entry_beta)
-  lib_other.AddRotamer(sidechain.ARG,entry_other)
-
-
-print
-print
-print "LYS"
-
-#handling Lysine
-for i in range(42,71):
-  temp = data[i].split(',')
-  chi1 = float('NaN')
-  chi2 = float('NaN')
-  chi3 = float('NaN')
-  chi4 = float('NaN')
-
-  sig1 = float('NaN')
-  sig2 = float('NaN')
-  sig3 = float('NaN')
-  sig4 = float('NaN')
-
-  try:
-    chi1 = int(temp[6])
-    chi2 = int(temp[8])
-    chi3 = int(temp[10])
-    chi4 = int(temp[12])
-
-    sig1 = int(temp[14])
-    sig2 = int(temp[15])
-    sig3 = int(temp[16])
-    sig4 = int(temp[17])
-  except:
-    #some rotamers have really low probability and consequently no
-    #no mode values. This results in int(' ') => error => neglect the shit
-    print "LYS fail..."
-    continue
-
-  p = 0.0
-  p_alpha = 0.0
-  p_beta = 0.0
-  p_other = 0.0
-
-  str_p = temp[2]
-  if "<1%" in str_p:
-    p = 0.5
-  else:
-    p = float(str_p.strip().strip('%').strip('<'))
-
-  str_p = temp[3]
-  if "<1%" in str_p:
-    p_alpha = 0.5
-  else:
-    p_alpha = float(str_p.strip().strip('%').strip('<'))
-
-  str_p = temp[4]
-  if "<1%" in str_p:
-    p_beta = 0.5
-  else:
-    p_beta = float(str_p.strip().strip('%').strip('<'))
-
-  str_p = temp[5]
-  if "<1%" in str_p:
-    p_other = 0.5
-  else:
-    p_other = float(str_p.strip().strip('%').strip('<'))
-
-  print p, p_alpha, p_beta, p_other, chi1,chi2,chi3,chi4,sig1,sig2,sig3,sig4  
-
-  entry = sidechain.RotamerLibEntry(p*0.01,ToRadian(chi1),ToRadian(chi2),ToRadian(chi3),ToRadian(chi4),
-                                    ToRadian(sig1),ToRadian(sig2),ToRadian(sig3),ToRadian(sig4))
-  entry_alpha = sidechain.RotamerLibEntry(p_alpha*0.01,ToRadian(chi1),ToRadian(chi2),ToRadian(chi3),ToRadian(chi4),
-                                          ToRadian(sig1),ToRadian(sig2),ToRadian(sig3),ToRadian(sig4))
-  entry_beta = sidechain.RotamerLibEntry(p_beta*0.01,ToRadian(chi1),ToRadian(chi2),ToRadian(chi3),ToRadian(chi4),
-                                         ToRadian(sig1),ToRadian(sig2),ToRadian(sig3),ToRadian(sig4))
-  entry_other = sidechain.RotamerLibEntry(p_other*0.01,ToRadian(chi1),ToRadian(chi2),ToRadian(chi3),ToRadian(chi4),
-                                          ToRadian(sig1),ToRadian(sig2),ToRadian(sig3),ToRadian(sig4))
-
-  lib.AddRotamer(sidechain.LYS,entry)
-  lib_alpha.AddRotamer(sidechain.LYS,entry_alpha)
-  lib_beta.AddRotamer(sidechain.LYS,entry_beta)
-  lib_other.AddRotamer(sidechain.LYS,entry_other)
-
-
-print
-print
-print "MET"
-
-#handling Methionine
-for i in range(72,87):
-  temp = data[i].split(',')
-  chi1 = float('NaN')
-  chi2 = float('NaN')
-  chi3 = float('NaN')
-  chi4 = float('NaN')
-
-  sig1 = float('NaN')
-  sig2 = float('NaN')
-  sig3 = float('NaN')
-  sig4 = float('NaN')
-
-  try:
-    chi1 = int(temp[6])
-    chi2 = int(temp[8])
-    chi3 = int(temp[10])
-
-    sig1 = int(temp[13])
-    sig2 = int(temp[14])
-    sig3 = int(temp[15])
-  except:
-    #some rotamers have really low probability and consequently no
-    #no mode values. This results in int(' ') => error => neglect the shit
-    print "MET fail..."
-    continue
-
-  p = 0.0
-  p_alpha = 0.0
-  p_beta = 0.0
-  p_other = 0.0
-
-  str_p = temp[2]
-  if "<1%" in str_p:
-    p = 0.5
-  else:
-    p = float(str_p.strip().strip('%').strip('<'))
-
-  str_p = temp[3]
-  if "<1%" in str_p:
-    p_alpha = 0.5
-  else:
-    p_alpha = float(str_p.strip().strip('%').strip('<'))
-
-  str_p = temp[4]
-  if "<1%" in str_p:
-    p_beta = 0.5
-  else:
-    p_beta = float(str_p.strip().strip('%').strip('<'))
-
-  str_p = temp[5]
-  if "<1%" in str_p:
-    p_other = 0.5
-  else:
-    p_other = float(str_p.strip().strip('%').strip('<'))
-
-  
-  print p, p_alpha, p_beta, p_other, chi1,chi2,chi3,chi4,sig1,sig2,sig3,sig4
-
-  entry = sidechain.RotamerLibEntry(p*0.01,ToRadian(chi1),ToRadian(chi2),ToRadian(chi3),ToRadian(chi4),
-                                    ToRadian(sig1),ToRadian(sig2),ToRadian(sig3),ToRadian(sig4))
-  entry_alpha = sidechain.RotamerLibEntry(p_alpha*0.01,ToRadian(chi1),ToRadian(chi2),ToRadian(chi3),ToRadian(chi4),
-                                          ToRadian(sig1),ToRadian(sig2),ToRadian(sig3),ToRadian(sig4))
-  entry_beta = sidechain.RotamerLibEntry(p_beta*0.01,ToRadian(chi1),ToRadian(chi2),ToRadian(chi3),ToRadian(chi4),
-                                         ToRadian(sig1),ToRadian(sig2),ToRadian(sig3),ToRadian(sig4))
-  entry_other = sidechain.RotamerLibEntry(p_other*0.01,ToRadian(chi1),ToRadian(chi2),ToRadian(chi3),ToRadian(chi4),
-                                          ToRadian(sig1),ToRadian(sig2),ToRadian(sig3),ToRadian(sig4))
-
-  lib.AddRotamer(sidechain.MET,entry)
-  lib_alpha.AddRotamer(sidechain.MET,entry_alpha)
-  lib_beta.AddRotamer(sidechain.MET,entry_beta)
-  lib_other.AddRotamer(sidechain.MET,entry_other)
-
-print
-print
-print "GLU"
-
-#handling Glutamate
-for i in range(88,98):
-  temp = data[i].split(',')
-  chi1 = float('NaN')
-  chi2 = float('NaN')
-  chi3 = float('NaN')
-  chi4 = float('NaN')
-
-  sig1 = float('NaN')
-  sig2 = float('NaN')
-  sig3 = float('NaN')
-  sig4 = float('NaN')
-
-  try:
-    chi1 = int(temp[6])
-    chi2 = int(temp[8])
-    chi3 = int(temp[10])
-
-    sig1 = int(temp[13])
-    sig2 = int(temp[14])
-    sig3 = int(temp[15])
-  except:
-    #some rotamers have really low probability and consequently no
-    #no mode values. This results in int(' ') => error => neglect the shit
-    print "GLU fail..."
-    continue
-
-  p = 0.0
-  p_alpha = 0.0
-  p_beta = 0.0
-  p_other = 0.0
-
-  str_p = temp[2]
-  if "<1%" in str_p:
-    p = 0.5
-  else:
-    p = float(str_p.strip().strip('%').strip('<'))
-
-  str_p = temp[3]
-  if "<1%" in str_p:
-    p_alpha = 0.5
-  else:
-    p_alpha = float(str_p.strip().strip('%').strip('<'))
-
-  str_p = temp[4]
-  if "<1%" in str_p:
-    p_beta = 0.5
-  else:
-    p_beta = float(str_p.strip().strip('%').strip('<'))
-
-  str_p = temp[5]
-  if "<1%" in str_p:
-    p_other = 0.5
-  else:
-    p_other = float(str_p.strip().strip('%').strip('<'))
-
-  
-  print p, p_alpha, p_beta, p_other, chi1,chi2,chi3,chi4,sig1,sig2,sig3,sig4
-
-  entry = sidechain.RotamerLibEntry(p*0.01,ToRadian(chi1),ToRadian(chi2),ToRadian(chi3),ToRadian(chi4),
-                                    ToRadian(sig1),ToRadian(sig2),ToRadian(sig3),ToRadian(sig4))
-  entry_alpha = sidechain.RotamerLibEntry(p_alpha*0.01,ToRadian(chi1),ToRadian(chi2),ToRadian(chi3),ToRadian(chi4),
-                                          ToRadian(sig1),ToRadian(sig2),ToRadian(sig3),ToRadian(sig4))
-  entry_beta = sidechain.RotamerLibEntry(p_beta*0.01,ToRadian(chi1),ToRadian(chi2),ToRadian(chi3),ToRadian(chi4),
-                                         ToRadian(sig1),ToRadian(sig2),ToRadian(sig3),ToRadian(sig4))
-  entry_other = sidechain.RotamerLibEntry(p_other*0.01,ToRadian(chi1),ToRadian(chi2),ToRadian(chi3),ToRadian(chi4),
-                                          ToRadian(sig1),ToRadian(sig2),ToRadian(sig3),ToRadian(sig4))
-
-  lib.AddRotamer(sidechain.GLU,entry)
-  lib_alpha.AddRotamer(sidechain.GLU,entry_alpha)
-  lib_beta.AddRotamer(sidechain.GLU,entry_beta)
-  lib_other.AddRotamer(sidechain.GLU,entry_other)
-
-
-print
-print
-print "GLN"
-
-#handling Glutamine
-for i in range(99,110):
-  temp = data[i].split(',')
-  chi1 = float('NaN')
-  chi2 = float('NaN')
-  chi3 = float('NaN')
-  chi4 = float('NaN')
-
-  sig1 = float('NaN')
-  sig2 = float('NaN')
-  sig3 = float('NaN')
-  sig4 = float('NaN')
-
-  try:
-    chi1 = int(temp[6])
-    chi2 = int(temp[8])
-    chi3 = int(temp[10])
-
-    sig1 = int(temp[13])
-    sig2 = int(temp[14])
-    sig3 = int(temp[15])
-  except:
-    #some rotamers have really low probability and consequently no
-    #no mode values. This results in int(' ') => error => neglect the shit
-    print "GLN fail..."
-    continue
-
-  p = 0.0
-  p_alpha = 0.0
-  p_beta = 0.0
-  p_other = 0.0
-
-  str_p = temp[2]
-  if "<1%" in str_p:
-    p = 0.5
-  else:
-    p = float(str_p.strip().strip('%').strip('<'))
-
-  str_p = temp[3]
-  if "<1%" in str_p:
-    p_alpha = 0.5
-  else:
-    p_alpha = float(str_p.strip().strip('%').strip('<'))
-
-  str_p = temp[4]
-  if "<1%" in str_p:
-    p_beta = 0.5
-  else:
-    p_beta = float(str_p.strip().strip('%').strip('<'))
-
-  str_p = temp[5]
-  if "<1%" in str_p:
-    p_other = 0.5
-  else:
-    p_other = float(str_p.strip().strip('%').strip('<'))
-
-  print p, p_alpha, p_beta, p_other, chi1,chi2,chi3,chi4,sig1,sig2,sig3,sig4 
-
-  entry = sidechain.RotamerLibEntry(p*0.01,ToRadian(chi1),ToRadian(chi2),ToRadian(chi3),ToRadian(chi4),
-                                    ToRadian(sig1),ToRadian(sig2),ToRadian(sig3),ToRadian(sig4))
-  entry_alpha = sidechain.RotamerLibEntry(p_alpha*0.01,ToRadian(chi1),ToRadian(chi2),ToRadian(chi3),ToRadian(chi4),
-                                          ToRadian(sig1),ToRadian(sig2),ToRadian(sig3),ToRadian(sig4))
-  entry_beta = sidechain.RotamerLibEntry(p_beta*0.01,ToRadian(chi1),ToRadian(chi2),ToRadian(chi3),ToRadian(chi4),
-                                         ToRadian(sig1),ToRadian(sig2),ToRadian(sig3),ToRadian(sig4))
-  entry_other = sidechain.RotamerLibEntry(p_other*0.01,ToRadian(chi1),ToRadian(chi2),ToRadian(chi3),ToRadian(chi4),
-                                          ToRadian(sig1),ToRadian(sig2),ToRadian(sig3),ToRadian(sig4))
-
-  lib.AddRotamer(sidechain.GLN,entry)
-  lib_alpha.AddRotamer(sidechain.GLN,entry_alpha)
-  lib_beta.AddRotamer(sidechain.GLN,entry_beta)
-  lib_other.AddRotamer(sidechain.GLN,entry_other)
-
-
-print
-print
-print "ASP"
-
-
-#handling Aspartate
-for i in range(111,118):
-  temp = data[i].split(',')
-  chi1 = float('NaN')
-  chi2 = float('NaN')
-  chi3 = float('NaN')
-  chi4 = float('NaN')
-
-  sig1 = float('NaN')
-  sig2 = float('NaN')
-  sig3 = float('NaN')
-  sig4 = float('NaN')
-
-  try:
-    chi1 = int(temp[6])
-    chi2 = int(temp[8])
-
-    sig1 = int(temp[13])
-    sig2 = int(temp[14])
-  except:
-    #some rotamers have really low probability and consequently no
-    #no mode values. This results in int(' ') => error => neglect the shit
-    print "ASP fail..."
-    continue
-
-  p = 0.0
-  p_alpha = 0.0
-  p_beta = 0.0
-  p_other = 0.0
-
-  str_p = temp[2]
-  if "<1%" in str_p:
-    p = 0.5
-  else:
-    p = float(str_p.strip().strip('%').strip('<'))
-
-  str_p = temp[3]
-  if "<1%" in str_p:
-    p_alpha = 0.5
-  else:
-    p_alpha = float(str_p.strip().strip('%').strip('<'))
-
-  str_p = temp[4]
-  if "<1%" in str_p:
-    p_beta = 0.5
-  else:
-    p_beta = float(str_p.strip().strip('%').strip('<'))
-
-  str_p = temp[5]
-  if "<1%" in str_p:
-    p_other = 0.5
-  else:
-    p_other = float(str_p.strip().strip('%').strip('<'))
-
-  print p, p_alpha, p_beta, p_other, chi1,chi2,chi3,chi4,sig1,sig2,sig3,sig4  
-
-  entry = sidechain.RotamerLibEntry(p*0.01,ToRadian(chi1),ToRadian(chi2),ToRadian(chi3),ToRadian(chi4),
-                                    ToRadian(sig1),ToRadian(sig2),ToRadian(sig3),ToRadian(sig4))
-  entry_alpha = sidechain.RotamerLibEntry(p_alpha*0.01,ToRadian(chi1),ToRadian(chi2),ToRadian(chi3),ToRadian(chi4),
-                                          ToRadian(sig1),ToRadian(sig2),ToRadian(sig3),ToRadian(sig4))
-  entry_beta = sidechain.RotamerLibEntry(p_beta*0.01,ToRadian(chi1),ToRadian(chi2),ToRadian(chi3),ToRadian(chi4),
-                                         ToRadian(sig1),ToRadian(sig2),ToRadian(sig3),ToRadian(sig4))
-  entry_other = sidechain.RotamerLibEntry(p_other*0.01,ToRadian(chi1),ToRadian(chi2),ToRadian(chi3),ToRadian(chi4),
-                                          ToRadian(sig1),ToRadian(sig2),ToRadian(sig3),ToRadian(sig4))
-
-  lib.AddRotamer(sidechain.ASP,entry)
-  lib_alpha.AddRotamer(sidechain.ASP,entry_alpha)
-  lib_beta.AddRotamer(sidechain.ASP,entry_beta)
-  lib_other.AddRotamer(sidechain.ASP,entry_other)
-
-print
-print
-print "ASN"
-
-#handling Asparagine
-for i in range(119,128):
-  temp = data[i].split(',')
-  chi1 = float('NaN')
-  chi2 = float('NaN')
-  chi3 = float('NaN')
-  chi4 = float('NaN')
-
-  sig1 = float('NaN')
-  sig2 = float('NaN')
-  sig3 = float('NaN')
-  sig4 = float('NaN')
-
-  try:
-    chi1 = int(temp[6])
-    chi2 = int(temp[8])
-
-    sig1 = int(temp[13])
-    sig2 = int(temp[14])
-  except:
-    #some rotamers have really low probability and consequently no
-    #no mode values. This results in int(' ') => error => neglect the shit
-    print "ASN fail..."
-    continue
-
-  p = 0.0
-  p_alpha = 0.0
-  p_beta = 0.0
-  p_other = 0.0
-
-  str_p = temp[2]
-  if "<1%" in str_p:
-    p = 0.5
-  else:
-    p = float(str_p.strip().strip('%').strip('<'))
-
-  str_p = temp[3]
-  if "<1%" in str_p:
-    p_alpha = 0.5
-  else:
-    p_alpha = float(str_p.strip().strip('%').strip('<'))
-
-  str_p = temp[4]
-  if "<1%" in str_p:
-    p_beta = 0.5
-  else:
-    p_beta = float(str_p.strip().strip('%').strip('<'))
-
-  str_p = temp[5]
-  if "<1%" in str_p:
-    p_other = 0.5
-  else:
-    p_other = float(str_p.strip().strip('%').strip('<'))
-
-  print p, p_alpha, p_beta, p_other, chi1,chi2,chi3,chi4,sig1,sig2,sig3,sig4  
-
-  entry = sidechain.RotamerLibEntry(p*0.01,ToRadian(chi1),ToRadian(chi2),ToRadian(chi3),ToRadian(chi4),
-                                    ToRadian(sig1),ToRadian(sig2),ToRadian(sig3),ToRadian(sig4))
-  entry_alpha = sidechain.RotamerLibEntry(p_alpha*0.01,ToRadian(chi1),ToRadian(chi2),ToRadian(chi3),ToRadian(chi4),
-                                          ToRadian(sig1),ToRadian(sig2),ToRadian(sig3),ToRadian(sig4))
-  entry_beta = sidechain.RotamerLibEntry(p_beta*0.01,ToRadian(chi1),ToRadian(chi2),ToRadian(chi3),ToRadian(chi4),
-                                         ToRadian(sig1),ToRadian(sig2),ToRadian(sig3),ToRadian(sig4))
-  entry_other = sidechain.RotamerLibEntry(p_other*0.01,ToRadian(chi1),ToRadian(chi2),ToRadian(chi3),ToRadian(chi4),
-                                          ToRadian(sig1),ToRadian(sig2),ToRadian(sig3),ToRadian(sig4))
-
-  lib.AddRotamer(sidechain.ASN,entry)
-  lib_alpha.AddRotamer(sidechain.ASN,entry_alpha)
-  lib_beta.AddRotamer(sidechain.ASN,entry_beta)
-  lib_other.AddRotamer(sidechain.ASN,entry_other)
-
-print
-print
-print "ILE"
-
-#handling IsoLeucine
-for i in range(129,138):
-  temp = data[i].split(',')
-  chi1 = float('NaN')
-  chi2 = float('NaN')
-  chi3 = float('NaN')
-  chi4 = float('NaN')
-
-  sig1 = float('NaN')
-  sig2 = float('NaN')
-  sig3 = float('NaN')
-  sig4 = float('NaN')
-
-  try:
-    chi1 = int(temp[6])
-    chi2 = int(temp[8])
-
-    sig1 = int(temp[11])
-    sig2 = int(temp[12])
-
-  except:
-    #some rotamers have really low probability and consequently no
-    #no mode values. This results in int(' ') => error => neglect the shit
-    print "ILE fail..."
-    continue
-
-  p = 0.0
-  p_alpha = 0.0
-  p_beta = 0.0
-  p_other = 0.0
-
-  str_p = temp[2]
-  if "<1%" in str_p:
-    p = 0.5
-  else:
-    p = float(str_p.strip().strip('%').strip('<'))
-
-  str_p = temp[3]
-  if "<1%" in str_p:
-    p_alpha = 0.5
-  else:
-    p_alpha = float(str_p.strip().strip('%').strip('<'))
-
-  str_p = temp[4]
-  if "<1%" in str_p:
-    p_beta = 0.5
-  else:
-    p_beta = float(str_p.strip().strip('%').strip('<'))
-
-  str_p = temp[5]
-  if "<1%" in str_p:
-    p_other = 0.5
-  else:
-    p_other = float(str_p.strip().strip('%').strip('<'))
-
-  print p, p_alpha, p_beta, p_other, chi1,chi2,chi3,chi4,sig1,sig2,sig3,sig4 
-
-  entry = sidechain.RotamerLibEntry(p*0.01,ToRadian(chi1),ToRadian(chi2),ToRadian(chi3),ToRadian(chi4),
-                                    ToRadian(sig1),ToRadian(sig2),ToRadian(sig3),ToRadian(sig4))
-  entry_alpha = sidechain.RotamerLibEntry(p_alpha*0.01,ToRadian(chi1),ToRadian(chi2),ToRadian(chi3),ToRadian(chi4),
-                                          ToRadian(sig1),ToRadian(sig2),ToRadian(sig3),ToRadian(sig4))
-  entry_beta = sidechain.RotamerLibEntry(p_beta*0.01,ToRadian(chi1),ToRadian(chi2),ToRadian(chi3),ToRadian(chi4),
-                                         ToRadian(sig1),ToRadian(sig2),ToRadian(sig3),ToRadian(sig4))
-  entry_other = sidechain.RotamerLibEntry(p_other*0.01,ToRadian(chi1),ToRadian(chi2),ToRadian(chi3),ToRadian(chi4),
-                                          ToRadian(sig1),ToRadian(sig2),ToRadian(sig3),ToRadian(sig4))
-
-  lib.AddRotamer(sidechain.ILE,entry)
-  lib_alpha.AddRotamer(sidechain.ILE,entry_alpha)
-  lib_beta.AddRotamer(sidechain.ILE,entry_beta)
-  lib_other.AddRotamer(sidechain.ILE,entry_other)
-
-
-print
-print
-print "LEU"
-
-#handling Leucine
-for i in range(139,146):
-  temp = data[i].split(',')
-  chi1 = float('NaN')
-  chi2 = float('NaN')
-  chi3 = float('NaN')
-  chi4 = float('NaN')
-
-  sig1 = float('NaN')
-  sig2 = float('NaN')
-  sig3 = float('NaN')
-  sig4 = float('NaN')
-
-  try:
-    chi1 = int(temp[6])
-    chi2 = int(temp[8])
-
-    sig1 = int(temp[11])
-    sig2 = int(temp[12])
-  except:
-    #some rotamers have really low probability and consequently no
-    #no mode values. This results in int(' ') => error => neglect the shit
-    print "LEU fail..."
-    continue
-
-  p = 0.0
-  p_alpha = 0.0
-  p_beta = 0.0
-  p_other = 0.0
-
-  str_p = temp[2]
-  if "<1%" in str_p:
-    p = 0.5
-  else:
-    p = float(str_p.strip().strip('%').strip('<'))
-
-  str_p = temp[3]
-  if "<1%" in str_p:
-    p_alpha = 0.5
-  else:
-    p_alpha = float(str_p.strip().strip('%').strip('<'))
-
-  str_p = temp[4]
-  if "<1%" in str_p:
-    p_beta = 0.5
-  else:
-    p_beta = float(str_p.strip().strip('%').strip('<'))
-
-  str_p = temp[5]
-  if "<1%" in str_p:
-    p_other = 0.5
-  else:
-    p_other = float(str_p.strip().strip('%').strip('<'))
-
-  
-  print p, p_alpha, p_beta, p_other, chi1,chi2,chi3,chi4,sig1,sig2,sig3,sig4
-
-  entry = sidechain.RotamerLibEntry(p*0.01,ToRadian(chi1),ToRadian(chi2),ToRadian(chi3),ToRadian(chi4),
-                                    ToRadian(sig1),ToRadian(sig2),ToRadian(sig3),ToRadian(sig4))
-  entry_alpha = sidechain.RotamerLibEntry(p_alpha*0.01,ToRadian(chi1),ToRadian(chi2),ToRadian(chi3),ToRadian(chi4),
-                                          ToRadian(sig1),ToRadian(sig2),ToRadian(sig3),ToRadian(sig4))
-  entry_beta = sidechain.RotamerLibEntry(p_beta*0.01,ToRadian(chi1),ToRadian(chi2),ToRadian(chi3),ToRadian(chi4),
-                                         ToRadian(sig1),ToRadian(sig2),ToRadian(sig3),ToRadian(sig4))
-  entry_other = sidechain.RotamerLibEntry(p_other*0.01,ToRadian(chi1),ToRadian(chi2),ToRadian(chi3),ToRadian(chi4),
-                                          ToRadian(sig1),ToRadian(sig2),ToRadian(sig3),ToRadian(sig4))
-
-  lib.AddRotamer(sidechain.LEU,entry)
-  lib_alpha.AddRotamer(sidechain.LEU,entry_alpha)
-  lib_beta.AddRotamer(sidechain.LEU,entry_beta)
-  lib_other.AddRotamer(sidechain.LEU,entry_other)
-
-
-
-print
-print
-print "HIS"
-
-#handling Histidine
-for i in range(147,157):
-  temp = data[i].split(',')
-  chi1 = float('NaN')
-  chi2 = float('NaN')
-  chi3 = float('NaN')
-  chi4 = float('NaN')
-
-  sig1 = float('NaN')
-  sig2 = float('NaN')
-  sig3 = float('NaN')
-  sig4 = float('NaN')
-
-  try:
-    chi1 = int(temp[6])
-    chi2 = int(temp[8])
-
-    sig1 = int(temp[11])
-    sig2 = int(temp[12])
-  except:
-    #some rotamers have really low probability and consequently no
-    #no mode values. This results in int(' ') => error => neglect the shit
-    print "HIS fail..."
-    continue
-
-  p = 0.0
-  p_alpha = 0.0
-  p_beta = 0.0
-  p_other = 0.0
-
-  str_p = temp[2]
-  if "<1%" in str_p:
-    p = 0.5
-  else:
-    p = float(str_p.strip().strip('%').strip('<'))
-
-  str_p = temp[3]
-  if "<1%" in str_p:
-    p_alpha = 0.5
-  else:
-    p_alpha = float(str_p.strip().strip('%').strip('<'))
-
-  str_p = temp[4]
-  if "<1%" in str_p:
-    p_beta = 0.5
-  else:
-    p_beta = float(str_p.strip().strip('%').strip('<'))
-
-  str_p = temp[5]
-  if "<1%" in str_p:
-    p_other = 0.5
-  else:
-    p_other = float(str_p.strip().strip('%').strip('<'))
-
-  print p, p_alpha, p_beta, p_other, chi1,chi2,chi3,chi4,sig1,sig2,sig3,sig4  
-
-  entry = sidechain.RotamerLibEntry(p*0.01,ToRadian(chi1),ToRadian(chi2),ToRadian(chi3),ToRadian(chi4),
-                                    ToRadian(sig1),ToRadian(sig2),ToRadian(sig3),ToRadian(sig4))
-  entry_alpha = sidechain.RotamerLibEntry(p_alpha*0.01,ToRadian(chi1),ToRadian(chi2),ToRadian(chi3),ToRadian(chi4),
-                                          ToRadian(sig1),ToRadian(sig2),ToRadian(sig3),ToRadian(sig4))
-  entry_beta = sidechain.RotamerLibEntry(p_beta*0.01,ToRadian(chi1),ToRadian(chi2),ToRadian(chi3),ToRadian(chi4),
-                                         ToRadian(sig1),ToRadian(sig2),ToRadian(sig3),ToRadian(sig4))
-  entry_other = sidechain.RotamerLibEntry(p_other*0.01,ToRadian(chi1),ToRadian(chi2),ToRadian(chi3),ToRadian(chi4),
-                                          ToRadian(sig1),ToRadian(sig2),ToRadian(sig3),ToRadian(sig4))
-
-  lib.AddRotamer(sidechain.HIS,entry)
-  lib_alpha.AddRotamer(sidechain.HIS,entry_alpha)
-  lib_beta.AddRotamer(sidechain.HIS,entry_beta)
-  lib_other.AddRotamer(sidechain.HIS,entry_other)
-
-
-print
-print
-print "TRP"
-
-#handling Tryptophane
-for i in range(158,167):
-  temp = data[i].split(',')
-  chi1 = float('NaN')
-  chi2 = float('NaN')
-  chi3 = float('NaN')
-  chi4 = float('NaN')
-
-  sig1 = float('NaN')
-  sig2 = float('NaN')
-  sig3 = float('NaN')
-  sig4 = float('NaN')
-
-  try:
-    chi1 = int(temp[6])
-    chi2 = int(temp[8])
-
-    sig1 = int(temp[11])
-    sig2 = int(temp[12])
-  except:
-    #some rotamers have really low probability and consequently no
-    #no mode values. This results in int(' ') => error => neglect the shit
-    print "TRP fail..."
-    continue
-
-  p = 0.0
-  p_alpha = 0.0
-  p_beta = 0.0
-  p_other = 0.0
-
-  str_p = temp[2]
-  if "<1%" in str_p:
-    p = 0.5
-  else:
-    p = float(str_p.strip().strip('%').strip('<'))
-
-  str_p = temp[3]
-  if "<1%" in str_p:
-    p_alpha = 0.5
-  else:
-    p_alpha = float(str_p.strip().strip('%').strip('<'))
-
-  str_p = temp[4]
-  if "<1%" in str_p:
-    p_beta = 0.5
-  else:
-    p_beta = float(str_p.strip().strip('%').strip('<'))
-
-  str_p = temp[5]
-  if "<1%" in str_p:
-    p_other = 0.5
-  else:
-    p_other = float(str_p.strip().strip('%').strip('<'))
-
-  print p, p_alpha, p_beta, p_other, chi1,chi2,chi3,chi4,sig1,sig2,sig3,sig4  
-
-  entry = sidechain.RotamerLibEntry(p*0.01,ToRadian(chi1),ToRadian(chi2),ToRadian(chi3),ToRadian(chi4),
-                                    ToRadian(sig1),ToRadian(sig2),ToRadian(sig3),ToRadian(sig4))
-  entry_alpha = sidechain.RotamerLibEntry(p_alpha*0.01,ToRadian(chi1),ToRadian(chi2),ToRadian(chi3),ToRadian(chi4),
-                                          ToRadian(sig1),ToRadian(sig2),ToRadian(sig3),ToRadian(sig4))
-  entry_beta = sidechain.RotamerLibEntry(p_beta*0.01,ToRadian(chi1),ToRadian(chi2),ToRadian(chi3),ToRadian(chi4),
-                                         ToRadian(sig1),ToRadian(sig2),ToRadian(sig3),ToRadian(sig4))
-  entry_other = sidechain.RotamerLibEntry(p_other*0.01,ToRadian(chi1),ToRadian(chi2),ToRadian(chi3),ToRadian(chi4),
-                                          ToRadian(sig1),ToRadian(sig2),ToRadian(sig3),ToRadian(sig4))
-
-  lib.AddRotamer(sidechain.TRP,entry)
-  lib_alpha.AddRotamer(sidechain.TRP,entry_alpha)
-  lib_beta.AddRotamer(sidechain.TRP,entry_beta)
-  lib_other.AddRotamer(sidechain.TRP,entry_other)
-
-
-print
-print
-print "TYR"
-
-#handling Tyrosine
-for i in range(168,174):
-  temp = data[i].split(',')
-  chi1 = float('NaN')
-  chi2 = float('NaN')
-  chi3 = float('NaN')
-  chi4 = float('NaN')
-
-  sig1 = float('NaN')
-  sig2 = float('NaN')
-  sig3 = float('NaN')
-  sig4 = float('NaN')
-
-  try:
-    chi1 = int(temp[6])
-    chi2 = int(temp[8])
-
-    sig1 = int(temp[11])
-    sig2 = int(temp[12])
-  except:
-    #some rotamers have really low probability and consequently no
-    #no mode values. This results in int(' ') => error => neglect the shit
-    print "TYR fail..."
-    continue
-
-  p = 0.0
-  p_alpha = 0.0
-  p_beta = 0.0
-  p_other = 0.0
-
-  str_p = temp[2]
-  if "<1%" in str_p:
-    p = 0.5
-  else:
-    p = float(str_p.strip().strip('%').strip('<'))
-
-  str_p = temp[3]
-  if "<1%" in str_p:
-    p_alpha = 0.5
-  else:
-    p_alpha = float(str_p.strip().strip('%').strip('<'))
-
-  str_p = temp[4]
-  if "<1%" in str_p:
-    p_beta = 0.5
-  else:
-    p_beta = float(str_p.strip().strip('%').strip('<'))
-
-  str_p = temp[5]
-  if "<1%" in str_p:
-    p_other = 0.5
-  else:
-    p_other = float(str_p.strip().strip('%').strip('<'))
-
-  print p, p_alpha, p_beta, p_other, chi1,chi2,chi3,chi4,sig1,sig2,sig3,sig4  
-
-  entry = sidechain.RotamerLibEntry(p*0.01,ToRadian(chi1),ToRadian(chi2),ToRadian(chi3),ToRadian(chi4),
-                                    ToRadian(sig1),ToRadian(sig2),ToRadian(sig3),ToRadian(sig4))
-  entry_alpha = sidechain.RotamerLibEntry(p_alpha*0.01,ToRadian(chi1),ToRadian(chi2),ToRadian(chi3),ToRadian(chi4),
-                                          ToRadian(sig1),ToRadian(sig2),ToRadian(sig3),ToRadian(sig4))
-  entry_beta = sidechain.RotamerLibEntry(p_beta*0.01,ToRadian(chi1),ToRadian(chi2),ToRadian(chi3),ToRadian(chi4),
-                                         ToRadian(sig1),ToRadian(sig2),ToRadian(sig3),ToRadian(sig4))
-  entry_other = sidechain.RotamerLibEntry(p_other*0.01,ToRadian(chi1),ToRadian(chi2),ToRadian(chi3),ToRadian(chi4),
-                                          ToRadian(sig1),ToRadian(sig2),ToRadian(sig3),ToRadian(sig4))
-
-  lib.AddRotamer(sidechain.TYR,entry)
-  lib_alpha.AddRotamer(sidechain.TYR,entry_alpha)
-  lib_beta.AddRotamer(sidechain.TYR,entry_beta)
-  lib_other.AddRotamer(sidechain.TYR,entry_other)
-
-
-print
-print
-print "PHE"
-
-#handling Phenylalanine
-for i in range(175,181):
-  temp = data[i].split(',')
-  chi1 = float('NaN')
-  chi2 = float('NaN')
-  chi3 = float('NaN')
-  chi4 = float('NaN')
-
-  sig1 = float('NaN')
-  sig2 = float('NaN')
-  sig3 = float('NaN')
-  sig4 = float('NaN')
-
-  try:
-    chi1 = int(temp[6])
-    chi2 = int(temp[8])
-
-    sig1 = int(temp[11])
-    sig2 = int(temp[12])
-  except:
-    #some rotamers have really low probability and consequently no
-    #no mode values. This results in int(' ') => error => neglect the shit
-    print "PHE fail..."
-    continue
-
-  p = 0.0
-  p_alpha = 0.0
-  p_beta = 0.0
-  p_other = 0.0
-
-  str_p = temp[2]
-  if "<1%" in str_p:
-    p = 0.5
-  else:
-    p = float(str_p.strip().strip('%').strip('<'))
-
-  str_p = temp[3]
-  if "<1%" in str_p:
-    p_alpha = 0.5
-  else:
-    p_alpha = float(str_p.strip().strip('%').strip('<'))
-
-  str_p = temp[4]
-  if "<1%" in str_p:
-    p_beta = 0.5
-  else:
-    p_beta = float(str_p.strip().strip('%').strip('<'))
-
-  str_p = temp[5]
-  if "<1%" in str_p:
-    p_other = 0.5
-  else:
-    p_other = float(str_p.strip().strip('%').strip('<'))
-
-  print p, p_alpha, p_beta, p_other, chi1,chi2,chi3,chi4,sig1,sig2,sig3,sig4 
-
-  entry = sidechain.RotamerLibEntry(p*0.01,ToRadian(chi1),ToRadian(chi2),ToRadian(chi3),ToRadian(chi4),
-                                    ToRadian(sig1),ToRadian(sig2),ToRadian(sig3),ToRadian(sig4))
-  entry_alpha = sidechain.RotamerLibEntry(p_alpha*0.01,ToRadian(chi1),ToRadian(chi2),ToRadian(chi3),ToRadian(chi4),
-                                          ToRadian(sig1),ToRadian(sig2),ToRadian(sig3),ToRadian(sig4))
-  entry_beta = sidechain.RotamerLibEntry(p_beta*0.01,ToRadian(chi1),ToRadian(chi2),ToRadian(chi3),ToRadian(chi4),
-                                         ToRadian(sig1),ToRadian(sig2),ToRadian(sig3),ToRadian(sig4))
-  entry_other = sidechain.RotamerLibEntry(p_other*0.01,ToRadian(chi1),ToRadian(chi2),ToRadian(chi3),ToRadian(chi4),
-                                          ToRadian(sig1),ToRadian(sig2),ToRadian(sig3),ToRadian(sig4))
-
-  lib.AddRotamer(sidechain.PHE,entry)
-  lib_alpha.AddRotamer(sidechain.PHE,entry_alpha)
-  lib_beta.AddRotamer(sidechain.PHE,entry_beta)
-  lib_other.AddRotamer(sidechain.PHE,entry_other)
-
-print
-print
-print "PRO"
-
-#handling Proline
-for i in range(182,187):
-  temp = data[i].split(',')
-  chi1 = float('NaN')
-  chi2 = float('NaN')
-  chi3 = float('NaN')
-  chi4 = float('NaN')
-
-  sig1 = float('NaN')
-  sig2 = float('NaN')
-  sig3 = float('NaN')
-  sig4 = float('NaN')
-
-  try:
-    chi1 = int(temp[6])
-
-    sig1 = int(temp[11])
-  except:
-    #some rotamers have really low probability and consequently no
-    #no mode values. This results in int(' ') => error => neglect the shit
-    print "PRO fail..."
-    continue
-
-  p = 0.0
-  p_alpha = 0.0
-  p_beta = 0.0
-  p_other = 0.0
-
-  str_p = temp[2]
-  if "<1%" in str_p:
-    p = 0.5
-  else:
-    p = float(str_p.strip().strip('%').strip('<'))
-
-  str_p = temp[3]
-  if "<1%" in str_p:
-    p_alpha = 0.5
-  else:
-    p_alpha = float(str_p.strip().strip('%').strip('<'))
-
-  str_p = temp[4]
-  if "<1%" in str_p:
-    p_beta = 0.5
-  else:
-    p_beta = float(str_p.strip().strip('%').strip('<'))
-
-  str_p = temp[5]
-  if "<1%" in str_p:
-    p_other = 0.5
-  else:
-    p_other = float(str_p.strip().strip('%').strip('<'))
-
-  print p, p_alpha, p_beta, p_other, chi1,chi2,chi3,chi4,sig1,sig2,sig3,sig4  
-
-  entry = sidechain.RotamerLibEntry(p*0.01,ToRadian(chi1),ToRadian(chi2),ToRadian(chi3),ToRadian(chi4),
-                                    ToRadian(sig1),ToRadian(sig2),ToRadian(sig3),ToRadian(sig4))
-  entry_alpha = sidechain.RotamerLibEntry(p_alpha*0.01,ToRadian(chi1),ToRadian(chi2),ToRadian(chi3),ToRadian(chi4),
-                                          ToRadian(sig1),ToRadian(sig2),ToRadian(sig3),ToRadian(sig4))
-  entry_beta = sidechain.RotamerLibEntry(p_beta*0.01,ToRadian(chi1),ToRadian(chi2),ToRadian(chi3),ToRadian(chi4),
-                                         ToRadian(sig1),ToRadian(sig2),ToRadian(sig3),ToRadian(sig4))
-  entry_other = sidechain.RotamerLibEntry(p_other*0.01,ToRadian(chi1),ToRadian(chi2),ToRadian(chi3),ToRadian(chi4),
-                                          ToRadian(sig1),ToRadian(sig2),ToRadian(sig3),ToRadian(sig4))
-
-  lib.AddRotamer(sidechain.PRO,entry)
-  lib_alpha.AddRotamer(sidechain.PRO,entry_alpha)
-  lib_beta.AddRotamer(sidechain.PRO,entry_beta)
-  lib_other.AddRotamer(sidechain.PRO,entry_other)
-
-
-print
-print
-print "THR"
-
-#handling Threonine
-for i in range(188,193):
-  temp = data[i].split(',')
-  chi1 = float('NaN')
-  chi2 = float('NaN')
-  chi3 = float('NaN')
-  chi4 = float('NaN')
-
-  sig1 = float('NaN')
-  sig2 = float('NaN')
-  sig3 = float('NaN')
-  sig4 = float('NaN')
-
-  try:
-    chi1 = int(temp[6])
-
-    sig1 = int(temp[9])
-  except:
-    #some rotamers have really low probability and consequently no
-    #no mode values. This results in int(' ') => error => neglect the shit
-    print "THR fail..."
-    continue
-
-  p = 0.0
-  p_alpha = 0.0
-  p_beta = 0.0
-  p_other = 0.0
-
-  str_p = temp[2]
-  if "<1%" in str_p:
-    p = 0.5
-  else:
-    p = float(str_p.strip().strip('%').strip('<'))
-
-  str_p = temp[3]
-  if "<1%" in str_p:
-    p_alpha = 0.5
-  else:
-    p_alpha = float(str_p.strip().strip('%').strip('<'))
-
-  str_p = temp[4]
-  if "<1%" in str_p:
-    p_beta = 0.5
-  else:
-    p_beta = float(str_p.strip().strip('%').strip('<'))
-
-  str_p = temp[5]
-  if "<1%" in str_p:
-    p_other = 0.5
-  else:
-    p_other = float(str_p.strip().strip('%').strip('<'))
-
-  print p, p_alpha, p_beta, p_other, chi1,chi2,chi3,chi4,sig1,sig2,sig3,sig4  
-
-  entry = sidechain.RotamerLibEntry(p*0.01,ToRadian(chi1),ToRadian(chi2),ToRadian(chi3),ToRadian(chi4),
-                                    ToRadian(sig1),ToRadian(sig2),ToRadian(sig3),ToRadian(sig4))
-  entry_alpha = sidechain.RotamerLibEntry(p_alpha*0.01,ToRadian(chi1),ToRadian(chi2),ToRadian(chi3),ToRadian(chi4),
-                                          ToRadian(sig1),ToRadian(sig2),ToRadian(sig3),ToRadian(sig4))
-  entry_beta = sidechain.RotamerLibEntry(p_beta*0.01,ToRadian(chi1),ToRadian(chi2),ToRadian(chi3),ToRadian(chi4),
-                                         ToRadian(sig1),ToRadian(sig2),ToRadian(sig3),ToRadian(sig4))
-  entry_other = sidechain.RotamerLibEntry(p_other*0.01,ToRadian(chi1),ToRadian(chi2),ToRadian(chi3),ToRadian(chi4),
-                                          ToRadian(sig1),ToRadian(sig2),ToRadian(sig3),ToRadian(sig4))
-
-  lib.AddRotamer(sidechain.THR,entry)
-  lib_alpha.AddRotamer(sidechain.THR,entry_alpha)
-  lib_beta.AddRotamer(sidechain.THR,entry_beta)
-  lib_other.AddRotamer(sidechain.THR,entry_other)
-
-
-
-print
-print
-print "VAL"
-
-#handling Valine
-for i in range(194,199):
-  temp = data[i].split(',')
-  chi1 = float('NaN')
-  chi2 = float('NaN')
-  chi3 = float('NaN')
-  chi4 = float('NaN')
-
-  sig1 = float('NaN')
-  sig2 = float('NaN')
-  sig3 = float('NaN')
-  sig4 = float('NaN')
-
-  try:
-    chi1 = int(temp[6])
-
-    sig1 = int(temp[9])
-  except:
-    #some rotamers have really low probability and consequently no
-    #no mode values. This results in int(' ') => error => neglect the shit
-    print "VAL fail..."
-    continue
-
-  p = 0.0
-  p_alpha = 0.0
-  p_beta = 0.0
-  p_other = 0.0
-
-  str_p = temp[2]
-  if "<1%" in str_p:
-    p = 0.5
-  else:
-    p = float(str_p.strip().strip('%').strip('<'))
-
-  str_p = temp[3]
-  if "<1%" in str_p:
-    p_alpha = 0.5
-  else:
-    p_alpha = float(str_p.strip().strip('%').strip('<'))
-
-  str_p = temp[4]
-  if "<1%" in str_p:
-    p_beta = 0.5
-  else:
-    p_beta = float(str_p.strip().strip('%').strip('<'))
-
-  str_p = temp[5]
-  if "<1%" in str_p:
-    p_other = 0.5
-  else:
-    p_other = float(str_p.strip().strip('%').strip('<'))
-
-  print p, p_alpha, p_beta, p_other, chi1,chi2,chi3,chi4,sig1,sig2,sig3,sig4  
-
-  entry = sidechain.RotamerLibEntry(p*0.01,ToRadian(chi1),ToRadian(chi2),ToRadian(chi3),ToRadian(chi4),
-                                    ToRadian(sig1),ToRadian(sig2),ToRadian(sig3),ToRadian(sig4))
-  entry_alpha = sidechain.RotamerLibEntry(p_alpha*0.01,ToRadian(chi1),ToRadian(chi2),ToRadian(chi3),ToRadian(chi4),
-                                          ToRadian(sig1),ToRadian(sig2),ToRadian(sig3),ToRadian(sig4))
-  entry_beta = sidechain.RotamerLibEntry(p_beta*0.01,ToRadian(chi1),ToRadian(chi2),ToRadian(chi3),ToRadian(chi4),
-                                         ToRadian(sig1),ToRadian(sig2),ToRadian(sig3),ToRadian(sig4))
-  entry_other = sidechain.RotamerLibEntry(p_other*0.01,ToRadian(chi1),ToRadian(chi2),ToRadian(chi3),ToRadian(chi4),
-                                          ToRadian(sig1),ToRadian(sig2),ToRadian(sig3),ToRadian(sig4))
-
-  lib.AddRotamer(sidechain.VAL,entry)
-  lib_alpha.AddRotamer(sidechain.VAL,entry_alpha)
-  lib_beta.AddRotamer(sidechain.VAL,entry_beta)
-  lib_other.AddRotamer(sidechain.VAL,entry_other)
-
-print
-print
-print "SER"
-
-#handling Serine
-for i in range(200,205):
-  temp = data[i].split(',')
-  chi1 = float('NaN')
-  chi2 = float('NaN')
-  chi3 = float('NaN')
-  chi4 = float('NaN')
-
-  sig1 = float('NaN')
-  sig2 = float('NaN')
-  sig3 = float('NaN')
-  sig4 = float('NaN')
-
-  try:
-    chi1 = int(temp[6])
-
-    sig1 = int(temp[9])
-  except:
-    #some rotamers have really low probability and consequently no
-    #no mode values. This results in int(' ') => error => neglect the shit
-    print "SER fail..."
-    continue
-
-  p = 0.0
-  p_alpha = 0.0
-  p_beta = 0.0
-  p_other = 0.0
-
-  str_p = temp[2]
-  if "<1%" in str_p:
-    p = 0.5
-  else:
-    p = float(str_p.strip().strip('%').strip('<'))
-
-  str_p = temp[3]
-  if "<1%" in str_p:
-    p_alpha = 0.5
-  else:
-    p_alpha = float(str_p.strip().strip('%').strip('<'))
-
-  str_p = temp[4]
-  if "<1%" in str_p:
-    p_beta = 0.5
-  else:
-    p_beta = float(str_p.strip().strip('%').strip('<'))
-
-  str_p = temp[5]
-  if "<1%" in str_p:
-    p_other = 0.5
-  else:
-    p_other = float(str_p.strip().strip('%').strip('<'))
-
-  print p, p_alpha, p_beta, p_other, chi1,chi2,chi3,chi4,sig1,sig2,sig3,sig4 
-
-  entry = sidechain.RotamerLibEntry(p*0.01,ToRadian(chi1),ToRadian(chi2),ToRadian(chi3),ToRadian(chi4),
-                                    ToRadian(sig1),ToRadian(sig2),ToRadian(sig3),ToRadian(sig4))
-  entry_alpha = sidechain.RotamerLibEntry(p_alpha*0.01,ToRadian(chi1),ToRadian(chi2),ToRadian(chi3),ToRadian(chi4),
-                                          ToRadian(sig1),ToRadian(sig2),ToRadian(sig3),ToRadian(sig4))
-  entry_beta = sidechain.RotamerLibEntry(p_beta*0.01,ToRadian(chi1),ToRadian(chi2),ToRadian(chi3),ToRadian(chi4),
-                                         ToRadian(sig1),ToRadian(sig2),ToRadian(sig3),ToRadian(sig4))
-  entry_other = sidechain.RotamerLibEntry(p_other*0.01,ToRadian(chi1),ToRadian(chi2),ToRadian(chi3),ToRadian(chi4),
-                                          ToRadian(sig1),ToRadian(sig2),ToRadian(sig3),ToRadian(sig4))
-
-  lib.AddRotamer(sidechain.SER,entry)
-  lib_alpha.AddRotamer(sidechain.SER,entry_alpha)
-  lib_beta.AddRotamer(sidechain.SER,entry_beta)
-  lib_other.AddRotamer(sidechain.SER,entry_other)
-
-
-
-print
-print
-print "CYS"
-
-#handling Cysteine
-for i in range(206,len(data)):
-  temp = data[i].split(',')
-  chi1 = float('NaN')
-  chi2 = float('NaN')
-  chi3 = float('NaN')
-  chi4 = float('NaN')
-
-  sig1 = float('NaN')
-  sig2 = float('NaN')
-  sig3 = float('NaN')
-  sig4 = float('NaN')
-
-  try:
-    chi1 = int(temp[6])
-
-    sig1 = int(temp[9])
-  except:
-    #some rotamers have really low probability and consequently no
-    #no mode values. This results in int(' ') => error => neglect the shit
-    print "CYS fail..."
-    continue
-
-  p = 0.0
-  p_alpha = 0.0
-  p_beta = 0.0
-  p_other = 0.0
-
-  str_p = temp[2]
-  if "<1%" in str_p:
-    p = 0.5
-  else:
-    p = float(str_p.strip().strip('%').strip('<'))
-
-  str_p = temp[3]
-  if "<1%" in str_p:
-    p_alpha = 0.5
-  else:
-    p_alpha = float(str_p.strip().strip('%').strip('<'))
-
-  str_p = temp[4]
-  if "<1%" in str_p:
-    p_beta = 0.5
-  else:
-    p_beta = float(str_p.strip().strip('%').strip('<'))
-
-  str_p = temp[5]
-  if "<1%" in str_p:
-    p_other = 0.5
-  else:
-    p_other = float(str_p.strip().strip('%').strip('<'))
-
-  print p, p_alpha, p_beta, p_other, chi1,chi2,chi3,chi4,sig1,sig2,sig3,sig4  
-
-  entry = sidechain.RotamerLibEntry(p*0.01,ToRadian(chi1),ToRadian(chi2),ToRadian(chi3),ToRadian(chi4),
-                                    ToRadian(sig1),ToRadian(sig2),ToRadian(sig3),ToRadian(sig4))
-  entry_alpha = sidechain.RotamerLibEntry(p_alpha*0.01,ToRadian(chi1),ToRadian(chi2),ToRadian(chi3),ToRadian(chi4),
-                                          ToRadian(sig1),ToRadian(sig2),ToRadian(sig3),ToRadian(sig4))
-  entry_beta = sidechain.RotamerLibEntry(p_beta*0.01,ToRadian(chi1),ToRadian(chi2),ToRadian(chi3),ToRadian(chi4),
-                                         ToRadian(sig1),ToRadian(sig2),ToRadian(sig3),ToRadian(sig4))
-  entry_other = sidechain.RotamerLibEntry(p_other*0.01,ToRadian(chi1),ToRadian(chi2),ToRadian(chi3),ToRadian(chi4),
-                                          ToRadian(sig1),ToRadian(sig2),ToRadian(sig3),ToRadian(sig4))
-
-  lib.AddRotamer(sidechain.CYS,entry)
-  lib_alpha.AddRotamer(sidechain.CYS,entry_alpha)
-  lib_beta.AddRotamer(sidechain.CYS,entry_beta)
-  lib_other.AddRotamer(sidechain.CYS,entry_other)
-
-
-
-lib.Save("Penultimate.dat")
-lib_alpha.Save("PenultimateAlpha.dat")
-lib_beta.Save("PenultimateBeta.dat")
-lib_other.Save("PenultimateOther.dat")
-
-
-
diff --git a/extras/data_generation/rotamer_library/do_lib.py b/extras/data_generation/rotamer_library/do_lib.py
new file mode 100644
index 0000000000000000000000000000000000000000..70a7a9e4ad8ead6df8cebb5ca672ed8c8081d9a7
--- /dev/null
+++ b/extras/data_generation/rotamer_library/do_lib.py
@@ -0,0 +1,324 @@
+import os, math, sys
+import numpy as np
+from scipy.ndimage import gaussian_filter
+from promod3 import sidechain
+
+if len(sys.argv) != 3:
+  print "USAGE: ost do_lib.py <path_to_data> <library_out_path>" 
+  sys.exit(0)
+
+# the csv file you created with fetch_data.py
+data_file_path = sys.argv[1]
+
+# library will be dumped here using the SavePortable() method
+library_out_path = sys.argv[2]
+
+
+# default parametrization
+
+# Width of bins to sample for non rotameric dihedral angles (in degrees)
+# e.g. in case of GLN you'll have 360 / 30 = 12 conformations for the
+# terminal dihedral angle if you keep the default (30).
+non_rot_sampling = 30 
+
+# An initial pdf is generated for the non-rotameric chi angles. The pdf is
+# smoothed with a circular gaussian function with following standard 
+# deviation (in degrees)
+non_rot_smooth_std = 10
+
+def GetNonRotChiStats(chi, non_rot_sampling, symmetric, smooth_std):
+
+  # stupid check 
+  if 180 % non_rot_sampling != 0:
+    raise RuntimeError("180 must be dividable by non_rot_sampling!")
+
+  n_sampled_rotamers = 360 / non_rot_sampling
+  if symmetric:
+    n_sampled_rotamers = 180 / non_rot_sampling
+
+  # symmetric or not, we first fill in a histogram covering a range of 2 pi
+  n_histogram_bins = 2 * 360 
+  histogram = np.zeros(n_histogram_bins)
+  bin_size = 2*np.pi/n_histogram_bins
+
+  # we add up the histogram by weights as estimated with the mises distribution
+  angle_bins = np.clip(np.floor((chi + np.pi) / bin_size), 0, len(histogram)-1)
+  for angle_bin in angle_bins:
+    histogram[int(angle_bin)] += 1.0
+
+  # if we're dealing with a symmetric distribution, we simply add up the
+  # first and second half of the histogram. The histogram has then an angle
+  # range of [-pi,0.0[
+  if symmetric:
+    n_histogram_bins /= 2
+    histogram = np.add(histogram[:n_histogram_bins], 
+                       histogram[n_histogram_bins:])
+
+  # translate the smooth_std, which is in degree, to bins in the histogram
+  # and apply it with a simple gaussian filter
+  gaussian_std = float(smooth_std) / 180 * np.pi / bin_size
+  histogram = gaussian_filter(histogram, gaussian_std, mode="wrap")
+  histogram = histogram / sum(histogram)
+
+  # find the maximum element, as this is the center of the first "window"
+  # of width non_rot_sampling
+  max_idx = np.argmax(histogram)
+  current_angle = max_idx * bin_size - np.pi
+
+  # concatenate, so we dont have to care for circularity anymore
+  histogram = np.concatenate((histogram, histogram, histogram, histogram))
+  
+  rad_non_rot_sampling = float(non_rot_sampling) / 180 * np.pi
+  first_start_angle = current_angle - rad_non_rot_sampling / 2
+
+  if first_start_angle < -np.pi:
+    # With this first angle we would get an underflow...
+    # we did so many concatenatinons, that we can add 360 degrees, even for
+    # the symmetric case
+    current_angle += 2*np.pi
+
+  probabilities = np.zeros(n_sampled_rotamers)
+  mean_values = np.zeros(n_sampled_rotamers)
+  std_values = np.zeros(n_sampled_rotamers)
+
+  for i in range(n_sampled_rotamers):
+    start_angle = current_angle - rad_non_rot_sampling / 2
+    end_angle = current_angle + rad_non_rot_sampling / 2
+
+    start_bin = int((start_angle + np.pi) / bin_size)
+    end_bin = int((end_angle + np.pi) / bin_size)
+    local_values = histogram[start_bin:end_bin+1]
+    normalized_local_values = local_values / sum(local_values)
+    angle_values = np.linspace(start_angle, end_angle, len(local_values))
+
+    probabilities[i] = np.sum(local_values)
+    mean_values[i] = np.sum(np.multiply(normalized_local_values, angle_values))
+    squared_std = np.sum(np.multiply(np.square(angle_values - mean_values[i]), 
+                                               normalized_local_values))
+    std_values[i] = np.sqrt(squared_std)
+
+    current_angle += rad_non_rot_sampling
+
+  # The probabilities of all ranges should add up to one...
+  # however, depending on the rounding etc., this might not exactly be the case.
+  # All probabilities need an additional normalization in the end
+  probabilities /= np.sum(probabilities)
+
+  # due to the concatenation, we still have mean values > pi.
+  # let's enforce valid ranges...
+  for i in range(len(mean_values)):
+    while mean_values[i] > np.pi:
+      mean_values[i] -= 2*np.pi
+
+  return probabilities, mean_values, std_values
+
+def GetChiStats(chi):
+  # do the mean
+  a = np.sum(np.sin(chi))
+  b = np.sum(np.cos(chi))
+  mean_value = np.arctan2(a, b)
+  # do the std
+  diffs = np.minimum(np.minimum(np.absolute(chi - mean_value), 
+                                np.absolute(chi - (mean_value + 2*np.pi))), 
+                     np.absolute(chi - (mean_value - 2*np.pi)))
+  squared_std = np.sum(np.square(diffs)) / len(diffs)
+  return (mean_value, np.sqrt(squared_std))
+
+
+def DoIt(aa_name, data_file_path, library, non_rot_sampling = 30, 
+         non_rot_smooth_std = 10):
+
+  print "processing", aa_name
+  
+  # Parse CSV file
+  data = open(data_file_path, 'r').readlines()
+
+  # get data indices
+  header = [item.strip() for item in data[0].split(',')]
+
+  # will throw an error if not there
+  rname_idx = header.index("rname")
+  chi1_idx = header.index("chi1")
+  chi2_idx = header.index("chi2")
+  chi3_idx = header.index("chi3")
+  chi4_idx = header.index("chi4")
+  conf1_idx = header.index("conf1")
+  conf2_idx = header.index("conf2")
+  conf3_idx = header.index("conf3")
+  conf4_idx = header.index("conf4")
+  str_c = ["GAUCHE_MINUS", "GAUCHE_PLUS", "TRANS", "NON_ROTAMERIC", "INVALID"]
+  promod_c = [sidechain.GAUCHE_MINUS, sidechain.GAUCHE_PLUS, sidechain.TRANS, 
+              sidechain.NON_ROTAMERIC, sidechain.INVALID]
+
+  # get the data
+  aa_data = {"chi1" : [], "chi2" : [], "chi3" : [], "chi4" : [], 
+             "conf1" : [], "conf2" : [], "conf3" : [], "conf4" : []}
+  
+  for line in data[1:]:
+    split_line = [item.strip() for item in line.split(',')]
+    rname = split_line[rname_idx]
+    if rname == aa_name:
+      aa_data["chi1"].append(float(split_line[chi1_idx]))
+      aa_data["chi2"].append(float(split_line[chi2_idx]))
+      aa_data["chi3"].append(float(split_line[chi3_idx]))
+      aa_data["chi4"].append(float(split_line[chi4_idx]))
+      aa_data["conf1"].append(promod_c[str_c.index(split_line[conf1_idx])])
+      aa_data["conf2"].append(promod_c[str_c.index(split_line[conf2_idx])])
+      aa_data["conf3"].append(promod_c[str_c.index(split_line[conf3_idx])])
+      aa_data["conf4"].append(promod_c[str_c.index(split_line[conf4_idx])])
+  
+  # convert all dihedral angles into numpy arrays
+  aa_data["chi1"] = np.array(aa_data["chi1"])
+  aa_data["chi2"] = np.array(aa_data["chi2"])
+  aa_data["chi3"] = np.array(aa_data["chi3"])
+  aa_data["chi4"] = np.array(aa_data["chi4"])
+
+  # the configurations in aa_data are stored in four lists with keys 
+  # conf1, conf2... we translate that to a unique string
+  configurations = list()
+  for a, b, c, d in zip(aa_data["conf1"], aa_data["conf2"], 
+                        aa_data["conf3"], aa_data["conf4"]):
+    configurations.append("%i%i%i%i"%(int(a), int(b), int(c), int(d)))
+  unique_configurations = list(set(configurations))
+
+  # we need configuration dependent chix
+  conf_chi1 = dict()
+  conf_chi2 = dict()
+  conf_chi3 = dict()
+  conf_chi4 = dict()
+  rotameric_probabilities = dict()
+
+  for uc in unique_configurations:
+    indices = [i for i, c in enumerate(configurations) if c == uc]
+    conf_chi1[uc] = aa_data["chi1"][indices]
+    conf_chi2[uc] = aa_data["chi2"][indices]
+    conf_chi3[uc] = aa_data["chi3"][indices]
+    conf_chi4[uc] = aa_data["chi4"][indices]
+    rotameric_probabilities[uc] = float(len(indices)) / len(configurations)
+
+  rot_confs = [int(sidechain.TRANS), int(sidechain.GAUCHE_MINUS),
+               int(sidechain.GAUCHE_PLUS)] 
+
+  for uc in unique_configurations:
+
+    rotameric_chi1 = float("nan")
+    rotameric_sig1 = float("nan")
+    rotameric_chi2 = float("nan")
+    rotameric_sig2 = float("nan")
+    rotameric_chi3 = float("nan")
+    rotameric_sig3 = float("nan")
+    rotameric_chi4 = float("nan")
+    rotameric_sig4 = float("nan")
+
+    # do chi1
+    if int(uc[0]) in rot_confs:
+      mean, std = GetChiStats(conf_chi1[uc])
+      rotameric_chi1 = mean
+      rotameric_sig1 = std
+    # do chi2
+    if int(uc[1]) in rot_confs:
+      mean, std = GetChiStats(conf_chi2[uc])
+      rotameric_chi2 = mean
+      rotameric_sig2 = std
+    # do chi3
+    if int(uc[2]) in rot_confs:
+      mean, std = GetChiStats(conf_chi3[uc])
+      rotameric_chi3 = mean
+      rotameric_sig3 = std
+    # do chi4
+    if int(uc[3]) in rot_confs:
+      mean, std = GetChiStats(conf_chi4[uc])
+      rotameric_chi4 = mean
+      rotameric_sig4 = std
+
+    # so far we only treated rotameric dihedral angles. 
+    # ASN(chi2), ASP(chi2), PHE(chi2), TYR(chi2), HIS(chi2), TRP(chi2), 
+    # GLN(chi3) and GLU(chi3) exhibit so called non-rotameric degrees
+    # of freedom and require further sampling of their terminal 
+    # dihedral angle.
+    if aa_name in ["ASN", "ASP", "PHE", "TYR", "HIS", "TRP", "GLN", "GLU"]:
+      non_rotameric_chi_idx = 1
+      if aa_name in ["GLN", "GLU"]:
+        non_rotameric_chi_idx = 2
+      symmetric = False
+      if aa_name in ["ASP", "PHE", "TYR", "GLU"]:
+        symmetric = True
+      chi_angles = None
+      if non_rotameric_chi_idx == 1:
+        chi_angles = conf_chi2[uc]
+      elif non_rotameric_chi_idx == 2:
+        chi_angles = conf_chi3[uc]
+      probs, mean_values, std_values = GetNonRotChiStats(chi_angles,
+                                                         non_rot_sampling,
+                                                         symmetric, 
+                                                         non_rot_smooth_std)
+      for p, m, s in zip(probs, mean_values, std_values):
+        rot = sidechain.RotamerLibEntry(p*rotameric_probabilities[uc],
+                                        rotameric_chi1, rotameric_chi2,
+                                        rotameric_chi3, rotameric_chi4,
+                                        rotameric_sig1, rotameric_sig2,
+                                        rotameric_sig3, rotameric_sig4)
+        if non_rotameric_chi_idx == 1:
+          rot.chi2 = m
+          rot.sig2 = s
+        elif non_rotameric_chi_idx == 2:
+          rot.chi3 = m
+          rot.sig3 = s
+        lib.AddRotamer(sidechain.TLCToRotID(aa_name), rot)
+    else:
+      rot = sidechain.RotamerLibEntry(rotameric_probabilities[uc],
+                                      rotameric_chi1, rotameric_chi2,
+                                      rotameric_chi3, rotameric_chi4,
+                                      rotameric_sig1, rotameric_sig2,
+                                      rotameric_sig3, rotameric_sig4)
+      lib.AddRotamer(sidechain.TLCToRotID(aa_name), rot)
+
+
+
+lib = sidechain.RotamerLib()
+DoIt("ARG", data_file_path, lib, non_rot_sampling = non_rot_sampling, 
+     non_rot_smooth_std = non_rot_smooth_std)
+DoIt("ASN", data_file_path, lib, non_rot_sampling = non_rot_sampling, 
+     non_rot_smooth_std = non_rot_smooth_std)
+DoIt("ASP", data_file_path, lib, non_rot_sampling = non_rot_sampling, 
+     non_rot_smooth_std = non_rot_smooth_std)
+DoIt("GLN", data_file_path, lib, non_rot_sampling = non_rot_sampling, 
+     non_rot_smooth_std = non_rot_smooth_std)
+DoIt("GLU", data_file_path, lib, non_rot_sampling = non_rot_sampling, 
+     non_rot_smooth_std = non_rot_smooth_std)
+DoIt("LYS", data_file_path, lib, non_rot_sampling = non_rot_sampling, 
+     non_rot_smooth_std = non_rot_smooth_std)
+DoIt("SER", data_file_path, lib, non_rot_sampling = non_rot_sampling, 
+     non_rot_smooth_std = non_rot_smooth_std)
+DoIt("CYH", data_file_path, lib, non_rot_sampling = non_rot_sampling, 
+     non_rot_smooth_std = non_rot_smooth_std)
+DoIt("CYD", data_file_path, lib, non_rot_sampling = non_rot_sampling, 
+     non_rot_smooth_std = non_rot_smooth_std)
+DoIt("CYS", data_file_path, lib, non_rot_sampling = non_rot_sampling, 
+     non_rot_smooth_std = non_rot_smooth_std)
+DoIt("MET", data_file_path, lib, non_rot_sampling = non_rot_sampling, 
+     non_rot_smooth_std = non_rot_smooth_std)
+DoIt("TRP", data_file_path, lib, non_rot_sampling = non_rot_sampling, 
+     non_rot_smooth_std = non_rot_smooth_std)
+DoIt("TYR", data_file_path, lib, non_rot_sampling = non_rot_sampling, 
+     non_rot_smooth_std = non_rot_smooth_std)
+DoIt("THR", data_file_path, lib, non_rot_sampling = non_rot_sampling, 
+     non_rot_smooth_std = non_rot_smooth_std)
+DoIt("VAL", data_file_path, lib, non_rot_sampling = non_rot_sampling, 
+     non_rot_smooth_std = non_rot_smooth_std)
+DoIt("ILE", data_file_path, lib, non_rot_sampling = non_rot_sampling, 
+     non_rot_smooth_std = non_rot_smooth_std)
+DoIt("LEU", data_file_path, lib, non_rot_sampling = non_rot_sampling, 
+     non_rot_smooth_std = non_rot_smooth_std)
+DoIt("CPR", data_file_path, lib, non_rot_sampling = non_rot_sampling, 
+     non_rot_smooth_std = non_rot_smooth_std)
+DoIt("TPR", data_file_path, lib, non_rot_sampling = non_rot_sampling, 
+     non_rot_smooth_std = non_rot_smooth_std)
+DoIt("PRO", data_file_path, lib, non_rot_sampling = non_rot_sampling, 
+     non_rot_smooth_std = non_rot_smooth_std)
+DoIt("HIS", data_file_path, lib, non_rot_sampling = non_rot_sampling, 
+     non_rot_smooth_std = non_rot_smooth_std)
+DoIt("PHE", data_file_path, lib, non_rot_sampling = non_rot_sampling, 
+     non_rot_smooth_std = non_rot_smooth_std)
+lib.MakeStatic()
+lib.SavePortable(library_out_path)
diff --git a/extras/data_generation/rotamer_library/penultimate.csv b/extras/data_generation/rotamer_library/penultimate.csv
deleted file mode 100755
index 8f4e358125c69728d11444394ebb7385d90b6da0..0000000000000000000000000000000000000000
--- a/extras/data_generation/rotamer_library/penultimate.csv
+++ /dev/null
@@ -1,211 +0,0 @@
-#This file is simply copied and pasted from the online publication...
-#Note, that it can't be changed anymore, so the according script can
-#parse it in a simple manner...
-
-Arginine, , , , , , , , , , , , , , , , , 
-ptp85°b,3,<1%c,0%,1%,<1%, ,62, ,180, ,65, ,85, , , , 
-ptp180°,11,1%,0%,2%,2%,71,62,171,180,65,65,-161,-175,14,17,10,13
-ptt85°,16,2%,1%,2%,2%,65,62,-178,180,-179,180,88,85,13,14,13,17
-ptt180°,16,2%,1%,2%,2%,59,62,176,180,-178,180,-177,180,15,13,15,19
-ptt-85°,15,2%,1%,2%,2%,66,62,-176,180,-178,180,-83,-85,15,14,12,14
-ptm180°,6,1%,0%,1%,1%, ,62, ,180, ,-65, ,175, , , , 
-ptm-85°,5,1%,0%,0%,1%, ,62, ,180, ,-65, ,-85, , , , 
-tpp85°,11,1%,3%,1%,<1%,-178,-177,57,65,57,65,85,85,13,13,12,15
-tpp180°,8,1%,1%,0%,1%, ,-177, ,65, ,65, ,-175, , , , 
-tpt85°,20,2%,3%,2%,2%,177,-177,64,65,180,180,86,85,14,13,15,14
-tpt180°,15,2%,3%,1%,1%,179,-177,60,65,178,180,163,180,13,17,14,17
-ttp85°,33,4%,5%,3%,3%,-179,-177,177,180,65,65,83,85,14,17,13,15
-ttp180°,25,3%,5%,3%,1%,-178,-177,-178,180,65,65,-162,-175,14,16,14,26
-ttp-105°,9,1%,1%,1%,1%, ,-177, ,180, ,65, ,-105, , , , 
-ttt85°,19,2%,2%,2%,2%,-175,-177,176,180,179,180,83,85,14,14,13,14
-ttt180°,33,4%,3%,7%,3%,-179,-177,177,180,-179,180,170,180,15,13,12,27
-ttt-85°,26,3%,3%,3%,2%,-179,-177,179,180,180,180,-86,-85,15,14,14,15
-ttm105°,10,1%,2%,1%,<1%,-178,-177,170,180,-66,-65,107,105,15,16,15,15
-ttm180°,13,1%,<1%,4%,1%,180,-177,-178,180,-67,-65,176,175,15,12,11,15
-ttm-85°,28,3%,3%,3%,3%,-175,-177,-178,180,-65,-65,-84,-85,14,16,15,14
-mtp85°,22,2%,2%,3%,2%,-69,-67,177,180,64,65,84,85,13,17,13,13
-mtp180°,45,5%,4%,3%,6%,-65,-67,176,180,64,65,-174,-175,12,19,13,19
-mtp-105°,7,1%,0%,2%,1%,-62,-67,179,180,67,65,-113,-105,11,15,13,15
-mtt85°,34,4%,4%,4%,3%,-67,-67,178,180,179,180,83,85,12,19,13,19
-mtt180°,89,9%,9%,5%,12%,-67,-67,-178,180,-177,180,174,180,14,13,13,21
-mtt-85°,53,6%,4%,7%,6%,-66,-67,-177,180,-179,180,-83,-85,13,13,13,13
-mtm105°,15,2%,1%,1%,2%,-68,-67,-179,180,-65,-65,103,105,12,13,13,15
-mtm180°,48,5%,1%,4%,8%,-68,-67,173,180,-64,-65,180,175,14,17,13,30
-mtm-85°,54,6%,13%,2%,3%,-69,-67,-167,-167,-63,-65,-86,-85,14,13,13,13
-mmt85°,7,1%,1%,1%,1%, ,-62, ,-68, ,180, ,85, , , , 
-mmt180°,18,2%,1%,3%,2%,-63,-62,-66,-68,-179,180,-168,180,13,13,10,29
-mmt-85°,22,2%,<1%,4%,3%,-60,-62,-72,-68,-178,180,-92,-85,14,13,15,13
-mmm180°,11,1%,<1%,2%,2%,-64,-62,-74,-68,-67,-65,172,175,14,15,10,13
-mmm-85°,22,2%,2%,3%,3%,-62,-62,-64,-68,-61,-65,-82,-85,14,13,15,13
- , ,82%,79%,81%,84%, , , , , , , , , , , , 
- ,769/938d, ,234,146,389, , , , , , , , , , , , 
-Lysine, , , , , , , , , , , , , , , , , 
-ptpt,7,1%,0%,2%,<1%, ,62, ,180, ,68, ,180, , , , 
-pttp,13,1%,0%,1%,2%,63,62,-170,180,-177,180,72,65,13,14,14,11
-pttt,29,2%,0%,4%,3%,63,62,-178,180,178,180,-179,180,13,13,13,10
-pttm,8,1%,0%,1%,1%, ,62, ,180, ,180, ,-65, , , , 
-ptmt,5,<1%,0%,1%,<1%, ,62, ,180, ,-68, ,180, , , , 
-tptp,11,1%,1%,1%,1%,179,-177,59,68,163,180,60,65,13,12,10,11
-tptt,32,3%,5%,1%,2%,179,-177,62,68,173,180,171,180,10,10,13,14
-tptm,7,1%,1%,1%,<1%, ,-177, ,68, ,180, ,-65,14,9,12,10
-ttpp,12,1%,1%,<1%,1%, ,-177, ,180, ,68, ,65, , , , 
-ttpt,25,2%,2%,5%,1%,180,-177,179,180,78,68,179,180,14,12,14,14
-tttp,49,4%,5%,5%,3%,-177,-177,180,180,171,180,63,65,14,13,12,12
-tttt,162,13%,17%,19%,10%,-177,-177,178,180,179,180,180,180,13,13,15,13
-tttm,37,3%,4%,2%,3%,-177,-177,172,180,178,180,-72,-65,12,13,15,13
-ttmt,20,2%,2%,4%,1%,-175,-177,-174,180,-69,-68,179,180,14,14,10,15
-ttmm,5,<1%,1%,0%,<1%, ,-177, ,180, ,-68, ,-65, , , , 
-mptt,4,<1%,0%,0%,1%, ,-90, ,68, ,180, ,180, , , , 
-mtpp,12,1%,1%,1%,1%,-69,-67,-179,180,70,68,67,65,10,9,10,13
-mtpt,38,3%,4%,2%,3%,-69,-67,164,180,62,68,-179,180,12,13,11,9
-mttp,42,3%,2%,4%,4%,-67,-67,-176,180,174,180,76,65,13,13,14,14
-mttt,244,20%,23%,14%,21%,-67,-67,176,180,179,180,177,180,14,13,12,14
-mttm,56,5%,3%,5%,6%,-67,-67,-179,180,-179,180,-63,-65,13,12,13,14
-mtmt,40,3%,6%,2%,3%,-70,-67,-170,180,-66,-68,-175,180,12,13,14,13
-mtmm,12,1%,0%,1%,1%,-70,-67,-179,180,-66,-68,-64,-65,12,12,12,11
-mmtp,9,1%,<1%,0%,1%, ,-62, ,-68, ,180, ,65, , , , 
-mmtt,77,6%,3%,5%,8%,-58,-62,-61,-68,-177,180,-179,180,12,13,13,13
-mmtm,18,1%,1%,1%,2%,-59,-62,-69,-68,-176,180,-70,-65,14,12,10,15
-mmmt,10,1%,<1%,1%,1%,-59,-62,-58,-68,-75,-68,-174,180,12,13,10,15
- , ,81%,82%,80%,82%, , , , , , , , , , , , 
- ,984/1209, ,261,194,529,,,,,,,,,,,,
-Methionine, , , , , , , , , , , , , , , ,,
-ptp,12,2%,1%,3%,3%,68,62,-167,180,88,75, ,11,17,12,,
-ptm,17,3%,1%,6%,4%,67,62,174,180,-78,-75, ,9,10,9,,
-tpp,30,5%,8%,2%,5%,-177,-177,66,65,75,75, ,10,15,15,,
-tpt,9,2%,1%,4%,1%,179,-177,67,65,-179,180, ,9,8,9,,
-ttp,28,5%,7%,7%,2%,176,-177,178,180,73,75, ,10,11,11,,
-ttt,17,3%,5%,2%,2%,180,-177,171,180,174,180, ,9,9,19,,
-ttm,36,7%,3%,10%,8%,-177,-177,176,180,-78,-75, ,10,10,13,,
-mtp,92,17%,22%,10%,17%,-68,-67,177,180,72,75, ,10,12,14,,
-mtt,43,8%,9%,8%,7%,-67,-67,177,180,-178,180, ,10,13,15,,
-mtm,58,11%,12%,11%,9%,-67,-67,-177,180,-76,-75, ,12,11,16,,
-mmp,15,3%,3%,1%,4%,-64,-65,-63,-65,103,103, ,9,10,10,,
-mmt,10,2%,0%,2%,3%,-63,-65,-64,-65,180,180, ,12,14,19,,
-mmm,105,19%,21%,16%,19%,-66,-65,-60,-65,-67,-70, ,11,13,16,,
- , ,86%,91%,84%,83%, , , , , , , , , , ,,
- ,472/550, ,175,112,185, , , , , , , , , , ,,
-Glutamate, , , , , , , , , , , , , , , ,,
-pt-20°,80,5%,1%,9%,7%,63,62,-175,180,-18,-20,-90 to 90,14,13,23,,
-pm0°,32,2%,0%,0%,4%,71,70,-79,-80,5,0,-50 to 50,14,13,17,,
-tp10°,91,6%,10%,2%,6%,-177,-177,65,65,13,10,-10 to 90,14,13,17,,
-tt 0°,350,24%,25%,42%,18%,-177,-177,178,180,2,0,-90 to 90,14,14,30,,
-tm-20°,17,1%,1%,1%,1%, ,-177, ,-80, ,-25,-50 to 10,13,13,15,,
-mp0°,88,6%,<1%,2%,10%,-65,-65,85,85,-3,0,-60 to 60,14,13,25,,
-mt-10°,484,33%,36%,29%,32%,-67,-67,177,180,-10,-10,-90 to 90,13,16,25,,
-mm-40°,197,13%,19%,7%,12%,-65,-65,-58,-65,-40,-40,-90 to 30,14,14,25,,
- , ,91%,92%,92%,90%, , , , , , , , , , ,,
- ,1339/1470, ,394,225,720, , , , , , , , , , ,,
-Glutamine, , , , , , , , , , , , , , , ,,
-pt 20°,37,4%,1%,5%,6%,64,62,180,180,20,20,-90 to 90,13,14,16,,
-pm0°,15,2%,0%,1%,3%, ,70, ,-75, ,0,-60 to 60, , , ,,
-tp-100°,14,2%,4%,2%,<1%, ,-177, ,65, ,-100,-150 to 0, , , ,,
-tp60°,78,9%,13%,9%,7%,-175,-177,64,65,60,60,0 to 90,14,15,24,,
-tt 0°,140,16%,16%,29%,12%,-174,-177,173,180,-5,0,-90 to 90,14,13,40,,
-mp0°,24,3%,<1%,1%,5%, ,-65, ,85, ,0,-60 to 60, , , ,,
-mt-30°,304,35%,40%,26%,36%,-67,-67,177,180,-25,-25,-90 to 90,16,15,37,,
-mm-40°,127,15%,12%,13%,17%,-66,-65,-60,-65,-40,-40,-95 to 0,16,18,26,,
-mm100°,22,3%,4%,1%,2%, ,-65, ,-65, ,100,0 to 150, , , ,,
- , ,88%,89%,86%,88%, , , , , , , , , , ,,
- ,761/863, ,229,137,395, , , , , , ,χ2, , , ,,
-Aspartate, , , , , , , , , , , ,range, , , ,,
-p-10°,203,10%,1%,2%,13%,61,62,-4,-10, , ,-90 to 0,9,19, ,,
-p30°,194,9%,1%,5%,12%,65,62,9,30, , ,0 to 90,8,14, ,,
-t0°,438,21%,8%,44%,20%,-176,-177,1,0, , ,-50 to 50,12,30, ,,
-t70°,118,6%,11%,7%,4%,-179,-177,65,65, , ,50 to 90,12,18, ,,
-m-20°,1088,51%,77%,38%,47%,-71,-70,-15,-15, , ,-90 to 20,10,16, ,,
- , ,96%,97%,95%,96%, , , , , , , , , , ,,
- ,2041/2124, ,365,232,1444, , , , , , , , , , ,,
-Asparagine, , , , , , , , , , , , , , , ,,
-p-10°,103,7%,0%,1%,10%,63,62,-13,-10, , ,-90 to 0,8,9, ,,
-p30°,132,9%,<1%,7%,12%,64,62,34,30, , ,0 to 90,6,7, ,,
-t-20°,177,12%,5%,21%,12%,-174,-174,-20,-20, , ,-120 to 0,5,21, ,,
-t30°,228,15%,13%,18%,15%,-168,-177,31,30, , ,0 to 80,14,22, ,,
-m-20°,580,39%,65%,28%,33%,-71,-65,-23,-20, , ,-60 to 10,10,20, ,,
-m-80°,118,8%,8%,9%,8%,-71,-65,-76,-75, , ,-100 to -60,9,9, ,,
-m120°,58,4%,3%,3%,4%,-64,-65,132,120, , ,60 to 160,9,18, ,,
- , ,94%,95%,88%,95%, , , , , , , , , , ,,
- ,1396/1490, ,293,179,924,,,,,,,,,,,,
-Isoleucine, , , , , , , , , , , , ,,,,,
-pp,10,1%,<1%,1%,<1%, ,62, ,100, , ,,,,,,
-pt,216,13%,4%,13%,22%,61,62,171,170, ,10,10,,,,,
-tp,36,2%,2%,1%,4%,-169,-177,66,66, ,13,11,,,,,
-tt,127,8%,1%,8%,14%,-174,-177,167,165, ,13,11,,,,,
-mp,19,1%,0%,2%,1%, ,-65, ,100, , , ,,,,,
-mt,993,60%,81%,58%,41%,-66,-65,169,170, ,10,10,,,,,
-mm,242,15%,10%,16%,17%,-57,-57,-59,-60, ,10,10,,,,,
- , ,99%,99%,98%,99%, , , , , , , ,,,,,
- ,1643/1667, ,496,629,518, , , , , , , ,,,,,
-Leucine, , , , , , , , , , , , ,,,,,
-pp,21,1%,<1%,2%,1%, ,62, ,80, , , ,,,,,
-tp,750,29%,30%,36%,23%,177,-177,63,65, ,10,10,,,,,
-tt,49,2%,1%,3%,1%,-172,-172,147,145,120 to 180,9,9,,,,,
-mp,63,2%,1%,5%,2%,-85,-85,66,65,45 to 105,11,14,,,,,
-mt,1548,59%,62%,46%,66%,-65,-65,174,175, ,11,11,,,,,
- , ,93%,95%,93%,93%, , , , , , , ,,,,,
- ,2431/2602, ,836,644,951, , , , , , , ,,,,,
-Histidine, , , , , , , , , , , , ,,,,,
-p-80°,51,9%,0%,6%,13%,60,62,-75,-75,-120 to -50,10,12,,,,,
-p80°,26,4%,0%,4%,6%,61,62,78,80,50 to 120,13,10,,,,,
-t-160°,31,5%,5%,14%,1%,-178,-177,-163,-165,150 to -120,12,20,,,,,
-t-80°,64,11%,17%,9%,9%,-173,-177,-81,-80,-120 to -50,10,22,,,,,
-t60°,94,16%,24%,17%,12%,-178,-177,62,60,50 to 120,13,19,,,,,
-m-70°,174,29%,26%,30%,30%,-60,-65,-69,-70,-120 to -30,11,23,,,,,
-m170°,44,7%,9%,3%,9%,-63,-65,165,165,120 to -160,10,16,,,,,
-m80°,78,13%,14%,10%,14%,-66,-65,83,80,50 to 120,11,18,,,,,
- , ,94%,94%,92%,95%, , , , , , , ,,,,,
- ,562/598, ,124,143,295, , , , , , , ,,,,,
-Tryptophan, , , , , , , , , , , , ,,,,,
-p-90°,67,11%,2%,13%,14%,58,62,-87,-90,-130 to -60,12,10,,,,,
-p90°,34,6%,1%,9%,6%,60,62,92,90,60 to 130,12,8,,,,,
-t-105°,100,16%,27%,10%,14%,178,-177,-105,-105,-130 to -60,16,14,,,,,
-t90°,109,18%,28%,14%,15%,-178,-177,88,90,0 to 100,10,11,,,,,
-m-90°,31,5%,0%,7%,7%,-70,-65,-87,-90,-130 to -60,9,12,,,,,
-m0°,48,8%,15%,2%,8%,-66,-65,-4,-5,-40 to 20,9,20,,,,,
-m95°,195,32%,22%,43%,29%,-69,-65,95,95,60 to 130,11,19,,,,,
- , ,94%,95%,98%,92%, , , , , , , ,,,,,
- ,584/618, ,140,175,269, , , , , , , ,,,,,
-Tyrosine, , , , , , , , , , , , ,,,,,
-p90°,182,13%,1%,21%,12%,63,62,89,90,"60 to 90 -90 to -60",13,13,,,,,
-t80°,486,34%,55%,25%,30%,176,-177,77,80,"20 to 90 -90 to -75",11,14,,,,,
-m-85°,618,43%,26%,50%,45%,-65,-65,-87,-85,"50 to 90 -90 to -50",11,21,,,,,
-m-30°,124,9%,15%,4%,9%,-64,-65,-42,-30,"-50 to 0 0 to 50",11,18,,,,,
- , ,98%,97%,99%,97%, , , , , , , ,,,,,
- ,1410/1443, ,290,468,652, , , , ,"(for Tyr, Phe 90° = -90°)",, ,,,,,
-Phenylalanine, , , , , , , , , , , , ,,,,,
-p90°,202,13%,1%,24%,11%,59,62,88,90,"60 to 90 -90 to -60",11,11,,,,,
-t80°,522,33%,57%,18%,29%,177,-177,80,80,"20 to 90 -90 to -75",13,17,,,,,
-m-85°,697,44%,29%,51%,47%,-64,-65,-83,-85,"50 to 90 -90 to -50",12,17,,,,,
-m-30°,149,9%,12%,5%,11%,-64,-65,-19,-30,"-50 to 0 0 to 50",9,20,,,,,
- , ,98%,97%,99%,98%, , , , , , , ,,,,,
- ,1570/1599, ,389,514,667, , , , , , , ,,,,,
-Proline, , , , , , , , , , , , ,,,,,
-Cγ endo,379,44%,23%,54%,43%,30,30, , ,15 to 60,7, ,,,,,
-Cγ exo,372,43%,68%,28%,44%,-29,-30, , ,-60 to -15,6, ,,,,,
-"cis Cγ endo",56,6%,0%,1%,7%,31,30, , ,15 to 60,5, ,,,,,
- , ,93%,91%,84%,94%, , , , , , , ,,,,,
- ,807/928, ,20,57,730,,,,,,,,,,,,
-Threonine, , , , , , , , , ,,,,,,,,
-p,1200,49%,25%,31%,65%,59,62, ,10,,,,,,,,
-t,169,7%,0%,13%,6%,-171,-175, ,6,,,,,,,,
-m,1062,43%,74%,55%,29%,-61,-65, ,7,,,,,,,,
- , ,99%,100%,99%,99%, , , ,,,,,,,,,
- ,2431/2447, ,395,672,1364, , , ,,,,,,,,,
-Valine, , , , , , , , ,,,,,,,,,
-p,169,6%,2%,8%,8%,63,63,=“177”f,8,,,,,,,,
-t,1931,73%,90%,72%,63%,175,175,Err:501,8,,,,,,,,
-m,526,20%,7%,20%,28%,-64,-60,Err:501,7,,,,,,,,
- , ,99%,100%,99%,99%, , , ,,,,,,,,,
- ,2626/2649, ,622,1080,924, , , ,,,,,,,,,
-Serine, , , , , , , , ,,,,,,,,,
-p,1201,48%,33%,36%,55%,64,62, ,10,,,,,,,,
-t,541,22%,22%,34%,18%,178,-177, ,11,,,,,,,,
-m,714,29%,44%,29%,25%,-65,-65, ,9,,,,,,,,
- , ,98%,98%,100%,98%, , , ,,,,,,,,,
- ,2456/2498, ,350,485,1621, , , ,,,,,,,,,
-Cysteine, , , , , , , , ,,,,,,,,,
-p,64,23%,5%,23%,34%,55,62, ,14,,,,,,,,
-t,74,26%,20%,45%,21%,-177,-177, ,10,,,,,,,,
-m,142,50%,75%,32%,43%,-65,-65, ,11,,,,,,,,
- , ,99%,100%,100%,98%, , , ,,,,,,,,,
- ,280/285, ,85,65,130,,,,,,,,,,,,
diff --git a/modelling/doc/sidechain_reconstruction.rst b/modelling/doc/sidechain_reconstruction.rst
index a7cf3dd8bfa2307bdf7e0a6c99f13392d1b0a986..c6e933f4a65043446a3ef51b7423ae3370509e3d 100644
--- a/modelling/doc/sidechain_reconstruction.rst
+++ b/modelling/doc/sidechain_reconstruction.rst
@@ -146,7 +146,7 @@ SidechainReconstructor Class
     :param use_bbdep_lib: If True, use default backbone dependent rot. library
                           (:meth:`LoadBBDepLib`), else use
                           backbone independent one
-                          (:meth:`Penultimate <LoadPenultimateLib>`).
+                          (:meth:`LoadLib`).
     :type use_bbdep_lib:  :class:`bool`
     :param rotamer_library: Custom rotamer library to be used.
     :type rotamer_library:  :class:`BBDepRotamerLib` / :class:`RotamerLib`
diff --git a/modelling/src/sidechain_env_listener.cc b/modelling/src/sidechain_env_listener.cc
index afda4ca112326e67d9962f936b50fda130b53434..74eb4c58226b3db4f1350db728363b369e316b51 100644
--- a/modelling/src/sidechain_env_listener.cc
+++ b/modelling/src/sidechain_env_listener.cc
@@ -14,11 +14,11 @@ SidechainEnvListener::SidechainEnvListener(bool use_frm, bool use_bbdep_lib,
                                            , env_(20.0), env_data_(NULL) {
   // check
   if (use_frm_ && !use_bbdep_lib_) {
-    throw promod3::Error("Cannot use PenultimateLib with FRMRotamers!");
+    throw promod3::Error("Cannot use non backbone dependent lib with FRMRotamers!");
   }
   // setup library
   if (use_bbdep_lib_) bbdep_library_ = sidechain::LoadBBDepLib();
-  else library_ = sidechain::LoadPenultimateLib();
+  else library_ = sidechain::LoadLib();
 
 }
 
diff --git a/modelling/tests/test_sidechain_reconstruction.py b/modelling/tests/test_sidechain_reconstruction.py
index c97a695551cf5284cefaa99daaf1a3d152d2f5f6..8daf328aa0594275dd407f8bf012d29e3ff7b5a6 100644
--- a/modelling/tests/test_sidechain_reconstruction.py
+++ b/modelling/tests/test_sidechain_reconstruction.py
@@ -9,7 +9,7 @@ class SidechainTests(unittest.TestCase):
     def setUpClass(cls):
         '''Load libs here for all tests.'''
         cls.bbdep_rotamer_library = sidechain.LoadBBDepLib() # DEFAULT
-        cls.rotamer_library = sidechain.LoadPenultimateLib()
+        cls.rotamer_library = sidechain.LoadLib()
 
     #######################################################################
     # HELPERs
diff --git a/sidechain/data/CMakeLists.txt b/sidechain/data/CMakeLists.txt
index 78adbacf839e7d899dc0ebca4aa9041a7c6c9f6a..c8224cba31cbdd8fd99abe5e3696f8aae0c4cb72 100644
--- a/sidechain/data/CMakeLists.txt
+++ b/sidechain/data/CMakeLists.txt
@@ -1,5 +1,5 @@
 # convert files
-convert_module_data(MODULE sidechain FILE PenultimateLib.dat
+convert_module_data(MODULE sidechain FILE lib.dat
                     SCRIPT convert_lib.py ARGS RotamerLib)
 convert_module_data(MODULE sidechain FILE bb_dep_lib.dat
                     SCRIPT convert_lib.py ARGS BBDepRotamerLib)
diff --git a/sidechain/data/portable_PenultimateLib.dat b/sidechain/data/portable_PenultimateLib.dat
deleted file mode 100644
index 67f192bc441a000d7d004990dc05c02f1211e959..0000000000000000000000000000000000000000
Binary files a/sidechain/data/portable_PenultimateLib.dat and /dev/null differ
diff --git a/sidechain/data/portable_lib.dat b/sidechain/data/portable_lib.dat
new file mode 100644
index 0000000000000000000000000000000000000000..38bf7f375c233b919fcb606507f26bb63dca4da1
Binary files /dev/null and b/sidechain/data/portable_lib.dat differ
diff --git a/sidechain/doc/loading.rst b/sidechain/doc/loading.rst
index dfd29f3c67b40aa857302959ea7d0fe97cbb9d9f..a321ad955976448b86af0e0b63d6a47ac0ce5eb7 100644
--- a/sidechain/doc/loading.rst
+++ b/sidechain/doc/loading.rst
@@ -10,9 +10,8 @@ You can request a licence `here <http://dunbrack.fccc.edu/bbdep2010/>`_
 and generate such a library as described in 
 extras/data_generation/rotamer_library/README. Alternatively, ProMod3
 provides its own backbone dependent library that can be loaded with
-:meth:`LoadBBDepLib`. Also the backbone independent Penultimate library 
-is directly provided in binary format and can be loaded with 
-:meth:`LoadPenultimateLib`.
+:meth:`LoadBBDepLib`. Also a backbone independent library is available: 
+:meth:`LoadLib`.
 
 .. method:: LoadBBDepLib()
 
@@ -25,12 +24,12 @@ is directly provided in binary format and can be loaded with
   :rtype:               :class:`BBDepRotamerLib`
 
 
-.. method:: LoadPenultimateLib()
+.. method:: LoadLib()
 
-  Loads the backbone independent Penultimate library. The values for the dihedral
-  angles are directly extracted from the publication without considering the
-  probabilities specific for helices/sheets. You can find details on what 
-  information is exactly stored in extras/data_generation/rotamer_library/README.
+  A backbone independent rotamer library shipped with ProMod3. You can find
+  details on how it is created in extras/data_generation/rotamer_library/README.
+  All scripts to build it are in the same directory as the README file and
+  build the basis for custom versions.
 
   :returns:             The requested library
   :rtype:               :class:`RotamerLib`
diff --git a/sidechain/pymod/export_sidechain_object_loader.cc b/sidechain/pymod/export_sidechain_object_loader.cc
index 6f4756acbb2858125627277c3ffffaeba40e57dd..30838988030d7697d55467f8123c0b6dbccc6603 100644
--- a/sidechain/pymod/export_sidechain_object_loader.cc
+++ b/sidechain/pymod/export_sidechain_object_loader.cc
@@ -7,5 +7,5 @@ using namespace boost::python;
 
 void export_SidechainObjectLoader(){
   def("LoadBBDepLib", &LoadBBDepLib);
-  def("LoadPenultimateLib", &LoadPenultimateLib);
+  def("LoadLib", &LoadLib);
 }
\ No newline at end of file
diff --git a/sidechain/src/sidechain_object_loader.cc b/sidechain/src/sidechain_object_loader.cc
index 81e96f77c2897c5c053f3a2ff91c40fb7fefa0a9..e814cd05af89b7e21357e8881167b4546179ab61 100644
--- a/sidechain/src/sidechain_object_loader.cc
+++ b/sidechain/src/sidechain_object_loader.cc
@@ -12,10 +12,10 @@ BBDepRotamerLibPtr LoadBBDepLib(){
   return p;  
 }
 
-RotamerLibPtr LoadPenultimateLib(){
+RotamerLibPtr LoadLib(){
   core::ScopedTimerPtr prof = core::StaticRuntimeProfiler::StartScoped(
-                                "sidechain::LoadPenultimateLib", 2);
-  String path = GetProMod3BinaryPath("sidechain_data", "PenultimateLib.dat");
+                                "sidechain::LoadLib", 2);
+  String path = GetProMod3BinaryPath("sidechain_data", "lib.dat");
   RotamerLibPtr p = RotamerLib::Load(path);
   return p;  
 }
diff --git a/sidechain/src/sidechain_object_loader.hh b/sidechain/src/sidechain_object_loader.hh
index bb40be7ee623d53cfcf82cbca9f16cfd819bcd19..85273a4c9e6eb14fcdbac7db1eb93f9347762ae1 100644
--- a/sidechain/src/sidechain_object_loader.hh
+++ b/sidechain/src/sidechain_object_loader.hh
@@ -7,7 +7,7 @@
 namespace promod3 { namespace sidechain{
 
 BBDepRotamerLibPtr LoadBBDepLib();
-RotamerLibPtr LoadPenultimateLib();
+RotamerLibPtr LoadLib();
 
 }} //ns
 #endif
diff --git a/sidechain/tests/test_rotamers.cc b/sidechain/tests/test_rotamers.cc
index 5273fb74a2c942474934a323efb9978342f28a64..cd1151bbd2e4edbac1d6873eb4f1ffc7b301a6c9 100644
--- a/sidechain/tests/test_rotamers.cc
+++ b/sidechain/tests/test_rotamers.cc
@@ -212,7 +212,7 @@ BOOST_AUTO_TEST_CASE(test_rotamer_group_consistency) {
   loop::AllAtomPositions all_atoms = GetAllAtomPos(res_list);
   // get all frames without hbonds
   BBDepRotamerLibPtr bbd_rot_lib = LoadBBDepLib();
-  RotamerLibPtr rot_lib = LoadPenultimateLib();
+  RotamerLibPtr rot_lib = LoadLib();
   CheckRotamerGroupConstruction(res_list, all_atoms, bbd_rot_lib,
                                 rot_lib);
 }
@@ -223,7 +223,7 @@ BOOST_AUTO_TEST_CASE(test_rotamer_apply_on_residue) {
   ost::mol::ResidueHandleList res_list = test_ent.GetResidueList();
   loop::AllAtomPositions all_atoms = GetAllAtomPos(res_list);
   // check all frames without hbonds
-  RotamerLibPtr rot_lib = LoadPenultimateLib();
+  RotamerLibPtr rot_lib = LoadLib();
   CheckRotamerApplyOnResidue(res_list, all_atoms, rot_lib);
 }