diff --git a/modules/mol/alg/pymod/export_accessibility.cc b/modules/mol/alg/pymod/export_accessibility.cc
index cecd75b551d9cfdecb6fc6b3b15b3cb7db928646..94d2bcabc9e99c7e0b508e30f97169c935f67639 100644
--- a/modules/mol/alg/pymod/export_accessibility.cc
+++ b/modules/mol/alg/pymod/export_accessibility.cc
@@ -31,13 +31,14 @@ Real WrapAccessibilityHandle(ost::mol::EntityHandle& ent,
                              bool include_hydrogens, 
                              bool include_hetatm,
                              bool include_water,
+                             bool oligo_mode,
                              const String& selection,
                              const String& asa_abs, 
                              const String& asa_rel,
                              const String& asa_atom) {
                                  
   return ost::mol::alg::Accessibility(ent, probe_radius, include_hydrogens, 
-                                      include_hetatm, include_water,
+                                      include_hetatm, include_water, oligo_mode,
                                       selection, asa_abs, asa_rel, asa_atom);
 }
 
@@ -46,12 +47,13 @@ Real WrapAccessibilityView(ost::mol::EntityView& ent,
                            bool include_hydrogens, 
                            bool include_hetatm,
                            bool include_water,
+                           bool oligo_mode,
                            const String& selection,
                            const String& asa_abs, const String& asa_rel,
                            const String& asa_atom) {
 
   return ost::mol::alg::Accessibility(ent, probe_radius, include_hydrogens, 
-                                      include_hetatm, include_water, 
+                                      include_hetatm, include_water, oligo_mode,
                                       selection, asa_abs, asa_rel, asa_atom);
 }
 
@@ -67,6 +69,7 @@ void export_accessibility() {
                                                    arg("include_hydrogens")=false,
                                                    arg("include_hetatm")=false,
                                                    arg("include_water")=false,
+                                                   arg("oligo_mode")=false,
                                                    arg("selection")="",
                                                    arg("asa_abs")="asaAbs",
                                                    arg("asa_rel")="asaRel",
@@ -77,6 +80,7 @@ void export_accessibility() {
                                                  arg("include_hydrogens")=false,
                                                  arg("include_hetatm")=false,
                                                  arg("include_water")=false,
+                                                 arg("oligo_mode")=false,
                                                  arg("selection")="",
                                                  arg("asa_abs")="asaAbs",
                                                  arg("asa_rel")="asaRel",
diff --git a/modules/mol/alg/src/accessibility.cc b/modules/mol/alg/src/accessibility.cc
index 4d5e971eb48bad70465b650bee5a8838cfe68f94..d4505d7ef9c1d4f1d40e2b1a62fddbb86d4aecf1 100644
--- a/modules/mol/alg/src/accessibility.cc
+++ b/modules/mol/alg/src/accessibility.cc
@@ -2,8 +2,10 @@
 
 #include <vector>
 #include <map>
+#include <set>
 #include <algorithm>
 #include <cmath>
+#include <ost/mol/chain_view.hh>
 #include <ost/mol/residue_view.hh>
 #include <ost/mol/atom_view.hh>
 
@@ -56,22 +58,15 @@ struct CubeGrid {
     cubes[cube_idx]->AddIndex(idx);
   }
 
-  void GetCubes(Real x, Real y, Real z,
-                std::vector<Cube*>& neighbouring_cubes,
-                Cube*& central_cube) {
+  void GetNeighbouringCubes(int cube_idx,
+                            std::vector<Cube*>& neighbouring_cubes) const {
 
-    int x_cube = (x - x_min) / cube_edge_length;
-    int y_cube = (y - y_min) / cube_edge_length;
-    int z_cube = (z - z_min) / cube_edge_length;
-
-    // set the central cube... we throw an error if this cube doesn't exist!
-    int cube_idx = x_cube * y_cubes * z_cubes + y_cube * z_cubes + z_cube;
-
-    if(cubes[cube_idx] == NULL){
-        throw ost::Error("This should not happen!");
-    }
-
-    central_cube = cubes[cube_idx];
+    int temp = cube_idx;
+    int x_cube = temp / (y_cubes * z_cubes);
+    temp -= x_cube * y_cubes * z_cubes;
+    int y_cube = temp / z_cubes;
+    temp -= y_cube * z_cubes;
+    int z_cube =  temp;
 
     // let's try all neighbours... only add if they actually exist!
     int x_min = std::max(x_cube - 1, 0);
@@ -97,6 +92,12 @@ struct CubeGrid {
     }
   }
 
+  int GetNumCubes() const { return x_cubes*y_cubes*z_cubes; }
+
+  bool IsInitialized(int cube_idx) const { return cubes[cube_idx] != NULL; }
+
+  Cube* GetCube(int cube_idx) const { return cubes[cube_idx]; }
+
   Real cube_edge_length;
   int x_cubes;
   int y_cubes;
@@ -107,15 +108,87 @@ struct CubeGrid {
   Cube** cubes;
 };
 
+// this struct might occur a bit stupid. The only thing it does is to keep track
+// of occupied cubes with the exactly Lookup scheme than the CubeGrid. 
+// It does not store anything else.
+struct CubeOccupationGrid{
+
+  CubeOccupationGrid(const CubeGrid& cube_grid): 
+                     cube_edge_length(cube_grid.cube_edge_length),
+                     x_cubes(cube_grid.x_cubes),
+                     y_cubes(cube_grid.y_cubes),
+                     z_cubes(cube_grid.z_cubes),
+                     x_min(cube_grid.x_min),
+                     y_min(cube_grid.y_min),
+                     z_min(cube_grid.z_min) {
+    int num_cubes = x_cubes * y_cubes * z_cubes;
+    occupied_cubes = new bool[num_cubes];
+    memset(occupied_cubes, 0, num_cubes * sizeof(bool));
+  }
+
+  ~CubeOccupationGrid() { delete [] occupied_cubes; }
+
+  void Occupy(Real x_pos, Real y_pos, Real z_pos) {
+    int x_cube = (x_pos - x_min) / cube_edge_length;
+    int y_cube = (y_pos - y_min) / cube_edge_length;
+    int z_cube = (z_pos - z_min) / cube_edge_length;
+    int cube_idx = x_cube * y_cubes * z_cubes + y_cube * z_cubes + z_cube;
+    occupied_cubes[cube_idx] = true;
+  }
+
+  bool IsOccupied(int cube_idx) {
+    return occupied_cubes[cube_idx];
+  }
+
+  bool HasOccupiedNeighbour(int cube_idx) {
+    int temp = cube_idx;
+    int x_cube = temp / (y_cubes * z_cubes);
+    temp -= x_cube * y_cubes * z_cubes;
+    int y_cube = temp / z_cubes;
+    temp -= y_cube * z_cubes;
+    int z_cube =  temp;
+
+    // let's try all neighbours... only add if they actually exist!
+    int x_min = std::max(x_cube - 1, 0);
+    int x_max = std::min(x_cube + 1, x_cubes - 1);
+    int y_min = std::max(y_cube - 1, 0);
+    int y_max = std::min(y_cube + 1, y_cubes - 1);
+    int z_min = std::max(z_cube - 1, 0);
+    int z_max = std::min(z_cube + 1, z_cubes - 1);
+   
+    for(int i = x_min; i <= x_max; ++i) {
+      for(int j = y_min; j <= y_max; ++j) {
+        for(int k = z_min; k <= z_max; ++k){
+          if(!(i == x_cube && j == y_cube && k == z_cube)){
+            // its not the central cube, so lets add it if initialized
+            cube_idx = i * y_cubes * z_cubes + j * z_cubes + k;
+            if(occupied_cubes[cube_idx]) return true; 
+          }
+        }
+      }
+    }
+    return false;
+  }
+
+  Real cube_edge_length;
+  int x_cubes;
+  int y_cubes;
+  int z_cubes;
+  Real x_min;
+  Real y_min;
+  Real z_min;
+  bool* occupied_cubes;
+};
+
 
 Real GetAtomAccessibility(Real x_pos, Real y_pos, Real z_pos,
-                           Real radius,
-                           const std::vector<Real>& dx, 
-                           const std::vector<Real>& dy, 
-                           const std::vector<Real>& d, 
-                           const std::vector<Real>& dsqr, 
-                           const std::vector<Real>& z, 
-                           const std::vector<Real>& radii) {
+                          Real radius,
+                          const std::vector<Real>& dx, 
+                          const std::vector<Real>& dy, 
+                          const std::vector<Real>& d, 
+                          const std::vector<Real>& dsqr, 
+                          const std::vector<Real>& z, 
+                          const std::vector<Real>& radii) {
 
   int num_close_atoms = dx.size();
 
@@ -242,59 +315,31 @@ Real GetAtomAccessibility(Real x_pos, Real y_pos, Real z_pos,
   return area*radius;
 }
 
-void CalculateASA(std::vector<Real>& x, std::vector<Real>& y, 
-                  std::vector<Real>& z, std::vector<Real>& radii, 
-                  Real probe_radius, std::vector<Real>& asa) {
 
-  int num_atoms = x.size();
-  asa.resize(num_atoms);
-
-  std::vector<Real> full_radii;
-  full_radii.resize(num_atoms);
-  Real x_min = x[0];
-  Real x_max = x[0];
-  Real y_min = y[0];
-  Real y_max = y[0];
-  Real z_min = z[0];
-  Real z_max = z[0];
-  Real r_max = radii[0] + probe_radius;
-  full_radii[0] = r_max;
-
-  for(int i = 1; i < num_atoms; ++i){
-    full_radii[i] = radii[i] + probe_radius;
-    x_min = std::min(x_min, x[i]);
-    x_max = std::max(x_max, x[i]);
-    y_min = std::min(y_min, y[i]);
-    y_max = std::max(y_max, y[i]);
-    z_min = std::min(z_min, z[i]);
-    z_max = std::max(z_max, z[i]);
-    r_max = std::max(r_max, full_radii[i]);
-  }
-  
-  Real x_range = x_max - x_min;
-  Real y_range = y_max - y_min;
-  Real z_range = z_max - z_min;
-  Real cube_edge_length = 2 * (r_max);
-  int x_cubes = std::ceil(x_range / cube_edge_length);
-  int y_cubes = std::ceil(y_range / cube_edge_length);
-  int z_cubes = std::ceil(z_range / cube_edge_length);
-
-  CubeGrid cube_grid(cube_edge_length, x_cubes, y_cubes, z_cubes,
-                     x_min, y_min, z_min);
-
-  for(int i = 0; i < num_atoms; ++i) {
-    cube_grid.AddIndex(x[i], y[i], z[i], i);
-  }
+void SolveCube(const CubeGrid& cube_grid, int cube_idx,
+               const std::vector<Real>& x, const std::vector<Real>& y, 
+               const std::vector<Real>& z, const std::vector<Real>& radii, 
+               std::vector<Real>& asa) {
 
   //prepare some stuff
   std::vector<Real> close_atom_dx, close_atom_dy, close_atom_d;
   std::vector<Real> close_atom_dsqr, close_atom_z, close_atom_radii;
+
+  close_atom_dx.reserve(200);
+  close_atom_dy.reserve(200);
+  close_atom_d.reserve(200);
+  close_atom_dsqr.reserve(200);
+  close_atom_z.reserve(200);
+  close_atom_radii.reserve(200);
+
+  Cube* central_cube = cube_grid.GetCube(cube_idx);;
   std::vector<Cube*> neighbouring_cubes;
-  Cube* central_cube;
+  cube_grid.GetNeighbouringCubes(cube_idx, neighbouring_cubes);
+  const std::vector<int>& cube_atoms = central_cube->GetIndices();
 
-  // iterate over every atom
-  for(int atom_idx = 0; atom_idx < num_atoms; ++atom_idx) {
+  for(uint idx = 0; idx < cube_atoms.size(); ++idx) {
 
+    int atom_idx = cube_atoms[idx];
     close_atom_dx.clear();
     close_atom_dy.clear();
     close_atom_d.clear();
@@ -305,10 +350,7 @@ void CalculateASA(std::vector<Real>& x, std::vector<Real>& y,
     Real current_x = x[atom_idx];
     Real current_y = y[atom_idx];
     Real current_z = z[atom_idx];
-    Real current_radius = full_radii[atom_idx];
-
-    cube_grid.GetCubes(current_x, current_y, current_z, 
-                       neighbouring_cubes, central_cube);
+    Real current_radius = radii[atom_idx];
 
     // gather the stuff from all neighbouring cubes
     for(std::vector<Cube*>::iterator cube_it = neighbouring_cubes.begin();
@@ -324,13 +366,13 @@ void CalculateASA(std::vector<Real>& x, std::vector<Real>& y,
         Real dy = current_y - y[close_atom_idx]; 
         Real sqr_d = dx*dx + dy*dy;
         Real d = std::sqrt(sqr_d);
-
+  
         close_atom_dx.push_back(dx);
         close_atom_dy.push_back(dy);
         close_atom_dsqr.push_back(sqr_d);
         close_atom_d.push_back(d);
         close_atom_z.push_back(z[close_atom_idx]);
-        close_atom_radii.push_back(full_radii[close_atom_idx]);
+        close_atom_radii.push_back(radii[close_atom_idx]);
       }
     }
 
@@ -352,10 +394,10 @@ void CalculateASA(std::vector<Real>& x, std::vector<Real>& y,
         close_atom_dsqr.push_back(sqr_d);
         close_atom_d.push_back(d);
         close_atom_z.push_back(z[close_atom_idx]);
-        close_atom_radii.push_back(full_radii[close_atom_idx]);
+        close_atom_radii.push_back(radii[close_atom_idx]);
       }
     }
-
+    
     asa[atom_idx] = GetAtomAccessibility(current_x, current_y, current_z, 
                                          current_radius, 
                                          close_atom_dx, close_atom_dy, 
@@ -365,11 +407,268 @@ void CalculateASA(std::vector<Real>& x, std::vector<Real>& y,
 }
 
 
-} //ns
+void AddProbeToRadii(const std::vector<Real>& radii,
+                     Real probe_radius,
+                     std::vector<Real>& full_radii) {
+  int size = radii.size();
+  full_radii.resize(size);
+  for(int i = 0; i < size; ++i) {
+    full_radii[i] = radii[i] + probe_radius;
+  }
+}
 
 
+CubeGrid SetupCubeGrid(const std::vector<Real>& x,
+                       const std::vector<Real>& y,
+                       const std::vector<Real>& z,
+                       const std::vector<Real>& full_radii) {
 
+  Real x_min = x[0];
+  Real x_max = x[0];
+  Real y_min = y[0];
+  Real y_max = y[0];
+  Real z_min = z[0];
+  Real z_max = z[0];
+  Real r_max = full_radii[0];
 
+  for(uint i = 1; i < x.size(); ++i){
+    x_min = std::min(x_min, x[i]);
+    x_max = std::max(x_max, x[i]);
+    y_min = std::min(y_min, y[i]);
+    y_max = std::max(y_max, y[i]);
+    z_min = std::min(z_min, z[i]);
+    z_max = std::max(z_max, z[i]);
+    r_max = std::max(r_max, full_radii[i]);
+  }
+  
+  Real x_range = x_max - x_min;
+  Real y_range = y_max - y_min;
+  Real z_range = z_max - z_min;
+  Real cube_edge_length = 2 * (r_max);
+  int x_cubes = std::ceil(x_range / cube_edge_length);
+  int y_cubes = std::ceil(y_range / cube_edge_length);
+  int z_cubes = std::ceil(z_range / cube_edge_length);
+
+  CubeGrid cube_grid(cube_edge_length, x_cubes, y_cubes, z_cubes,
+                     x_min, y_min, z_min);
+
+  return cube_grid;
+}
+
+
+void CalculateASAOligo(std::vector<Real>& x, std::vector<Real>& y, 
+                       std::vector<Real>& z, std::vector<Real>& radii,
+                       std::vector<int> chain_indices, 
+                       Real probe_radius, std::vector<Real>& asa,
+                       std::vector<Real>& asa_single_chain) {
+
+  int num_atoms = x.size();
+  asa.resize(num_atoms);
+
+  std::vector<Real> full_radii;
+  AddProbeToRadii(radii, probe_radius, full_radii);
+
+  CubeGrid cube_grid = SetupCubeGrid(x,y,z,full_radii);
+
+  for(int i = 0; i < num_atoms; ++i) {
+    cube_grid.AddIndex(x[i], y[i], z[i], i);
+  }
+
+  int num_cubes = cube_grid.GetNumCubes();
+  for(int cube_idx = 0; cube_idx < num_cubes; ++cube_idx) {
+
+    if(cube_grid.IsInitialized(cube_idx)) {
+      // there is at least one atom!
+      SolveCube(cube_grid, cube_idx, x, y, z, full_radii, asa);
+    }
+  }
+
+  // let's start with the single chain stuff
+  // the asa are assumed to be exactly the same for the majority of the atoms
+  asa_single_chain = asa;
+
+  // let's find all unique chains
+  std::set<int> unique_indices;
+  for(std::vector<int>::const_iterator it = chain_indices.begin(); 
+      it != chain_indices.end(); ++it) {
+    unique_indices.insert(*it);
+  }
+
+  for(std::set<int>::iterator set_it = unique_indices.begin(); 
+      set_it != unique_indices.end(); ++set_it) {
+
+    int current_chain_idx = *set_it;
+
+    // let's generate a cube grid with exactly the same size as before 
+    // but only fill it with stuff from the current chain
+    CubeGrid single_chain_cube_grid(cube_grid.cube_edge_length, 
+                                    cube_grid.x_cubes, 
+                                    cube_grid.y_cubes, 
+                                    cube_grid.z_cubes,
+                                    cube_grid.x_min, 
+                                    cube_grid.y_min, 
+                                    cube_grid.z_min);
+
+    // in here we store the cube grids that are occupied by the atoms NOT
+    // belonging to the current chain
+    CubeOccupationGrid occupation_grid(single_chain_cube_grid);
+
+    for(int i = 0; i < num_atoms; ++i) {
+      if(current_chain_idx == chain_indices[i]) {
+        single_chain_cube_grid.AddIndex(x[i], y[i], z[i], i);
+      }
+      else {
+        occupation_grid.Occupy(x[i], y[i], z[i]);
+      }
+    }
+
+    for(int cube_idx = 0; cube_idx < single_chain_cube_grid.GetNumCubes(); 
+        ++cube_idx) {
+
+      if(single_chain_cube_grid.IsInitialized(cube_idx) && 
+         (occupation_grid.IsOccupied(cube_idx) ||
+          occupation_grid.HasOccupiedNeighbour(cube_idx))) {
+        // there is at least one atom in the cube AND the environment has 
+        // changes compared to the previous asa calculation
+        SolveCube(single_chain_cube_grid, cube_idx, x, y, z, full_radii, 
+                  asa_single_chain);
+      }
+    }
+  }
+}
+
+
+void CalculateASA(const std::vector<Real>& x, 
+                  const std::vector<Real>& y, 
+                  const std::vector<Real>& z, 
+                  const std::vector<Real>& radii, 
+                  Real probe_radius, 
+                  std::vector<Real>& asa) {
+
+  int num_atoms = x.size();
+  asa.resize(num_atoms);
+
+  std::vector<Real> full_radii;
+  AddProbeToRadii(radii, probe_radius, full_radii);
+
+  CubeGrid cube_grid = SetupCubeGrid(x, y, z, full_radii);
+
+  for(int i = 0; i < num_atoms; ++i) {
+    cube_grid.AddIndex(x[i], y[i], z[i], i);
+  }
+
+  int num_cubes = cube_grid.GetNumCubes();
+  for(int cube_idx = 0; cube_idx < num_cubes; ++cube_idx) {
+
+    if(cube_grid.IsInitialized(cube_idx)) {
+      // there is at least one atom!
+      SolveCube(cube_grid, cube_idx, x, y, z, full_radii, asa);
+    }
+  }
+}
+
+
+void ASAParamFromAtomList(const ost::mol::AtomViewList& atom_list,
+                          std::vector<Real>& x_pos,
+                          std::vector<Real>& y_pos,
+                          std::vector<Real>& z_pos,
+                          std::vector<Real>& radii) {
+
+  const ost::mol::alg::NACCESSParam& param = 
+  ost::mol::alg::NACCESSParam::GetInstance();
+  String rname, aname, ele;
+
+  for(ost::mol::AtomViewList::const_iterator at_it = atom_list.begin();
+      at_it != atom_list.end(); ++at_it) {
+    rname = at_it->GetResidue().GetName();
+    aname = at_it->GetName();
+    ele = at_it->GetElement();
+    geom::Vec3 at_pos = at_it->GetPos();
+    x_pos.push_back(at_pos[0]);
+    y_pos.push_back(at_pos[1]);
+    z_pos.push_back(at_pos[2]);
+    radii.push_back(param.GetVdWRadius(rname, aname, ele));
+  } 
+}  
+
+
+void ASAParamFromAtomList(const ost::mol::AtomViewList& atom_list,
+                          std::vector<Real>& x_pos,
+                          std::vector<Real>& y_pos,
+                          std::vector<Real>& z_pos,
+                          std::vector<Real>& radii,
+                          std::vector<int>& chain_indices) {
+
+  const ost::mol::alg::NACCESSParam& param = 
+  ost::mol::alg::NACCESSParam::GetInstance();
+  String rname, aname, ele;
+
+  // since no function to directly access a chain index, we have to do
+  // that with an ugly hack... thats stupid and should be replaced...
+  ost::mol::ChainViewList chain_list = 
+  atom_list[0].GetEntity().GetChainList();
+  ost::mol::ChainViewList::iterator chain_list_begin = chain_list.begin();
+  ost::mol::ChainViewList::iterator chain_list_end = chain_list.end();
+
+  for(ost::mol::AtomViewList::const_iterator at_it = atom_list.begin();
+      at_it != atom_list.end(); ++at_it) {
+    rname = at_it->GetResidue().GetName();
+    aname = at_it->GetName();
+    ele = at_it->GetElement();
+    geom::Vec3 at_pos = at_it->GetPos();
+    x_pos.push_back(at_pos[0]);
+    y_pos.push_back(at_pos[1]);
+    z_pos.push_back(at_pos[2]);
+    radii.push_back(param.GetVdWRadius(rname, aname, ele));
+    ost::mol::ChainView chain = at_it->GetResidue().GetChain();
+    ost::mol::ChainViewList::iterator found_it = 
+    std::find(chain_list_begin, chain_list_end, chain);
+    chain_indices.push_back(static_cast<int>(found_it - chain_list_begin));
+  } 
+} 
+
+
+Real SetAccessibilityProps(ost::mol::EntityView& ent,
+                           ost::mol::AtomViewList& atom_list,
+                           const std::vector<Real>& asa,
+                           const String& asa_atom,
+                           const String& asa_abs,
+                           const String& asa_rel){
+
+  // assign absolute accessibilities
+  Real summed_asa = 0.0;
+  for(uint idx = 0; idx < asa.size(); ++idx) {
+    Real val = asa[idx];
+    atom_list[idx].SetFloatProp(asa_atom, val);
+    ost::mol::ResidueView res = atom_list[idx].GetResidue();
+    Real current_asa = res.GetFloatProp(asa_abs, 0.0);
+    res.SetFloatProp(asa_abs, current_asa + val);
+    summed_asa += val;
+  }
+
+  // go over residue and assign relative accessibilities
+  String rname;
+  ost::mol::ResidueViewList res_list = ent.GetResidueList();
+  for(uint idx = 0; idx < res_list.size(); ++idx) {
+    rname = res_list[idx].GetName();
+    Real tot_acc = 
+    ost::mol::alg::NACCESSParam::GetInstance().GetResidueAccessibility(rname);
+    if(tot_acc == 0.0) {
+      // no accessibility found... 
+      res_list[idx].SetFloatProp(asa_rel, 0.0);
+    }
+    else {
+      // the fraction gets multiplied by 100 (Thats how NACCESS does it...)
+      Real val = res_list[idx].GetFloatProp(asa_abs, 0.0) / tot_acc * 100.0;
+      res_list[idx].SetFloatProp(asa_rel, val);
+    }
+  }
+
+  return summed_asa;
+}
+
+
+} //ns
 
 
 
@@ -628,6 +927,7 @@ NACCESSParam::NACCESSParam() {
   accessibilities_["TYR"] = 212.76;
 }
 
+
 Real NACCESSParam::GuessRadius(const String& ele) const{
   if(ele == "C") return 1.80;
   if(ele == "N") return 1.60;
@@ -644,6 +944,7 @@ Real NACCESSParam::GuessRadius(const String& ele) const{
   return 1.80;
 }
 
+
 Real NACCESSParam::GetVdWRadius(const String& rname, const String& aname, 
                                 const String& ele) const{
   std::map<String, std::map<String, Real> >::const_iterator res_map_it =
@@ -656,6 +957,7 @@ Real NACCESSParam::GetVdWRadius(const String& rname, const String& aname,
   return GuessRadius(ele);
 }
 
+
 Real NACCESSParam::GetResidueAccessibility(const String& rname) const{
   std::map<String, Real>::const_iterator it = accessibilities_.find(rname);
   if(it != accessibilities_.end()) return it->second;
@@ -666,6 +968,7 @@ Real NACCESSParam::GetResidueAccessibility(const String& rname) const{
 Real Accessibility(ost::mol::EntityView& ent, 
                    Real probe_radius, bool include_hydrogens,
                    bool include_hetatm, bool include_water,
+                   bool oligo_mode,
                    const String& selection, 
                    const String& asa_abs, 
                    const String& asa_rel,
@@ -720,68 +1023,57 @@ Real Accessibility(ost::mol::EntityView& ent,
   radii.reserve(selected_ent.GetAtomCount());
 
   // extract data from ent
-  String rname, aname, ele;
+  ost::mol::AtomViewList atom_list = selected_ent.GetAtomList();
 
-  const NACCESSParam& param = NACCESSParam::GetInstance();
+  if(atom_list.size() == 0) return 0.0;
 
-  ost::mol::AtomViewList atom_list = selected_ent.GetAtomList();
-  for(ost::mol::AtomViewList::const_iterator at_it = atom_list.begin();
-      at_it != atom_list.end(); ++at_it) {
-    rname = at_it->GetResidue().GetName();
-    aname = at_it->GetName();
-    ele = at_it->GetElement();
-    geom::Vec3 at_pos = at_it->GetPos();
-    x_pos.push_back(at_pos[0]);
-    y_pos.push_back(at_pos[1]);
-    z_pos.push_back(at_pos[2]);
-    radii.push_back(param.GetVdWRadius(rname, aname, ele));
-  }  
+  if(oligo_mode) {
+    std::vector<int> chain_indices;
+    chain_indices.reserve(selected_ent.GetAtomCount());
 
-  // per atom accessibilities come in here
-  std::vector<Real> asa;
+    ASAParamFromAtomList(atom_list, x_pos, y_pos, z_pos, radii, chain_indices);
 
-  // do it! do it! do it!
-  CalculateASA(x_pos, y_pos, z_pos, radii, probe_radius, asa);
+    // do it! do it! do it!              
+    std::vector<Real> asa;
+    std::vector<Real> asa_single_chain;
+    CalculateASAOligo(x_pos, y_pos, z_pos, radii, chain_indices, 
+                      probe_radius, asa, asa_single_chain);
 
-  // assign 0.0 for per residue asaAbs
-  ost::mol::ResidueViewList res_list = selected_ent.GetResidueList();
-  for(uint res_idx = 0; res_idx < res_list.size(); ++res_idx) {
-    res_list[res_idx].SetFloatProp(asa_abs, 0.0);
-  }
+    Real summed_asa = SetAccessibilityProps(selected_ent, atom_list, asa, 
+                                            asa_atom, asa_abs, asa_rel);
 
-  // assign absolute accessibilities
-  Real summed_asa = 0.0;
-  for(uint idx = 0; idx < asa.size(); ++idx) {
-    Real val = asa[idx];
-    atom_list[idx].SetFloatProp(asa_atom, val);
-    ost::mol::ResidueView res = atom_list[idx].GetResidue();
-    Real current_asa = res.GetFloatProp(asa_abs);
-    res.SetFloatProp(asa_abs, current_asa + val);
-    summed_asa += val;
+    // in case of the single chain asa, the property names are
+    // moodified!!
+    String single_chain_asa_atom = asa_atom + "_single_chain";
+    String single_chain_asa_abs = asa_abs + "_single_chain";
+    String single_chain_asa_rel = asa_rel + "_single_chain";
+
+    SetAccessibilityProps(selected_ent, atom_list, asa_single_chain, 
+                          single_chain_asa_atom, 
+                          single_chain_asa_abs, 
+                          single_chain_asa_rel);
+
+    return summed_asa;
   }
+  else {
+    ASAParamFromAtomList(atom_list, x_pos, y_pos, z_pos, radii);
+    // do it! do it! do it!
+    std::vector<Real> asa;
+    CalculateASA(x_pos, y_pos, z_pos, radii, probe_radius, asa);
 
-  // go over residue and assign relative accessibilities
-  for(uint idx = 0; idx < res_list.size(); ++idx) {
-    rname = res_list[idx].GetName();
-    Real tot_acc = NACCESSParam::GetInstance().GetResidueAccessibility(rname);
-    if(tot_acc == 0.0) {
-      // no accessibility found... 
-      res_list[idx].SetFloatProp(asa_rel, 0.0);
-    }
-    else {
-      // the fraction gets multiplied by 100 (Thats how NACCESS does it...)
-      Real val = res_list[idx].GetFloatProp(asa_abs) / tot_acc * 100.0;
-      res_list[idx].SetFloatProp(asa_rel, val);
-    }
+    Real summed_asa = SetAccessibilityProps(selected_ent, atom_list, asa, 
+                                            asa_atom, asa_abs, asa_rel);
+
+    return summed_asa;
   }
 
-  return summed_asa;
 }
 
 
 Real Accessibility(ost::mol::EntityHandle& ent, 
                    Real probe_radius, bool include_hydrogens,
                    bool include_hetatm, bool include_water,
+                   bool oligo_mode,
                    const String& selection,
                    const String& asa_abs, 
                    const String& asa_rel,
@@ -789,7 +1081,7 @@ Real Accessibility(ost::mol::EntityHandle& ent,
 
   ost::mol::EntityView entity_view = ent.CreateFullView();
   return Accessibility(entity_view, probe_radius, include_hydrogens,
-                       include_hetatm, include_water,
+                       include_hetatm, include_water, oligo_mode,
                        selection, asa_abs, asa_rel, asa_atom);
 }
 
diff --git a/modules/mol/alg/src/accessibility.hh b/modules/mol/alg/src/accessibility.hh
index 35a2811e6c97bc45e578801d4ac7e7b6fc91b91b..e880ab5227c9a36e584e1ac0f5749dc2a8859c3d 100644
--- a/modules/mol/alg/src/accessibility.hh
+++ b/modules/mol/alg/src/accessibility.hh
@@ -57,6 +57,7 @@ Real Accessibility(ost::mol::EntityView& ent,
                    bool include_hydrogens = false,  
                    bool include_hetatm = false,
                    bool include_water = false,
+                   bool oligo_mode = false,
                    const String& selection = "",
                    const String& asa_abs = "asaAbs",
                    const String& asa_rel = "asaRel",
@@ -68,6 +69,7 @@ Real Accessibility(ost::mol::EntityHandle& ent,
                    bool include_hydrogens = false,
                    bool include_hetatm = false,
                    bool include_water = false,
+                   bool oligo_mode = false,
                    const String& selection = "",
                    const String& asa_abs = "asaAbs",
                    const String& asa_rel = "asaRel",