#include "SuperBB.h" #include "HierarchicalFold.h" SuperBB::SuperBB(std::shared_ptr bb) : backBonePen_(0), transScore_(0), weightedTransScore_(100) { bbs_.push_back(bb); Vector3 v(0, 0, 0); Matrix3 M(1); RigidTrans3 T(M, v); trans_.push_back(T); size_ = 1; bitIDS_ = bb->bitId(); } float getWeightedTransScore(std::vector steps, std::vector> bbs) { unsigned int totalCa = 0; float totalScore = 0; std::map bbIdToCaLength; for (std::shared_ptr bb : bbs) { bbIdToCaLength[bb->getID()] = bb->getNumOfAtoms(); } for (FoldStep step : steps) { std::vector right; std::vector left; right.push_back(step.i_); left.push_back(step.j_); std::vector notUsedSteps(steps); while (!notUsedSteps.empty()) { FoldStep step2 = notUsedSteps.back(); notUsedSteps.pop_back(); if (step2.i_ == step.i_ && step2.j_ == step.j_) continue; if (std::find(right.begin(), right.end(), step2.i_) != right.end() && std::find(right.begin(), right.end(), step2.j_) == right.end()) { right.push_back(step2.j_); } else if (std::find(right.begin(), right.end(), step2.j_) != right.end() && std::find(right.begin(), right.end(), step2.i_) == right.end()) { right.push_back(step2.i_); } else if (std::find(left.begin(), left.end(), step2.i_) != left.end() && std::find(left.begin(), left.end(), step2.j_) == left.end()) { left.push_back(step2.j_); } else if (std::find(left.begin(), left.end(), step2.j_) != left.end() && std::find(left.begin(), left.end(), step2.i_) == left.end()) { left.push_back(step2.i_); } else { notUsedSteps.insert(notUsedSteps.begin(), step2); } } unsigned int rightSize = 0; unsigned int leftSize = 0; for (unsigned int elem : right) rightSize += bbIdToCaLength[elem]; for (unsigned int elem : left) leftSize += bbIdToCaLength[elem]; unsigned int usedSize = rightSize; if (rightSize > leftSize) usedSize = leftSize; totalScore += usedSize * step.tScore_; totalCa += usedSize; } return totalScore / totalCa; } void SuperBB::join(const RigidTrans3 &trans, const SuperBB &other, int bbPen, FoldStep &step, float transScore) { // now joining is simple for (unsigned int j = 0; j < other.size_; j++) { bbs_.push_back(other.bbs_[j]); trans_.push_back(trans * other.trans_[j]); } size_ += other.size_; bitIDS_ |= other.bitIDS_; backBonePen_ = bbPen; transScore_ += other.transScore_ + transScore; if (!other.foldSteps_.empty()) { foldSteps_.insert(foldSteps_.end(), other.foldSteps_.begin(), other.foldSteps_.end()); } foldSteps_.push_back(step); weightedTransScore_ = getWeightedTransScore(foldSteps_, bbs_); } void SuperBB::replaceIdentBB(BitId oldBBBitId, std::shared_ptr bb) { if((bb->bitId() & bitIDS_) != 0) throw std::runtime_error("Tried to replace BB with BB that already exists in SuperBB"); std::shared_ptr oldBB; unsigned int bbIndex = -1; for (unsigned int i = 0; i < size_; i++) { if (bbs_[i]->bitId() == oldBBBitId) { oldBB = bbs_[i]; bbIndex = i; break; } } if(bbIndex == -1) throw std::runtime_error("SuperBB::replaceIdentBB: oldBBBitId not found in SuperBB"); bbs_[bbIndex] = bb; // bitIDS_ -= oldBB->bitId(); // bitIDS_ += bb->bitId(); bitIDS_[oldBB->getID()] = false; bitIDS_[bb->getID()] = true; for(FoldStep &step : foldSteps_) { if(step.i_ == oldBB->getID()) step.i_ = bb->getID(); if(step.j_ == oldBB->getID()) step.j_ = bb->getID(); } } bool SuperBB::isPenetrating(const RigidTrans3 &trans, const SuperBB &other, float threshold) const { for (unsigned int i = 0; i < size_; i++) { RigidTrans3 t = (!trans_[i]) * trans; for (unsigned int j = 0; j < other.size_; j++) { if (bbs_[i]->isPenetrating(t * other.trans_[j], *other.bbs_[j], threshold)) return true; } } return false; } // RMSD between two SBBs (assuming same BBs in each SBB) double SuperBB::calcRmsd(const SuperBB &other, std::vector> &identGroups) const { std::vector> presentIdentGroups; for (std::vector identGroup : identGroups) { std::vector possiblyRelevantIdentGroup; for (unsigned int i : identGroup) { if (bitIDS_.test(i)) possiblyRelevantIdentGroup.push_back(i); } if (possiblyRelevantIdentGroup.size() >= 2) presentIdentGroups.push_back(possiblyRelevantIdentGroup); } std::map bbIdToThisBBIndex; std::map bbIdToOtherBBIndex; std::vector bbIdsInThis; for (unsigned int i = 0; i < bbs_.size(); i++) { bbIdsInThis.push_back(bbs_[i]->getID()); bbIdToThisBBIndex[bbs_[i]->getID()] = i; for (unsigned int j = 0; j < size_; j++) { if (bbs_[i]->getID() == other.bbs_[j]->getID()) { // same BB bbIdToOtherBBIndex[bbs_[i]->getID()] = j; break; } } } // base rmsd find Match cmMatch; Molecule cmA, cmB; for (unsigned int bbId : bbIdsInThis) { Vector3 a = trans_[bbIdToThisBBIndex[bbId]] * bbs_[bbIdToThisBBIndex[bbId]]->cm_; cmA.add(a); Vector3 b = other.trans_[bbIdToOtherBBIndex[bbId]] * other.bbs_[bbIdToOtherBBIndex[bbId]]->cm_; cmB.add(b); } for (unsigned int i = 0; i < size_; i++) { cmMatch.add(i, i); } cmMatch.calculateBestFit(cmA, cmB); float foundRMSD = cmMatch.rmsd(); int MAX_ITER = 10; // try replacing chains with each other for (int i = 0; i < MAX_ITER; i++) { // std::cout << "iter " << i << std::endl; bool somethingChanged = false; for (std::vector identGroup : presentIdentGroups) { for (unsigned int i = 0; i < identGroup.size(); i++) { for (unsigned int j = i + 1; j < identGroup.size(); j++) { Match cmMatch; Molecule cmA, cmB; for (unsigned int bbId : bbIdsInThis) { Vector3 a; if (bbId == identGroup[i]) { unsigned int replacedbbId = identGroup[j]; a = trans_[bbIdToThisBBIndex[replacedbbId]] * bbs_[bbIdToThisBBIndex[replacedbbId]]->cm_; } else if (bbId == identGroup[j]) { unsigned int replacedbbId = identGroup[i]; a = trans_[bbIdToThisBBIndex[replacedbbId]] * bbs_[bbIdToThisBBIndex[replacedbbId]]->cm_; } else { a = trans_[bbIdToThisBBIndex[bbId]] * bbs_[bbIdToThisBBIndex[bbId]]->cm_; } cmA.add(a); Vector3 b = other.trans_[bbIdToOtherBBIndex[bbId]] * other.bbs_[bbIdToOtherBBIndex[bbId]]->cm_; cmB.add(b); } for (unsigned int i = 0; i < size_; i++) { cmMatch.add(i, i); } cmMatch.calculateBestFit(cmA, cmB); float newRMSD = cmMatch.rmsd(); if (newRMSD < foundRMSD) { // std::cout << "replacing chains in calcRMSD " << newRMSD << " " << foundRMSD << " " << // identGroup[i] << " " << identGroup[j] << " " << bbIdToThisBBIndex[identGroup[i]] << " " << // bbIdToThisBBIndex[identGroup[j]] << std::endl; unsigned int tmp = bbIdToThisBBIndex[identGroup[i]]; bbIdToThisBBIndex[identGroup[i]] = bbIdToThisBBIndex[identGroup[j]]; bbIdToThisBBIndex[identGroup[j]] = tmp; foundRMSD = newRMSD; somethingChanged = true; } else { // std::cout << "not replacing chains in calcRMSD " << newRMSD << " " << foundRMSD << " " << // identGroup[i] << " " << identGroup[j] << std::endl; } } } } if (!somethingChanged) break; if (i == MAX_ITER - 1) std::cout << "stops clustering because max iteration " << bitIDS_ << std::endl; } if (foundRMSD > 1.5) return foundRMSD; Match match; Molecule A, B; for (unsigned int bbId : bbIdsInThis) { Molecule molA = bbs_[bbIdToThisBBIndex[bbId]]->caAtoms_; molA.rigidTrans(trans_[bbIdToThisBBIndex[bbId]]); A.concat(molA); Molecule molB = other.bbs_[bbIdToOtherBBIndex[bbId]]->caAtoms_; molB.rigidTrans(other.trans_[bbIdToOtherBBIndex[bbId]]); B.concat(molB); } for (unsigned int i = 0; i < A.size(); i++) { match.add(i, i); } match.calculateBestFit(A, B); return match.rmsd(); } double SuperBB::calcRmsd(const SuperBB &other) const { std::vector> emptyIdentGroups; return calcRmsd(other, emptyIdentGroups); } void SuperBB::fullReport(std::ostream &s) { HierarchicalFold::countResults_++; RigidTrans3 tr; s << "size_ " << size_ << " transScore_ " << transScore_ << " multPen_ " << multPen_ << " singlePen_ " << singlePen_ << " diffPen " << singlePen_ - multPen_ << " backBonePen_ " << backBonePen_ << " maxPen_ " << maxPen_ << " restraintsRatio_ " << restraintsRatio_ << " weightedTransScore " << weightedTransScore_; s << " ["; int i = 0; for (auto it = bbs_.begin(); it != bbs_.end(); it++, i++) { s << (*it)->id_ << "(" << trans_[i] << ")"; if (it + 1 != bbs_.end()) s << ","; } s << "] " << tr; FoldStep::outputFoldSteps(s, foldSteps_); s << std::endl; } std::ostream &operator<<(std::ostream &s, const SuperBB &sbb) { // scores s << "size_ " << sbb.size_ << " backBonePen_ " << sbb.backBonePen_ << " restraintsRatio_ " << sbb.restraintsRatio_; // transformations s << " ["; int i = 0; for (auto it = sbb.bbs_.begin(); it != sbb.bbs_.end(); it++, i++) { s << (*it)->getID() << "(" << sbb.trans_[i] << ")"; if (it + 1 != sbb.bbs_.end()) s << ","; } s << "] "; FoldStep::outputFoldSteps(s, sbb.foldSteps_); s << std::endl; return s; } TransIterator2::TransIterator2(const SuperBB &bb1, const SuperBB &bb2, int pbb1, int pbb2) : bb1_(bb1), bb2_(bb2), index1_(0), index2_(0) { std::shared_ptr b1 = bb1_.bbs_[index1_]; while (b1->getID() != pbb1) { b1 = bb1_.bbs_[++index1_]; } std::shared_ptr b2 = bb2_.bbs_[index2_]; while (b2->getID() != pbb2) { b2 = bb2_.bbs_[++index2_]; } mediatorTrans_ = !bb2_.trans_[index2_]; trans_ = &(b1->getTransformations(b2->getID())); // BB::trans(*b1, *b2); it_ = trans_->begin(); if (!isAtEnd()) { generateTransformation(); } }