/** 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; }