// ----------------------------------------------------------------------------- std::string Action_NMRrst::Site::SiteLegend(Topology const& top) const { std::string legend( top.TruncResNameNum(resNum_) + "(" ); for (Iarray::const_iterator atom = indices_.begin(); atom != indices_.end(); ++atom) { if (atom != indices_.begin()) legend.append(","); legend.append( top[*atom].Name().Truncated() ); } legend.append(")"); return legend; }
/** Find potential symmetric atoms. All residues up to the last selected * residue are considered. */ int SymmetricRmsdCalc::SetupSymmRMSD(Topology const& topIn, AtomMask const& tgtMask, bool remapIn) { // Allocate space for remapping selected atoms in target frame. This will // also put the correct masses in based on the mask. tgtRemap_.SetupFrameFromMask(tgtMask, topIn.Atoms()); // Create map of original atom numbers to selected indices Iarray SelectedIdx( topIn.Natom(), -1 ); int tgtIdx = 0; for (int originalAtom = 0; originalAtom != topIn.Natom(); ++originalAtom) if ( originalAtom == tgtMask[tgtIdx] ) SelectedIdx[originalAtom] = tgtIdx++; if (debug_ > 0) { mprintf("DEBUG: Original atom -> Selected Index mapping:\n"); for (int originalAtom = 0; originalAtom != topIn.Natom(); ++originalAtom) mprintf("\t%8i -> %8i\n", originalAtom + 1, SelectedIdx[originalAtom] + 1); } // Create initial 1 to 1 atom map for all selected atoms; indices in // SymmetricAtomIndices will correspond to positions in AMap. AMap_.resize( tgtRemap_.Natom() ); // Determine last selected residue. int last_res = topIn[tgtMask.back()].ResNum() + 1; mprintf("\tResidues up to %s will be considered for symmetry correction.\n", topIn.TruncResNameNum(last_res-1).c_str()); // In each residue, determine which selected atoms are symmetric. SymmetricAtomIndices_.clear(); AtomMap resmap; if (debug_ > 1) resmap.SetDebug(1); for (int res = 0; res < last_res; ++res) { AtomMap::AtomIndexArray residue_SymmetricGroups; if (resmap.SymmetricAtoms(topIn, residue_SymmetricGroups, res)) { mprinterr("Error: Finding symmetric atoms in residue '%s'\n", topIn.TruncResNameNum(res).c_str()); return 1; } if (!residue_SymmetricGroups.empty()) { // Which atoms in symmetric groups are selected? bool resHasSelectedSymmAtoms = false; for (AtomMap::AtomIndexArray::const_iterator symmGroup = residue_SymmetricGroups.begin(); symmGroup != residue_SymmetricGroups.end(); ++symmGroup) { Iarray selectedAtomIndices; for (Iarray::const_iterator atnum = symmGroup->begin(); atnum != symmGroup->end(); ++atnum) { if ( SelectedIdx[*atnum] != -1 ) selectedAtomIndices.push_back( SelectedIdx[*atnum] ); // Store tgtMask indices } if (!selectedAtomIndices.empty()) { SymmetricAtomIndices_.push_back( selectedAtomIndices ); resHasSelectedSymmAtoms = true; } } // If remapping and not all atoms in a residue are selected, warn user. // TODO: Should they just be considered even if not selected? if (remapIn && resHasSelectedSymmAtoms) { for (int atom = topIn.Res(res).FirstAtom(); atom != topIn.Res(res).LastAtom(); ++atom) if (SelectedIdx[atom] == -1) { mprintf("Warning: Not all atoms selected in residue '%s'. Re-mapped\n" "Warning: structures may appear distorted.\n", topIn.TruncResNameNum(res).c_str()); break; } } } } if (debug_ > 0) { mprintf("DEBUG: Potential Symmetric Atom Groups:\n"); for (AtomIndexArray::const_iterator symmatoms = SymmetricAtomIndices_.begin(); symmatoms != SymmetricAtomIndices_.end(); ++symmatoms) { mprintf("\t%8u) ", symmatoms - SymmetricAtomIndices_.begin()); for (Iarray::const_iterator atom = symmatoms->begin(); atom != symmatoms->end(); ++atom) mprintf(" %s(%i)", topIn.AtomMaskName(tgtMask[*atom]).c_str(), tgtMask[*atom] + 1); mprintf("\n"); } } return 0; }
/** Perform setup required for per residue rmsd calculation. * Need to set up a target mask, reference mask, and dataset for each * residue specified in ResRange. * NOTE: Residues in the range arguments from user start at 1, internal * res nums start from 0. */ int Action_Rmsd::perResSetup(Topology const& currentParm, Topology const& refParm) { Range tgt_range; // Selected target residues Range ref_range; // Selected reference residues // If no target range previously specified do all solute residues if (TgtRange_.Empty()) { tgt_range = currentParm.SoluteResidues(); tgt_range.ShiftBy(1); // To match user range arg which would start from 1 } else tgt_range = TgtRange_; // If the reference range is empty, set it to match the target range if (RefRange_.Empty()) ref_range = tgt_range; else ref_range = RefRange_; // Check that the number of reference residues matches number of target residues if (tgt_range.Size() != ref_range.Size()) { mprintf("Warning: Number of target residues %i does not match\n" "Warning: number of reference residues %i.\n", tgt_range.Size(), ref_range.Size()); return 1; } // Setup a dataset, target mask, and reference mask for each residue. int maxNatom = 0; Range::const_iterator ref_it = ref_range.begin(); MetaData md(rmsd_->Meta().Name(), "res"); md.SetScalarMode( MetaData::M_RMS ); for (Range::const_iterator tgt_it = tgt_range.begin(); tgt_it != tgt_range.end(); ++tgt_it, ++ref_it) { int tgtRes = *tgt_it; int refRes = *ref_it; // Check if either the residue num or the reference residue num out of range. if ( tgtRes < 1 || tgtRes > currentParm.Nres()) { mprintf("Warning: Specified residue # %i is out of range.\n", tgtRes); continue; } if ( refRes < 1 || refRes > refParm.Nres() ) { mprintf("Warning: Specified reference residue # %i is out of range.\n", refRes); continue; } // Check if a perResType has been set for this residue # yet. perResArray::iterator PerRes; for (PerRes = ResidueRMS_.begin(); PerRes != ResidueRMS_.end(); ++PerRes) if ( PerRes->data_->Meta().Idx() == tgtRes ) break; // If necessary, create perResType for residue if (PerRes == ResidueRMS_.end()) { perResType p; md.SetIdx( tgtRes ); md.SetLegend( currentParm.TruncResNameNum(tgtRes-1) ); p.data_ = (DataSet_1D*)masterDSL_->AddSet(DataSet::DOUBLE, md); if (p.data_ == 0) { mprinterr("Internal Error: Could not set up per residue data set.\n"); return 2; } if (perresout_ != 0) perresout_->AddDataSet( p.data_ ); // Setup mask strings. Note that masks are based off user residue nums p.tgtResMask_.SetMaskString(":" + integerToString(tgtRes) + perresmask_); p.refResMask_.SetMaskString(":" + integerToString(refRes) + perresmask_); ResidueRMS_.push_back( p ); PerRes = ResidueRMS_.end() - 1; } PerRes->isActive_ = false; // Setup the reference mask if (refParm.SetupIntegerMask(PerRes->refResMask_)) { mprintf("Warning: Could not setup reference mask for residue %i\n",refRes); continue; } if (PerRes->refResMask_.None()) { mprintf("Warning: No atoms selected for reference residue %i\n",refRes); continue; } // Setup the target mask if (currentParm.SetupIntegerMask(PerRes->tgtResMask_)) { mprintf("Warning: Could not setup target mask for residue %i\n",tgtRes); continue; } if (PerRes->tgtResMask_.None()) { mprintf("Warning: No atoms selected for target residue %i\n",tgtRes); continue; } // Check that # atoms in target and reference masks match if (PerRes->tgtResMask_.Nselected() != PerRes->refResMask_.Nselected()) { mprintf("Warning: Res %i: # atoms in Tgt (%i) != # atoms in Ref (%i)\n", tgtRes, PerRes->tgtResMask_.Nselected(), PerRes->refResMask_.Nselected()); if (debug_ > 0) { mprintf(" Target Atoms:\n"); for (AtomMask::const_iterator t = PerRes->tgtResMask_.begin(); t != PerRes->tgtResMask_.end(); ++t) mprintf("\t%s\n", currentParm.AtomMaskName(*t).c_str()); mprintf(" Ref Atoms:\n"); for (AtomMask::const_iterator r = PerRes->refResMask_.begin(); r != PerRes->refResMask_.end(); ++r) mprintf("\t%s\n", refParm.AtomMaskName(*r).c_str()); } continue; } if ( PerRes->tgtResMask_.Nselected() > maxNatom ) maxNatom = PerRes->tgtResMask_.Nselected(); // Indicate that these masks were properly set up PerRes->isActive_ = true; } mprintf("\tMax # selected atoms in residues: %i\n", maxNatom); // Allocate memory for target and reference residue frames. // Although initial masses are wrong this is OK since the number of atoms // and masses will be assigned when residue RMSD is actually being calcd. if (maxNatom > 0) { std::vector<Atom> temp( maxNatom ); ResTgtFrame_.SetupFrameM( temp ); ResRefFrame_.SetupFrameM( temp ); } else { mprintf("Warning: No residues selected for per-residue calculation.\n"); return 1; } return 0; }