void PeptideCapProcessor::optimizeCapPosition(Chain& chain, bool start) { Vector3 translation; Atom* axis = NULL; Residue* cap = NULL; std::vector<Atom*> a; std::vector<Atom*> b; Size nr = chain.countResidues(); // cap at the beginning of a peptide if (start) { // put ACE-C to the center for (AtomIterator it = chain.getResidue(1)->beginAtom(); +it; ++it) { if (it->getName() == "N") { translation = it->getPosition(); } b.push_back(&*it); } cap = chain.getResidue(0); for (AtomIterator it = cap->beginAtom(); +it; ++it) { a.push_back(&*it); if (it->getName() == "C") { axis = &*it; } } } //cap at the end of a peptide else { for (AtomIterator it = chain.getResidue(nr-2)->beginAtom(); +it; ++it) { if (it->getName() == "C") { translation = it->getPosition(); } b.push_back(&*it); } cap = chain.getResidue(nr-1); for (AtomIterator it = cap->beginAtom(); +it; ++it) { a.push_back(&*it); if (it->getName() == "N") { axis = &*it; } } } //translate the anchor to origin TranslationProcessor tlp; tlp.setTranslation(translation*-1.0); chain.apply(tlp); //try all torsions float largest_distance = 0.0; float tmp_distance = 0.0; float torsion = 0.0; float step = 2.0; TransformationProcessor tfp; Matrix4x4 m; m.setRotation( Angle(step, false), axis->getPosition()); tfp.setTransformation(m); for (Position r = step; r <= 360; r+=step) { cap->apply(tfp); tmp_distance = computeDistance(a,b); if (largest_distance < tmp_distance) { largest_distance = tmp_distance; torsion = r; } } //apply best rotation angle m.setRotation( Angle(torsion, false), axis->getPosition()); tfp.setTransformation(m); cap->apply(tfp); //now translate the protein back tlp.setTranslation(translation); chain.apply(tlp); }
bool ResidueChecker::checkAtomPositions(const Residue& res, const String& res_name) { // Make sure we are suppose to do this. if (!isEnabled(NAN_POSITIONS) && !isEnabled(STRONGLY_OVERLAPPING_ATOMS) && !isEnabled(OVERLAPPING_ATOMS) && !isEnabled(DUPLICATE_ATOM_NAMES)) { return true; } bool result = true; AtomConstIterator atom_it; for (atom_it = res.beginAtom(); +atom_it; ++atom_it) { // Check for illegal atom positions (NaNs in any of the coordinates). if (isEnabled(NAN_POSITIONS) && (Maths::isNan(atom_it->getPosition().x) || Maths::isNan(atom_it->getPosition().y) || Maths::isNan(atom_it->getPosition().z))) { Log.warn() << "ResidueChecker: illegal atom position (not a number) for atom " << atom_it->getName() << " of " << res_name << endl; // Mark the atoms affected if (selection_) { const_cast<Atom&>(*atom_it).select(); } result = false; } Vector3 pos(atom_it->getPosition()); AtomConstIterator atom_it2; for (atom_it2 = atom_it, ++atom_it2; +atom_it2; ++atom_it2) { // Check for strongly overlapping atoms (closer than 0.2 Angstrom) if (isEnabled(STRONGLY_OVERLAPPING_ATOMS) && (pos.getSquareDistance(atom_it2->getPosition()) < 0.04)) { Log.warn() << "ResidueChecker: atoms far too close -- distance between " << atom_it->getName() << " and " << atom_it2->getName() << " in " << res_name << " is " << pos.getDistance(atom_it2->getPosition()) << " A." << std::endl; // Mark the atoms affected if (selection_) { const_cast<Atom&>(*atom_it).select(); const_cast<Atom&>(*atom_it2).select(); } result = false; } // Check for overlapping atoms (closer than vdW radii minus 0.5 Angstrom) if (isEnabled(OVERLAPPING_ATOMS) && (!atom_it->isBoundTo(*atom_it2))) { double radius1 = atom_it->getElement().getVanDerWaalsRadius(); if (radius1 == 0.0) { radius1 = atom_it->getElement().getAtomicRadius(); } double radius2 = atom_it2->getElement().getVanDerWaalsRadius(); if (radius2 == 0.0) { radius2 = atom_it2->getElement().getAtomicRadius(); } // Compute the square of the sum of the vdw radii minus 0.6 Angstrom // overlap. double min_dist = std::max(radius1 + radius2 - 0.6, 0.0); if (atom_it->isGeminal(*atom_it2)) { min_dist = std::max(min_dist - 1.0, 0.0); } min_dist *= min_dist; // If the atoms are further apart, skip them. if (pos.getSquareDistance(atom_it2->getPosition()) > min_dist) { continue; } // Complain about the overlap and mark the two atoms. Log.warn() << "ResidueChecker: atoms too close -- distance between " << atom_it->getName() << " and " << atom_it2->getName() << " in " << res_name << " is " << pos.getDistance(atom_it2->getPosition()) << " A (min: " << sqrt(min_dist) << ")." << std::endl; // Mark the atoms affected if (selection_) { const_cast<Atom&>(*atom_it).select(); const_cast<Atom&>(*atom_it2).select(); } result = false; } // Check for identical names (OK, a bad place, but why not...) if (isEnabled(DUPLICATE_ATOM_NAMES) && (atom_it->getName() == atom_it2->getName())) { Log.warn() << "ResidueChecker: duplicate atom name " << atom_it->getName() << " in " << res_name << "." << std::endl; result = false; const_cast<Atom&>(*atom_it).select(); const_cast<Atom&>(*atom_it2).select(); } } } return result; }
bool ResidueChecker::checkTemplate(const Residue& residue, const Residue& reference, const String& res_name) { // Make sure there's something to be done at all. if (!isEnabled(SUSPECT_BOND_LENGTHS) && !isEnabled(ELEMENTS)) { return true; } bool result = true; // Check bond lengths (should be within +/- 15% of reference values). Atom::BondConstIterator bond_it; AtomConstIterator bond_atom_it; AtomConstIterator atom_it; BALL_FOREACH_BOND(reference, bond_atom_it, bond_it) { const Atom* first = 0; const Atom* second = 0; for (atom_it = residue.beginAtom(); +atom_it && (first == 0 || second == 0); ++atom_it) { if (atom_it->getName() == bond_it->getFirstAtom()->getName()) { first = &*atom_it; } if (atom_it->getName() == bond_it->getSecondAtom()->getName()) { second = &*atom_it; } } // if we found the bond atoms in residue, check the atom distance if ((first != 0) && (second != 0)) { float distance = first->getPosition().getDistance(second->getPosition()); float deviation = fabs(distance - bond_it->getLength()) / bond_it->getLength(); if (isEnabled(SUSPECT_BOND_LENGTHS) && (deviation > 0.15)) { Log.warn() << "ResidueChecker: in residue " << res_name << ": atom distance " << "between " << first->getName() << " and " << second->getName() << " suspect: " << distance << " A instead of " << bond_it->getLength() << " A" << endl; result = false; // If selection is enabled, mark the two atoms if (selection_) { const_cast<Atom*>(first)->select(); const_cast<Atom*>(second)->select(); } } // Check for the element type of each atom if (isEnabled(ELEMENTS) && (first->getElement() != bond_it->getFirstAtom()->getElement())) { Log.warn() << "ResidueChecker: in residue " << res_name << ": atom " << first->getName() << " is " << first->getElement().getSymbol() << " should be " << bond_it->getFirstAtom()->getElement().getSymbol() << endl; // This could be the anchor of a ResidueRectfifier... // (const_cast<Atom*> (first))->setElement(bond_it->getFirstAtom()->getElement()); result = false; // If selection is enabled, mark the atom if (selection_) { const_cast<Atom*>(first)->select(); } } if (isEnabled(ELEMENTS) && (second->getElement() != bond_it->getSecondAtom()->getElement())) { Log.warn() << "ResidueChecker: in residue " << res_name << ": atom " << second->getName() << " is " << second->getElement().getSymbol() << " should be " << bond_it->getSecondAtom()->getElement().getSymbol() << endl; result = false; // If selection is enabled, mark the atom if (selection_) { const_cast<Atom*>(second)->select(); } } } } return result; }
bool ResidueChecker::checkCompleteness (const Residue& residue, const Residue& reference, const String& res_name) { // Make sure we are suppose to do this. if (!isEnabled(EXTRA_ATOMS) && !isEnabled(MISSING_ATOMS)) { return true; } bool result = true; // First, check for completeness HashSet<String> reference_names; AtomConstIterator atom_it; for (atom_it = reference.beginAtom(); +atom_it; ++atom_it) { reference_names.insert(atom_it->getName()); } // Check for extra atoms in the residue. for (atom_it = residue.beginAtom(); +atom_it; ++atom_it) { if (reference_names.has(atom_it->getName())) { reference_names.erase(atom_it->getName()); } else if (isEnabled(EXTRA_ATOMS)) { Log.warn() << "ResidueChecker: did not find atom " << atom_it->getName() << " of " << res_name << " in the reference residue " << reference.getName() << endl; result = false; // If selection is enabled, mark the residue if (selection_) { const_cast<Residue&>(residue).select(); } } } // Check for missing atoms in the residue. if (isEnabled(MISSING_ATOMS) && (reference_names.size() > 0)) { Log.warn() << "ResidueChecker: did not find the following atoms in " << res_name << " : "; HashSet<String>::Iterator set_it = reference_names.begin(); for (; set_it != reference_names.end(); ++set_it) { Log.warn() << *set_it << " "; } Log.warn() << " (template was " << reference.getName() << ")" << endl; result = false; // If selection is enabled, mark the residue if (selection_) { const_cast<Residue&>(residue).select(); } } return result; }
bool ResidueChecker::checkCharge(const Residue& residue, const String& res_name) { // Make sure we are suppose to do this. if (!isEnabled(LARGE_NET_CHARGE) && !isEnabled(LARGE_CHARGES) && !isEnabled(NON_INTEGRAL_NET_CHARGE)) { return true; } bool result = true; // checking charge: charge should be integral and -2 <= charge <= 2 float total_charge = 0.0; AtomConstIterator atom_it = residue.beginAtom(); for (; +atom_it; ++atom_it) { total_charge += atom_it->getCharge(); // warn for too large charges (above +/- 4 e0) if (isEnabled(LARGE_CHARGES) && (fabs(atom_it->getCharge()) > 4.0)) { Log.warn() << "ResidueChecker: suspect charge of " << atom_it->getCharge() << " for " << atom_it->getName() << " in " << res_name << std::endl; result = false; // If selection is enabled, mark the atom if (selection_) { const_cast<Atom&>(*atom_it).select(); } } } // check for very large absolute charges if (isEnabled(LARGE_NET_CHARGE) && (total_charge < -2.0)) { Log.warn() << "ResidueChecker: in residue " << res_name << ": total charge of " << total_charge << " is too negative." << endl; result = false; // If selection is enabled, mark the residue if (selection_) { const_cast<Residue&>(residue).select(); } } if (isEnabled(LARGE_NET_CHARGE) && (total_charge > 2.0)) { Log.warn() << "ResidueChecker: in residue " << res_name << ": total charge of " << total_charge << " is too positive." << endl; result = false; // If selection is enabled, mark the residue if (selection_) { const_cast<Residue&>(residue).select(); } } // check for integrality of charges float tmp = fabs(fabs(total_charge) - (float)((int)(fabs(total_charge) + 0.5))); if (isEnabled(NON_INTEGRAL_NET_CHARGE) && (tmp > 0.05)) { Log.warn() << "ResidueChecker: in residue " << res_name << ": residue total charge of " << total_charge << " is not integral." << endl; result = false; // If selection is enabled, mark the residue if (selection_) { const_cast<Residue&>(residue).select(); } } return result; }
void EditMode::addStructure_() { QAction* action = dynamic_cast<QAction*>(sender()); if (action == 0) return; String name = ascii(action->text()); scene_->deselect(); if (!fragment_db_) { fragment_db_ = new FragmentDB("fragments/Editing-Fragments.db"); } list<AtomContainer*> containers = scene_->getContainers(); if (containers.size() == 0) return; Residue* residue = fragment_db_->getResidueCopy(name); if (residue == 0) { residue = fragment_db_->getResidueCopy(name + "-Skeleton"); if (residue == 0) return; } Vector3 p; Size nr = 0; AtomIterator ait = residue->beginAtom(); for (;+ait; ++ait) { p += ait->getPosition(); nr++; } if (nr == 0) { BALLVIEW_DEBUG delete residue; return; } p /= (float) nr; QPoint pos = scene_->mapFromGlobal(mouse_pos_new_); Matrix4x4 m; Vector3 x = scene_->mapViewportTo3D(pos.x(), pos.y()); TransformationProcessor tf; Vector3 vv = scene_->getStage()->getCamera().getViewVector(); float l = vv.getLength(); if (!Maths::isZero(l)) vv /= l; Vector3 axis = Vector3(1,0,0) % vv; if (axis.getSquareLength() != 0) { Angle a = vv.getAngle(Vector3(1,0,0)); m.setRotation(a, axis); tf.setTransformation(m); residue->apply(tf); } m.setTranslation(x - p); tf.setTransformation(m); residue->apply(tf); AtomContainer* s = *containers.begin(); if (RTTI::isKindOf<System>(*s)) { System* system = (System*) s; Molecule* mol = system->getMolecule(0); if (mol == 0) { mol = new Molecule(); system->insert(*mol); } s = mol; } s->insert(*residue); scene_->getMainControl()->deselectCompositeRecursive(s, true); scene_->getMainControl()->selectCompositeRecursive(residue, true); scene_->getMainControl()->update(*s); scene_->notify(new NewSelectionMessage); // setMode(MOVE__MODE); }
//TODO switch to real Angle float calculateResidueChiAngles(const Residue& residue) { // some variables Atom const* N = 0; Atom const* CA = 0; Atom const* CB = 0; Atom const* X = 0; int num_of_atoms = 0; float angle = 0;//FLOAT_VALUE_NA; String residue_name = residue.getName(); // we assume that GLY has no typical CHI_1 - angle if (residue_name == "GLY" ) { return angle; } AtomConstIterator r_it = residue.beginAtom(); for (; r_it != residue.endAtom(); ++r_it) { String name = r_it->getName(); if (name == "N") { N = &(*r_it); num_of_atoms += 1; } else if (name == "CA") { CA = &(*r_it); num_of_atoms += 1; } else if (name == "CB") { CB = &(*r_it); num_of_atoms += 1; } } if (num_of_atoms != 3) { Log.info() << "calculateResidueChiAngles: Torsion angle of " << residue_name<< std::endl; return angle; } // determine the missing atom X /* Sidechain dihedral angle chi1 is defined (for non-Gly residues) as follows: Chi1: N(i)-CA(i)-CB(i)-X(i) where X is the following atom for the following residue types: X Residue type ---- ---------------------------- HB1 Ala (for models with protons,labelled 1HB in PDB files). SG Cys CG Asp, Glu, Phe, His, Lys, Leu, Met, Asn, Pro, Gln, Arg, Trp, Tyr CG1 Ile, Val OG Ser OG1 Thr In order to be conform with ShiftX we leave out GLY and ALA */ if (residue_name == "GLY") { Log.info() << "calculateResidueChiAngles: Torsion angle of a Glycine could not be computed!" << std::endl; return angle; } else if (residue_name == "ALA") { r_it = residue.beginAtom(); for (;r_it != residue.endAtom(); ++r_it) { if (r_it->getName() == "HB1" || r_it->getName() == "1HB") { X = &(*r_it); num_of_atoms += 1; break; } } } else if (residue_name == "CYS") { r_it = residue.beginAtom(); for (;r_it != residue.endAtom(); ++r_it) { if (r_it->getName() == "SG") { X = &(*r_it); num_of_atoms += 1; break; } } } else if (residue_name == "ASP" || residue_name == "GLU" || residue_name == "PHE" || residue_name == "HIS" || residue_name == "LYS" || residue_name == "LEU" || residue_name == "MET" || residue_name == "ASN" || residue_name == "PRO" || residue_name == "GLN" || residue_name == "ARG" || residue_name == "TRP" || residue_name == "TYR") { r_it = residue.beginAtom(); for (;r_it != residue.endAtom(); ++r_it) { if (r_it->getName() == "CG") { X = &(*r_it); num_of_atoms += 1; break; } } } else if (residue_name == "VAL" || residue_name == "ILE") { r_it = residue.beginAtom(); for (;r_it != residue.endAtom(); ++r_it) { if (r_it->getName() == "CG1") { X = &(*r_it); num_of_atoms += 1; break; } } } else if (residue_name == "SER") { r_it = residue.beginAtom(); for (;r_it != residue.endAtom(); ++r_it) { if (r_it->getName() == "OG") { X = &(*r_it); num_of_atoms += 1; break; } } } else if (residue_name == "THR") { r_it = residue.beginAtom(); for (;r_it != residue.endAtom(); ++r_it) { if (r_it->getName() == "OG1") { X = &(*r_it); num_of_atoms += 1; break; } } } if (num_of_atoms != 4) { Log.info() << "calculateResidueChiAngles: Chi torsion angle of " << residue.getID() << "-"<< residue.getName() << " could not be computed!" << std::endl; return angle; } Vector3 a = N->getPosition(); Vector3 b = CA->getPosition(); Vector3 c = CB->getPosition(); Vector3 d = X->getPosition(); //angle = getTorsionAngle(a.x, a.y, a.z, b.x, b.y, b.z, // c.x, c.y, c.z, d.x, d.y, d.z)*180./M_PI; angle = calculateTorsionAngle(*N,*CA,*CB,*X).toRadian(); while (angle < 0.) { angle = angle + 2*BALL::Constants::PI; } return angle; // TODO return real angle }
//TODO switch to real Angle float calculateResidueChi2Angles(const Residue& residue) { // some variables Atom const* CA = 0; Atom const* CB = 0; Atom const* CG = 0; Atom const* XG = 0; int num_of_atoms = 0; float angle = 0; // FLOAT_VALUE_NA; String residue_name = residue.getName(); // GLY, ALA, SER and CYS have no typical CHI2 - angle if ( (residue_name == "ALA") || (residue_name == "GLY") || (residue_name == "SER") || (residue_name == "CYS")) { Log.info() << "calculateResidueChi2Angles: Chi torsion angle of " << residue.getID() << "-"<< residue.getName() << " could not be computed!" << std::endl; return angle; } // Sidechain dihedral angle chi2 is defined as follows: // // Chi2: CA(i)-CB(i)-CG(i)-XG(i) // where XG is the following atom for the following // residue types: // // CG XG residue // ------------------------------------- // CG CD PRO, GLN, GLU, LYS, ARG // CD1 LEU,TRP,PHE,TYR, // OD1 ASN, ASP // ND1 HIS // SD MET // CG1 CD1 ILE // 1HG1 VAL // CG2 (1HG2 VAL) // 1HG2 THR // // Note: in some amino acids the atom names can be switched, i.e. // for chi2 in amino acids PHE: CD1 <-> CD2 // TYR: CD1 <-> CD2 // ASP: OD1 <-> OD2 AtomConstIterator r_it = residue.beginAtom(); for (; r_it != residue.endAtom(); ++r_it) { String name = r_it->getName(); if (name == "CA") { CA = &(*r_it); num_of_atoms += 1; } else if (name == "CB") { CB = &(*r_it); num_of_atoms += 1; } if (name == "CG") { CG = &(*r_it); num_of_atoms += 1; } } //look for XG if ( (residue_name == "ARG") || (residue_name == "GLN") || (residue_name == "GLU") || (residue_name == "LYS") || (residue_name == "PRO")) { r_it = residue.beginAtom(); for (;r_it != residue.endAtom(); ++r_it) { if (r_it->getName() == "CD") { XG = &(*r_it); num_of_atoms += 1; break; } } } else if ( (residue_name == "ASN") || (residue_name == "ASP") ) { r_it = residue.beginAtom(); for (;r_it != residue.endAtom(); ++r_it) { if (r_it->getName() == "OD1") { XG = &(*r_it); num_of_atoms += 1; break; } } } else if ( (residue_name == "LEU") || (residue_name == "TRP") ||(residue_name == "PHE") || (residue_name == "TYR") ) { r_it = residue.beginAtom(); for (;r_it != residue.endAtom(); ++r_it) { if (r_it->getName() == "CD1") { XG = &(*r_it); num_of_atoms += 1; break; } } } else if (residue_name == "HIS") { r_it = residue.beginAtom(); for (;r_it != residue.endAtom(); ++r_it) { if (r_it->getName() == "ND1") { XG = &(*r_it); num_of_atoms += 1; break; } } } else if(residue_name == "MET") { r_it = residue.beginAtom(); for (;r_it != residue.endAtom(); ++r_it) { if (r_it->getName() == "SD") { XG = &(*r_it); num_of_atoms += 1; break; } } } // we have to take special care about ILE, VAL and THR else if(residue_name == "ILE") { r_it = residue.beginAtom(); for (;r_it != residue.endAtom(); ++r_it) { if (r_it->getName() == "CG1") { CG = &(*r_it); num_of_atoms += 1; } else if (r_it->getName() == "CD1") { XG = &(*r_it); num_of_atoms += 1; } } } else if(residue_name == "VAL") { r_it = residue.beginAtom(); for (;r_it != residue.endAtom(); ++r_it) { if (r_it->getName() == "1HG1") { XG = &(*r_it); num_of_atoms += 1; } else if (r_it->getName() == "CG1") { CG = &(*r_it); num_of_atoms += 1; } } } else if(residue_name == "THR") { r_it = residue.beginAtom(); for (;r_it != residue.endAtom(); ++r_it) { if (r_it->getName() == "1HG2") { XG = &(*r_it); num_of_atoms += 1; } else if (r_it->getName() == "CG2") { CG = &(*r_it); num_of_atoms += 1; } } } if (num_of_atoms != 4) { Log.info() << "calculateResidueChi2Angles: Chi torsion angle of " << residue.getID() << "-"<< residue.getName() << " could not be computed!" << std::endl; return angle; } Vector3 a = CA->getPosition(); Vector3 b = CB->getPosition(); Vector3 c = CG->getPosition(); Vector3 d = XG->getPosition(); angle = calculateTorsionAngle(*CA,*CB,*CG,*XG).toRadian(); while (angle < 0.) { angle = angle + 2*BALL::Constants::PI; } return angle; // TODO return real angle }