1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360
|
// ----------------------------------------------------
// $Maintainer: Marcel Schumann $
// $Authors: Slick-development Team, Marcel Schumann $
// ----------------------------------------------------
#include <BALL/SCORING/COMPONENTS/aromaticRingStacking.h>
using namespace std;
namespace BALL
{
const String AromaticRingStacking::Option::VERBOSITY
= "verbosity";
const String AromaticRingStacking::Option::F2F_PLANE_DISTANCE_LOWER
= "f2f_plane_distance_lower";
const String AromaticRingStacking::Option::F2F_PLANE_DISTANCE_UPPER
= "f2f_plane_distance_upper";
const String AromaticRingStacking::Option::F2F_LATERAL_DISPLACEMENT_LOWER
= "f2f_lateral_displacement_lower";
const String AromaticRingStacking::Option::F2F_LATERAL_DISPLACEMENT_UPPER
= "f2f_lateral_displacement_upper";
const String AromaticRingStacking::Option::F2E_CENTER_DISTANCE_LOWER
= "f2e_center_distance_lower";
const String AromaticRingStacking::Option::F2E_CENTER_DISTANCE_UPPER
= "f2e_center_distance_upper";
const String AromaticRingStacking::Option::SCORING_TOLERANCE
= "scoring_tolerance";
// Values from Angew. Chem. 115(11):1244-1287, 2003
const Size AromaticRingStacking::Default::VERBOSITY
= 0;
const float AromaticRingStacking::Default::F2F_PLANE_DISTANCE_LOWER
= 3.40f;
const float AromaticRingStacking::Default::F2F_PLANE_DISTANCE_UPPER
= 3.60f;
const float AromaticRingStacking::Default::F2F_LATERAL_DISPLACEMENT_LOWER
= 1.60f;
const float AromaticRingStacking::Default::F2F_LATERAL_DISPLACEMENT_UPPER
= 1.80f;
const float AromaticRingStacking::Default::F2E_CENTER_DISTANCE_LOWER
= 4.96f - 0.10f;
const float AromaticRingStacking::Default::F2E_CENTER_DISTANCE_UPPER
= 4.96f + 0.10f;
const float AromaticRingStacking::Default::SCORING_TOLERANCE
= 0.10f;
AromaticRingStacking::AromaticRingStacking()
{
// Set the name
setName("AromaticRingStacking");
valid_ = 0;
gridable_ = 0;
angle_tolerance_ = 5;
atom_pairwise_ = 0;
}
AromaticRingStacking::AromaticRingStacking(ScoringFunction& sf)
: ScoringComponent(sf)
{
// Set the name
setName("SLICK AromaticRingStacking");
valid_ = 0;
gridable_ = 0;
angle_tolerance_ = 5;
atom_pairwise_ = 0;
}
AromaticRingStacking::~AromaticRingStacking()
{
clear();
}
void AromaticRingStacking::clear()
{
for (Size i = 0; i < receptor_rings_.size(); i++)
{
delete receptor_rings_[i];
}
for (Size i = 0; i < ligand_rings_.size(); i++)
{
delete ligand_rings_[i];
}
ligand_rings_.clear();
receptor_rings_.clear();
possible_interactions_.clear();
}
bool AromaticRingStacking::setup(Options& options)
{
if (scoring_function_ == 0)
{
Log.error() << "AromaticRingStacking::setup(): "
<< "component not bound to scoring function." << std::endl;
return false;
}
clear();
// Set all paramters
options.setDefaultInteger(Option::VERBOSITY, Default::VERBOSITY);
options.setDefaultReal(Option::F2F_PLANE_DISTANCE_LOWER,
Default::F2F_PLANE_DISTANCE_LOWER);
options.setDefaultReal(Option::F2F_PLANE_DISTANCE_UPPER,
Default::F2F_PLANE_DISTANCE_UPPER);
options.setDefaultReal(Option::F2F_LATERAL_DISPLACEMENT_LOWER,
Default::F2F_LATERAL_DISPLACEMENT_LOWER);
options.setDefaultReal(Option::F2F_LATERAL_DISPLACEMENT_UPPER,
Default::F2F_LATERAL_DISPLACEMENT_UPPER);
options.setDefaultReal(Option::F2E_CENTER_DISTANCE_LOWER,
Default::F2E_CENTER_DISTANCE_LOWER);
options.setDefaultReal(Option::F2E_CENTER_DISTANCE_UPPER,
Default::F2E_CENTER_DISTANCE_UPPER);
options.setDefaultReal(Option::SCORING_TOLERANCE,
Default::SCORING_TOLERANCE);
f2f_plane_distance_lower_
= options.getReal(Option::F2F_PLANE_DISTANCE_LOWER);
f2f_plane_distance_upper_
= options.getReal(Option::F2F_PLANE_DISTANCE_UPPER);
f2f_lateral_displacemant_lower_
= options.getReal(Option::F2F_LATERAL_DISPLACEMENT_LOWER);
f2f_lateral_displacemant_upper_
= options.getReal(Option::F2F_LATERAL_DISPLACEMENT_UPPER);
f2e_center_distance_lower_
= options.getReal(Option::F2E_CENTER_DISTANCE_LOWER);
f2e_center_distance_upper_
= options.getReal(Option::F2E_CENTER_DISTANCE_UPPER);
scoring_tolerance_ = options.getReal(Option::SCORING_TOLERANCE);
// All ring-pairs with a distance larger than this value would result in a score of zero, so simple ignore those pairs!
distance_cutoff_ = max(max(f2f_plane_distance_upper_, f2f_lateral_displacemant_upper_), f2e_center_distance_upper_)+scoring_tolerance_;
/// Find aromatic rings in receptor
AtomContainer* receptor = scoring_function_->getReceptor();
// First, find the rings of the receptor (via SSSR)
std::vector< std::vector< Atom*> > SSSR_r;
Size rings_r = rp_.calculateSSSR(SSSR_r, *receptor);
// If there are no rings, we cannot compute anything.
if (rings_r == 0)
{
return true;
}
// Now look for aromatic rings
ap_.aromatize(SSSR_r, *receptor);
std::vector< std::vector< Atom* > >::iterator SSSR_it;
for (SSSR_it = SSSR_r.begin(); SSSR_it != SSSR_r.end(); ++SSSR_it)
{
std::vector< Atom* >::iterator ring_atom_it = SSSR_it->begin();
if ((*ring_atom_it)->hasProperty("IsAromatic"))
{
CHPI::AromaticRing* current_ring = new CHPI::AromaticRing(*SSSR_it);
receptor_rings_.push_back(current_ring);
//current_ring->dump();
}
}
cout<<"AromaticRingStacking::setup() found "<<receptor_rings_.size()<<" aromatic rings within the receptor"<<endl;
valid_ = 1;
setupLigand();
// remember the setup time in order to known later whether the receptor-structure was modified (translation of entire system or rotation of side-chains)
update_time_stamp_.stamp();
return true;
}
// This function needs to be called once for every new ligand
void AromaticRingStacking::setupLigand()
{
if (valid_ == 0)
{
Log.error() << "AromaticRingStacking::setupLigand() error: Component has not been set up properly!" << endl;
return;
}
if (receptor_rings_.size() == 0)
{
return;
}
AtomContainer* ligand = scoring_function_->getLigand();
vector< std::vector< Atom*> > SSSR_l;
Size rings_l = rp_.calculateSSSR(SSSR_l, *ligand);
// If there are no rings, we cannot compute anything.
if (rings_l == 0)
{
cout << "AromaticRingStacking::setupLigand() found no aromatic rings within the ligand" << endl;
return;
}
/// Find aromatic rings in ligand
for (Size i = 0; i < ligand_rings_.size(); i++)
{
delete ligand_rings_[i];
}
ligand_rings_.clear();
ap_.aromatize(SSSR_l, *ligand);
vector<vector<Atom*> >::iterator SSSR_it;
for (SSSR_it = SSSR_l.begin(); SSSR_it != SSSR_l.end(); ++SSSR_it)
{
std::vector< Atom* >::iterator ring_atom_it = SSSR_it->begin();
if ((*ring_atom_it)->hasProperty("IsAromatic"))
{
CHPI::AromaticRing* current_ring = new CHPI::AromaticRing(*SSSR_it);
ligand_rings_.push_back(current_ring);
}
}
if (ligand_rings_.size() == 0)
{
cout << "AromaticRingStacking::setupLigand() found no aromatic rings within the ligand" << endl;
return;
}
cout << "AromaticRingStacking::setupLigand() found " << ligand_rings_.size()<< " aromatic rings within the ligand" << endl;
AtomPairVector empty(0);
update(empty);
}
void AromaticRingStacking::update(const vector<std::pair<Atom*, Atom*> >& /*atom_pairs*/)
{
// ignore 'atom_pairs', since this component does not calculate a pair-wise score
/// Recalculate ring-centers and normal-vectors
if (update_time_stamp_.isOlderThan(scoring_function_->getReceptor()->getModificationTime()))
{
cout<<"Receptor has been translated or rotated; updating the aromatic ring centers and normal-vectors..."<<endl;
for (vector < CHPI::AromaticRing* > ::const_iterator r_it = receptor_rings_.begin(); r_it != receptor_rings_.end(); ++r_it)
{
(*r_it)->update();
}
update_time_stamp_.stamp();
}
for (vector < CHPI::AromaticRing* > ::const_iterator l_it = ligand_rings_.begin(); l_it != ligand_rings_.end(); ++l_it)
{
(*l_it)->update();
}
/// Build pairs of aromatic rings
possible_interactions_.clear();
vector<CHPI::AromaticRing*>::const_iterator r_it;
vector<CHPI::AromaticRing*>::const_iterator l_it;
for (r_it = receptor_rings_.begin(); r_it != receptor_rings_.end(); ++r_it)
{
for (l_it = ligand_rings_.begin(); l_it != ligand_rings_.end(); ++l_it)
{
if ((*r_it)->getCentre().getDistance((*l_it)->getCentre()) < distance_cutoff_)
{
possible_interactions_.push_back(std::pair<const CHPI::AromaticRing*, const CHPI::AromaticRing*>(*r_it, *l_it));
}
}
}
//if (possible_interactions_.size() != 0) cout<<"AromaticRingStacking::update() found "<<possible_interactions_.size()<<" possible ring interactions"<<endl;
}
double AromaticRingStacking::updateScore()
{
if (possible_interactions_.size() == 0)
{
return 0.0;
}
// Reset the energy value.
score_ = 0.0f;
float f2f_score = 0.0f;
float f2e_score = 0.0f;
Vector3 c_r;
Vector3 c_l;
Vector3 n_r;
Vector3 n_l;
float angle;
Vector3 distance;
// iterate over all ring pairs
std::vector< std::pair<const CHPI::AromaticRing*, const CHPI::AromaticRing*> >::const_iterator it = possible_interactions_.begin();
for (; it != possible_interactions_.end(); ++it)
{
n_r = it->first->getNormalVector();
n_l = it->second->getNormalVector();
c_r = it->first->getCentre();
c_l = it->second->getCentre();
angle = n_r.getAngle(n_l).toDegree();
distance = c_l - c_r;
// face to face
if ((fabs(angle) < angle_tolerance_)
|| (fabs(180.0f - angle) < angle_tolerance_))
{
// Calculate the distance of the planes
Vector3 plane_distance_vec = ((distance * n_r) * n_r);
float plane_distance = plane_distance_vec.getLength();
// Calculate projected distance of one ring centre to the other
// one
Vector3 lateral_displacement_vec = c_r + plane_distance_vec - c_l;
float lateral_displacement = lateral_displacement_vec.getLength();
f2f_score
+= base_function_->calculate(plane_distance,
f2f_plane_distance_lower_ + scoring_tolerance_,
f2f_plane_distance_lower_ - scoring_tolerance_)
* base_function_->calculate(plane_distance,
f2f_plane_distance_upper_ - scoring_tolerance_,
f2f_plane_distance_upper_ + scoring_tolerance_)
* base_function_->calculate(lateral_displacement,
f2f_lateral_displacemant_lower_ + scoring_tolerance_,
f2f_lateral_displacemant_lower_ - scoring_tolerance_)
* base_function_->calculate(lateral_displacement,
f2f_lateral_displacemant_upper_ - scoring_tolerance_,
f2f_lateral_displacemant_upper_ + scoring_tolerance_);
}
// face to edge
if ((fabs(90 - angle) < angle_tolerance_)
|| (fabs(270 -angle) < angle_tolerance_))
{
float d = distance.getLength();
f2e_score += base_function_->calculate(d,
f2e_center_distance_lower_ + scoring_tolerance_,
f2e_center_distance_lower_ - scoring_tolerance_)
* base_function_->calculate(d,
f2e_center_distance_upper_ - scoring_tolerance_,
f2e_center_distance_upper_ + scoring_tolerance_);
}
}
// we want a negative score for a good pose, thus we will use the negative of the value computed above
score_ = -(f2f_score + f2e_score);
/*
scaleScore();
return score_;
*/
return getScaledScore();
}
}
|