// Action_CheckStructure::SeparateSetup() int Action_CheckStructure::SeparateSetup(Topology const& top, Box::BoxType btype, bool checkBonds) { image_.SetupImaging( btype ); bondList_.clear(); // Set up masks if ( top.SetupIntegerMask( Mask1_ ) ) return 1; Mask1_.MaskInfo(); if (Mask1_.None()) { mprinterr("Error: Mask '%s' has no atoms.\n", Mask1_.MaskString()); return 1; } if (checkBonds) SetupBondList(Mask1_, top); if ( Mask2_.MaskStringSet() ) { if (top.SetupIntegerMask( Mask2_ ) ) return 1; Mask2_.MaskInfo(); if (Mask2_.None()) { mprinterr("Error: Mask '%s' has no atoms.\n", Mask2_.MaskString()); return 1; } int common = Mask1_.NumAtomsInCommon( Mask2_ ); if (common > 0) mprintf("Warning: '%s' has %i atoms in common with '%s'. Some problems may be reported\n" "Warning: more than once.\n", Mask1_.MaskString(), common, Mask2_.MaskString()); // Outer mask should be the one with the most atoms. if ( Mask2_.Nselected() > Mask1_.Nselected() ) { OuterMask_ = Mask2_; InnerMask_ = Mask1_; } else { OuterMask_ = Mask1_; InnerMask_ = Mask2_; } if (checkBonds) SetupBondList(Mask2_, top); } return 0; }
// ReferenceAction::SetRefMask() int ReferenceAction::SetRefMask(Topology const& topIn, const char* call) { if (topIn.SetupIntegerMask( refMask_ )) return 1; mprintf("\tReference mask:"); refMask_.BriefMaskInfo(); mprintf("\n"); if (refMask_.None()) { mprinterr("Error: %s: No reference atoms selected for parm %s, [%s]\n", call, topIn.c_str(), refMask_.MaskString()); return 1; } selectedRef_.SetupFrameFromMask( refMask_, topIn.Atoms() ); return 0; }
/** Based on selected atoms in Mask1 (and optionally Mask2), set up * potential contact lists. Also set up atom/residue indices corresponding * to each potential contact. */ int Action_NativeContacts::SetupContactLists(Topology const& parmIn, Frame const& frameIn) { // Setup first contact list if ( parmIn.SetupIntegerMask( Mask1_, frameIn ) ) return 1; if (!includeSolvent_) removeSelectedSolvent( parmIn, Mask1_ ); Mask1_.MaskInfo(); if (Mask1_.None()) { mprinterr("Warning: Nothing selected for '%s'\n", Mask1_.MaskString()); return 1; } if (debug_ > 0) DebugContactList( Mask1_, parmIn ); contactIdx1_ = SetupContactIndices( Mask1_, parmIn ); // Setup second contact list if necessary if ( Mask2_.MaskStringSet() ) { if (parmIn.SetupIntegerMask( Mask2_, frameIn ) ) return 1; if (!includeSolvent_) removeSelectedSolvent( parmIn, Mask2_ ); Mask2_.MaskInfo(); if (Mask2_.None()) { mprinterr("Warning: Nothing selected for '%s'\n", Mask2_.MaskString()); return 1; } // Warn if masks overlap int nOverlap = Mask1_.NumAtomsInCommon( Mask2_ ); if (nOverlap > 0) { mprintf("Warning: Masks '%s' and '%s' overlap by %i atoms.\n" "Warning: Some contacts may be double-counted.\n", Mask1_.MaskString(), Mask2_.MaskString(), nOverlap); if (mindist_ != 0) mprintf("Warning: Minimum distance will always be 0.0\n"); } if (debug_ > 0) DebugContactList( Mask2_, parmIn ); contactIdx2_ = SetupContactIndices( Mask2_, parmIn ); } return 0; }
Exec::RetType Exec_ParmStrip::Execute(CpptrajState& State, ArgList& argIn) { Topology* parm = State.DSL().GetTopByIndex( argIn ); if (parm == 0) return CpptrajState::ERR; // Check if this topology has already been used to set up an input // trajectory, as this will break the traj read. bool topology_in_use = false; const char* fname = 0; for (TrajinList::trajin_it tIn = State.InputTrajList().trajin_begin(); tIn != State.InputTrajList().trajin_end(); ++tIn) if ( (*tIn)->Traj().Parm() == parm ) { topology_in_use = true; fname = (*tIn)->Traj().Filename().full(); break; } if (!topology_in_use) { for (TrajinList::ensemble_it eIn = State.InputTrajList().ensemble_begin(); eIn != State.InputTrajList().ensemble_end(); ++eIn) if ( (*eIn)->Traj().Parm() == parm ) { topology_in_use = true; fname = (*eIn)->Traj().Filename().full(); break; } } if (topology_in_use) { mprinterr("Error: Topology '%s' has already been used to set up trajectory '%s'.\n" "Error: To strip this topology use the 'strip' action.\n", parm->c_str(), fname); return CpptrajState::ERR; } AtomMask tempMask( argIn.GetMaskNext() ); // Since want to keep atoms outside mask, invert selection tempMask.InvertMaskExpression(); if (parm->SetupIntegerMask( tempMask )) return CpptrajState::ERR; mprintf("\tStripping atoms in mask [%s] (%i) from %s\n",tempMask.MaskString(), parm->Natom() - tempMask.Nselected(), parm->c_str()); Topology* tempParm = parm->modifyStateByMask(tempMask); if (tempParm==0) { mprinterr("Error: %s: Could not strip parm.\n", argIn.Command()); return CpptrajState::ERR; } else { // Replace parm with stripped version *parm = *tempParm; parm->Brief("Stripped parm:"); delete tempParm; } return CpptrajState::OK; }
/** Process a mask from the command line. */ int Cpptraj::ProcessMask( Sarray const& topFiles, Sarray const& refFiles, std::string const& maskexpr, bool verbose, bool residue ) const { SetWorldSilent(true); if (topFiles.empty()) { mprinterr("Error: No topology file specified.\n"); return 1; } ParmFile pfile; Topology parm; if (pfile.ReadTopology(parm, topFiles[0], State_.Debug())) return 1; if (!refFiles.empty()) { DataSet_Coords_REF refCoords; if (refCoords.LoadRefFromFile( refFiles[0], parm, State_.Debug())) return 1; parm.SetDistMaskRef( refCoords.RefFrame() ); } if (!verbose) { AtomMask tempMask( maskexpr ); if (parm.SetupIntegerMask( tempMask )) return 1; loudPrintf("Selected="); if (residue) { int res = -1; for (AtomMask::const_iterator atom = tempMask.begin(); atom != tempMask.end(); ++atom) { if (parm[*atom].ResNum() > res) { loudPrintf(" %i", parm[*atom].ResNum()+1); res = parm[*atom].ResNum(); } } } else for (AtomMask::const_iterator atom = tempMask.begin(); atom != tempMask.end(); ++atom) loudPrintf(" %i", *atom + 1); loudPrintf("\n"); } else { if (residue) parm.PrintResidueInfo( maskexpr ); else parm.PrintAtomInfo( maskexpr ); } return 0; }
/** An atom pair list consists of 2 values for each entry, a beginning * index and ending index. For molecules and residues this is the first * and just beyond the last atom; for atoms it is just the atom itself * twice. */ Image::PairType Image::CreatePairList(Topology const& Parm, Mode modeIn, std::string const& maskExpression) { PairType atomPairs; // Set up mask based on desired imaging mode. if ( modeIn == BYMOL || modeIn == BYRES ) { CharMask cmask( maskExpression ); if ( Parm.SetupCharMask( cmask ) ) return atomPairs; cmask.MaskInfo(); if (cmask.None()) return atomPairs; // Set up atom range for each entity to be imaged. if (modeIn == BYMOL) { atomPairs.reserve( Parm.Nmol()*2 ); for (Topology::mol_iterator mol = Parm.MolStart(); mol != Parm.MolEnd(); ++mol) CheckRange( atomPairs, cmask, mol->BeginAtom(), mol->EndAtom()); } else { // BYRES atomPairs.reserve( Parm.Nres()*2 ); for (Topology::res_iterator residue = Parm.ResStart(); residue != Parm.ResEnd(); ++residue) CheckRange( atomPairs, cmask, residue->FirstAtom(), residue->LastAtom() ); } } else { // BYATOM AtomMask imask( maskExpression ); if ( Parm.SetupIntegerMask( imask ) ) return atomPairs; imask.MaskInfo(); if (imask.None()) return atomPairs; atomPairs.reserve( Parm.Natom()*2 ); for (AtomMask::const_iterator atom = imask.begin(); atom != imask.end(); ++atom) { atomPairs.push_back( *atom ); atomPairs.push_back( (*atom)+1 ); } } // mprintf("\tNumber of %ss to be imaged is %zu based on mask '%s'\n", // ModeString[modeIn], atomPairs.size()/2, maskIn.MaskString()); return atomPairs; }
/** Like the strip action, closest will modify the current parm keeping info * for atoms in mask plus the closestWaters solvent molecules. Set up the * vector of MolDist objects, one for every solvent molecule in the original * parm file. Atom masks for each solvent molecule will be set up. */ Action_Closest::RetType Action_Closest::Setup(Topology const& topIn, CoordinateInfo const& cInfoIn) { // If there are no solvent molecules this action is not valid. if (topIn.Nsolvent()==0) { mprintf("Warning: Parm %s does not contain solvent.\n",topIn.c_str()); return Action_Closest::SKIP; } // If # solvent to keep >= solvent in this parm the action is not valid. if (closestWaters_ >= topIn.Nsolvent()) { mprintf("Warning: # solvent to keep (%i) >= # solvent molecules in '%s' (%i)\n", closestWaters_, topIn.c_str(), topIn.Nsolvent()); return Action_Closest::SKIP; } image_.SetupImaging( cInfoIn.TrajBox().Type() ); if (image_.ImagingEnabled()) mprintf("\tDistances will be imaged.\n"); else mprintf("\tImaging off.\n"); // LOOP OVER MOLECULES // 1: Check that all solvent molecules contain same # atoms. Solvent // molecules must be identical for the command to work properly; // the prmtop strip occurs only once so the solvent params become fixed. // 2: Set up a mask for all solvent molecules. SolventMols_.clear(); // NOTE: May not be necessary to init 'solvent' MolDist solvent; solvent.D = 0.0; solvent.mol = 0; SolventMols_.resize(topIn.Nsolvent(), solvent); std::vector<MolDist>::iterator mdist = SolventMols_.begin(); // 3: Set up the soluteMask for all non-solvent molecules. int molnum = 1; int nclosest = 0; int NsolventAtoms = -1; for (Topology::mol_iterator Mol = topIn.MolStart(); Mol != topIn.MolEnd(); ++Mol) { if ( Mol->IsSolvent() ) { // Solvent, check for same # of atoms. if (NsolventAtoms == -1) NsolventAtoms = Mol->NumAtoms(); else if ( NsolventAtoms != Mol->NumAtoms() ) { mprinterr("Error: Solvent molecules in '%s' are not of uniform size.\n" "Error: First solvent mol = %i atoms, solvent mol %i = %i atoms.\n", topIn.c_str(), NsolventAtoms, molnum, (*Mol).NumAtoms()); return Action_Closest::ERR; } // mol here is the output molecule number which is why it starts from 1. mdist->mol = molnum; // Solvent molecule mask mdist->mask.AddAtomRange( Mol->BeginAtom(), Mol->EndAtom() ); // Atoms in the solvent molecule to actually calculate distances to. if (firstAtom_) { mdist->solventAtoms.assign(1, Mol->BeginAtom() ); } else { mdist->solventAtoms.clear(); mdist->solventAtoms.reserve( Mol->NumAtoms() ); for (int svatom = Mol->BeginAtom(); svatom < Mol->EndAtom(); svatom++) mdist->solventAtoms.push_back( svatom ); } if (debug_ > 0) { mprintf("DEBUG:\tSet up mol %i:", mdist->mol); // DEBUG mdist->mask.PrintMaskAtoms("solvent"); // DEBUG mprintf("\n"); // DEBUG } ++mdist; } ++molnum; } // Setup distance atom mask // NOTE: Should ensure that no solvent atoms are selected! if ( topIn.SetupIntegerMask(distanceMask_) ) return Action_Closest::ERR; if (distanceMask_.None()) { mprintf("Warning: Distance mask '%s' contains no atoms.\n", distanceMask_.MaskString()); return Action_Closest::SKIP; } distanceMask_.MaskInfo(); // Check the total number of solvent atoms to be kept. NsolventAtoms *= closestWaters_; mprintf("\tKeeping %i solvent atoms.\n",NsolventAtoms); if (NsolventAtoms < 1) { mprintf("Warning: # of solvent atoms to be kept is < 1.\n"); return Action_Closest::SKIP; } NsolventMolecules_ = (int)SolventMols_.size(); return Action_Closest::OK; }
// Analysis_Modes::Setup() Analysis::RetType Analysis_Modes::Setup(ArgList& analyzeArgs, AnalysisSetup& setup, int debugIn) { debug_ = debugIn; // Analysis type if (analyzeArgs.hasKey("fluct")) type_ = FLUCT; else if (analyzeArgs.hasKey("displ")) type_ = DISPLACE; else if (analyzeArgs.hasKey("corr")) type_ = CORR; else if (analyzeArgs.Contains("trajout")) type_ = TRAJ; else if (analyzeArgs.hasKey("eigenval")) type_ = EIGENVAL; else if (analyzeArgs.hasKey("rmsip")) type_ = RMSIP; else { mprinterr("Error: No analysis type specified.\n"); return Analysis::ERR; } // Get modes name std::string modesfile = analyzeArgs.GetStringKey("name"); if (modesfile.empty()) { // Check for deprecated args CheckDeprecated(analyzeArgs, modesfile, "file"); CheckDeprecated(analyzeArgs, modesfile, "stack"); if (modesfile.empty()) { mprinterr("Error: No 'name <modes data set name>' argument given.\n"); return Analysis::ERR; } } // Get second modes name for RMSIP std::string modesfile2 = analyzeArgs.GetStringKey("name2"); if (type_ == RMSIP) { if (modesfile2.empty()) { mprinterr("Error: 'rmsip' requires second modes data 'name2 <modes>'\n"); return Analysis::ERR; } } else modesfile2.clear(); // Get topology for TRAJ/CORR Topology* analyzeParm = setup.DSL().GetTopology( analyzeArgs ); if (type_ == TRAJ ) { // Get trajectory format args for projected traj beg_ = analyzeArgs.getKeyInt("beg",1) - 1; // Args start at 1 std::string tOutName = analyzeArgs.GetStringKey("trajout"); if (tOutName.empty()) { mprinterr("Error: Require output trajectory filename, 'trajout <name>'\n"); return Analysis::ERR; } TrajectoryFile::TrajFormatType tOutFmt = TrajectoryFile::UNKNOWN_TRAJ; if ( analyzeArgs.Contains("trajoutfmt") ) tOutFmt = TrajectoryFile::GetFormatFromString( analyzeArgs.GetStringKey("trajoutfmt") ); if (analyzeParm == 0) { mprinterr("Error: Could not get topology for output trajectory.\n"); return Analysis::ERR; } AtomMask tOutMask( analyzeArgs.GetStringKey("trajoutmask") ); if ( analyzeParm->SetupIntegerMask( tOutMask ) || tOutMask.None() ) { mprinterr("Error: Could not setup output trajectory mask.\n"); return Analysis::ERR; } tOutMask.MaskInfo(); // Strip topology to match mask. if (tOutParm_ != 0) delete tOutParm_; tOutParm_ = analyzeParm->modifyStateByMask( tOutMask ); if (tOutParm_ == 0) { mprinterr("Error: Could not create topology to match mask.\n"); return Analysis::ERR; } // Setup output traj if (trajout_.InitTrajWrite( tOutName, ArgList(), tOutFmt ) != 0) { mprinterr("Error: Could not init output trajectory.\n"); return Analysis::ERR; } // Get min and max for PC pcmin_ = analyzeArgs.getKeyDouble("pcmin", -10.0); pcmax_ = analyzeArgs.getKeyDouble("pcmax", 10.0); if (pcmax_ < pcmin_ || pcmax_ - pcmin_ < Constants::SMALL) { mprinterr("Error: pcmin must be less than pcmax\n"); return Analysis::ERR; } tMode_ = analyzeArgs.getKeyInt("tmode", 1); } else { // Args for everything else beg_ = analyzeArgs.getKeyInt("beg",7) - 1; // Args start at 1 bose_ = analyzeArgs.hasKey("bose"); calcAll_ = analyzeArgs.hasKey("calcall"); } end_ = analyzeArgs.getKeyInt("end", 50); factor_ = analyzeArgs.getKeyDouble("factor",1.0); std::string setname = analyzeArgs.GetStringKey("setname"); // Check if modes name exists on the stack modinfo_ = (DataSet_Modes*)setup.DSL().FindSetOfType( modesfile, DataSet::MODES ); if (modinfo_ == 0) { mprinterr("Error: '%s' not found: %s\n", modesfile.c_str(), DataSet_Modes::DeprecateFileMsg); return Analysis::ERR; } if (!modesfile2.empty()) { modinfo2_ = (DataSet_Modes*)setup.DSL().FindSetOfType( modesfile2, DataSet::MODES ); if (modinfo2_ == 0) { mprinterr("Error: Set %s not found.\n", modesfile2.c_str()); return Analysis::ERR; } } // Check modes type for specified analysis if (type_ == FLUCT || type_ == DISPLACE || type_ == CORR || type_ == TRAJ) { if (modinfo_->Meta().ScalarType() != MetaData::COVAR && modinfo_->Meta().ScalarType() != MetaData::MWCOVAR) { mprinterr("Error: Modes must be of type COVAR or MWCOVAR for %s.\n", analysisTypeString[type_]); return Analysis::ERR; } } // Get output filename for types that use DataSets std::string outfilename = analyzeArgs.GetStringKey("out"); // TODO all datafile? DataFile* dataout = 0; if (type_ == FLUCT || type_ == DISPLACE || type_ == EIGENVAL || type_ == RMSIP) dataout = setup.DFL().AddDataFile( outfilename, analyzeArgs ); else if (type_ == CORR) { // CORR-specific setup outfile_ = setup.DFL().AddCpptrajFile( outfilename, "Modes analysis", DataFileList::TEXT, true ); if (outfile_ == 0) return Analysis::ERR; // Get list of atom pairs if (analyzeParm == 0) { mprinterr("Error: 'corr' requires topology.\n"); return Analysis::ERR; } std::string maskexp = analyzeArgs.GetStringKey("mask1"); if (maskexp.empty()) { while (analyzeArgs.hasKey("maskp")) { // Next two arguments should be one-atom masks std::string a1mask = analyzeArgs.GetMaskNext(); std::string a2mask = analyzeArgs.GetMaskNext(); if (a1mask.empty() || a2mask.empty()) { mprinterr("Error: For 'corr' two 1-atom masks are expected.\n"); return Analysis::ERR; } // Check that each mask is just 1 atom AtomMask m1( a1mask ); AtomMask m2( a2mask ); analyzeParm->SetupIntegerMask( m1 ); analyzeParm->SetupIntegerMask( m2 ); if ( m1.Nselected()==1 && m2.Nselected()==1 ) // Store atom pair atompairStack_.push_back( std::pair<int,int>( m1[0], m2[0] ) ); else { mprinterr("Error: For 'corr', masks should specify only one atom.\n" "\tM1[%s]=%i atoms, M2[%s]=%i atoms.\n", m1.MaskString(), m1.Nselected(), m2.MaskString(), m2.Nselected()); return Analysis::ERR; } } } else { AtomMask mask1( maskexp ); maskexp = analyzeArgs.GetStringKey("mask2"); if (maskexp.empty()) { mprinterr("Error: 'mask2' must be specified if 'mask1' is.\n"); return Analysis::ERR; } AtomMask mask2( maskexp ); if ( analyzeParm->SetupIntegerMask( mask1 ) ) return Analysis::ERR; if ( analyzeParm->SetupIntegerMask( mask2 ) ) return Analysis::ERR; mask1.MaskInfo(); mask2.MaskInfo(); if (mask1.None() || mask2.None()) { mprinterr("Error: One or both masks are empty.\n"); return Analysis::ERR; } if (mask1.Nselected() != mask2.Nselected()) { mprinterr("Error: # atoms in mask 1 not equal to # atoms in mask 2.\n"); return Analysis::ERR; } for (int idx = 0; idx != mask1.Nselected(); idx++) atompairStack_.push_back( std::pair<int,int>( mask1[idx], mask2[idx] ) ); } if ( atompairStack_.empty() ) { mprinterr("Error: No atom pairs found (use 'maskp' or 'mask1'/'mask2' keywords.)\n"); return Analysis::ERR; } } // Set up data sets Dimension Xdim; if (type_ == FLUCT) { if (setname.empty()) setname = setup.DSL().GenerateDefaultName("FLUCT"); MetaData md(setname, "rmsX"); OutSets_.resize( 4, 0 ); OutSets_[RMSX] = setup.DSL().AddSet( DataSet::DOUBLE, md ); md.SetAspect("rmsY"); OutSets_[RMSY] = setup.DSL().AddSet( DataSet::DOUBLE, md ); md.SetAspect("rmsZ"); OutSets_[RMSZ] = setup.DSL().AddSet( DataSet::DOUBLE, md ); md.SetAspect("rms"); OutSets_[RMS] = setup.DSL().AddSet( DataSet::DOUBLE, md ); Xdim = Dimension(1, 1, "Atom_no."); } else if (type_ == DISPLACE) { if (setname.empty()) setname = setup.DSL().GenerateDefaultName("DISPL"); MetaData md(setname, "displX"); OutSets_.resize( 3, 0 ); OutSets_[RMSX] = setup.DSL().AddSet( DataSet::DOUBLE, md ); md.SetAspect("displY"); OutSets_[RMSY] = setup.DSL().AddSet( DataSet::DOUBLE, md ); md.SetAspect("displZ"); OutSets_[RMSZ] = setup.DSL().AddSet( DataSet::DOUBLE, md ); Xdim = Dimension(1, 1, "Atom_no."); } else if (type_ == EIGENVAL) { if (setname.empty()) setname = setup.DSL().GenerateDefaultName("XEVAL"); MetaData md(setname, "Frac"); OutSets_.resize( 3, 0 ); OutSets_[0] = setup.DSL().AddSet( DataSet::DOUBLE, md ); md.SetAspect("Cumulative"); OutSets_[1] = setup.DSL().AddSet( DataSet::DOUBLE, md ); md.SetAspect("Eigenval"); OutSets_[2] = setup.DSL().AddSet( DataSet::DOUBLE, md ); Xdim = Dimension( 1, 1, "Mode" ); } else if (type_ == RMSIP) { if (setname.empty()) setname = setup.DSL().GenerateDefaultName("RMSIP"); OutSets_.push_back( setup.DSL().AddSet( DataSet::DOUBLE, setname ) ); if (dataout != 0) dataout->ProcessArgs("noxcol"); OutSets_[0]->SetupFormat() = TextFormat(TextFormat::GDOUBLE); OutSets_[0]->SetLegend( modinfo_->Meta().Legend() + "_X_" + modinfo2_->Meta().Legend() ); } for (std::vector<DataSet*>::const_iterator set = OutSets_.begin(); set != OutSets_.end(); ++set) { if (*set == 0) return Analysis::ERR; if (dataout != 0) dataout->AddDataSet( *set ); (*set)->SetDim(Dimension::X, Xdim); } // Status mprintf(" ANALYZE MODES: Calculating %s using modes from %s", analysisTypeString[type_], modinfo_->legend()); if ( type_ != TRAJ ) { if (type_ != EIGENVAL) mprintf(", modes %i to %i", beg_+1, end_); if (outfile_ != 0) mprintf("\n\tResults are written to %s\n", outfile_->Filename().full()); else if (dataout != 0) mprintf("\n\tResults are written to '%s'\n", dataout->DataFilename().full()); if (type_ != EIGENVAL && type_ != RMSIP) { if (bose_) mprintf("\tBose statistics used.\n"); else mprintf("\tBoltzmann statistics used.\n"); if (calcAll_) mprintf("\tEigenvectors associated with zero or negative eigenvalues will be used.\n"); else mprintf("\tEigenvectors associated with zero or negative eigenvalues will be skipped.\n"); } if (type_ == DISPLACE) mprintf("\tFactor for displacement: %f\n", factor_); if (type_ == CORR) { mprintf("\tUsing the following atom pairs:"); for (modestack_it apair = atompairStack_.begin(); apair != atompairStack_.end(); ++apair) mprintf(" (%i,%i)", apair->first+1, apair->second+1 ); mprintf("\n"); } if (type_ == RMSIP) mprintf("\tRMSIP calculated to modes in %s\n", modinfo2_->legend()); } else { mprintf("\n\tCreating trajectory for mode %i\n" "\tWriting to trajectory %s\n" "\tPC range: %f to %f\n" "\tScaling factor: %f\n", tMode_, trajout_.Traj().Filename().full(), pcmin_, pcmax_, factor_); } return Analysis::OK; }
/** Set up variable with value. In this case allow any amount of whitespace, * so re-tokenize the original argument line (minus the command). */ CpptrajState::RetType Control_Set::SetupControl(CpptrajState& State, ArgList& argIn, Varray& CurrentVars) { ArgList remaining = argIn.RemainingArgs(); size_t pos0 = remaining.ArgLineStr().find_first_of("="); if (pos0 == std::string::npos) { mprinterr("Error: Expected <var>=<value>\n"); return CpptrajState::ERR; } size_t pos1 = pos0; bool append = false; if (pos0 > 0 && remaining.ArgLineStr()[pos0-1] == '+') { pos0--; append = true; } std::string variable = NoWhitespace( remaining.ArgLineStr().substr(0, pos0) ); if (variable.empty()) { mprinterr("Error: No variable name.\n"); return CpptrajState::ERR; } ArgList equals( NoLeadingWhitespace(remaining.ArgLineStr().substr(pos1+1)) ); std::string value; if (equals.Contains("inmask")) { AtomMask mask( equals.GetStringKey("inmask") ); Topology* top = State.DSL().GetTopByIndex( equals ); if (top == 0) return CpptrajState::ERR; if (top->SetupIntegerMask( mask )) return CpptrajState::ERR; if (equals.hasKey("atoms")) value = integerToString( mask.Nselected() ); else if (equals.hasKey("residues")) { int curRes = -1; int nres = 0; for (AtomMask::const_iterator at = mask.begin(); at != mask.end(); ++at) { int res = (*top)[*at].ResNum(); if (res != curRes) { nres++; curRes = res; } } value = integerToString( nres ); } else if (equals.hasKey("molecules")) { int curMol = -1; int nmol = 0; for (AtomMask::const_iterator at = mask.begin(); at != mask.end(); ++at) { int mol = (*top)[*at].MolNum(); if (mol != curMol) { nmol++; curMol = mol; } } value = integerToString( nmol ); } else { mprinterr("Error: Expected 'atoms', 'residues', or 'molecules'.\n"); return CpptrajState::ERR; } } else if (equals.hasKey("trajinframes")) { value = integerToString(State.InputTrajList().MaxFrames()); } else value = equals.ArgLineStr(); if (append) CurrentVars.AppendVariable( "$" + variable, value ); else CurrentVars.UpdateVariable( "$" + variable, value ); mprintf("\tVariable '%s' set to '%s'\n", variable.c_str(), value.c_str()); for (int iarg = 0; iarg < argIn.Nargs(); iarg++) argIn.MarkArg( iarg ); return CpptrajState::OK; }
/** Set up each mask/integer loop. */ int ControlBlock_For::SetupBlock(CpptrajState& State, ArgList& argIn) { mprintf(" Setting up 'for' loop.\n"); Vars_.clear(); Topology* currentTop = 0; static const char* TypeStr[] = { "ATOMS ", "RESIDUES ", "MOLECULES ", "MOL_FIRST_RES ", "MOL_LAST_RES " }; static const char* OpStr[] = {"+=", "-=", "<", ">"}; description_.assign("for ("); int MaxIterations = -1; int iarg = 0; while (iarg < argIn.Nargs()) { // Advance to next unmarked argument. while (iarg < argIn.Nargs() && argIn.Marked(iarg)) iarg++; if (iarg == argIn.Nargs()) break; // Determine 'for' type ForType ftype = UNKNOWN; bool isMaskFor = true; int argToMark = iarg; if ( argIn[iarg] == "atoms" ) ftype = ATOMS; else if ( argIn[iarg] == "residues" ) ftype = RESIDUES; else if ( argIn[iarg] == "molecules" ) ftype = MOLECULES; else if ( argIn[iarg] == "molfirstres" ) ftype = MOLFIRSTRES; else if ( argIn[iarg] == "mollastres" ) ftype = MOLLASTRES; else if ( argIn[iarg].find(";") != std::string::npos ) { isMaskFor = false; ftype = INTEGER; } // If type is still unknown, check for list. if (ftype == UNKNOWN) { if (iarg+1 < argIn.Nargs() && argIn[iarg+1] == "in") { ftype = LIST; isMaskFor = false; argToMark = iarg+1; } } // Exit if type could not be determined. if (ftype == UNKNOWN) { mprinterr("Error: for loop type not specfied.\n"); return 1; } argIn.MarkArg(argToMark); Vars_.push_back( LoopVar() ); LoopVar& MH = Vars_.back(); int Niterations = -1; // Set up for specific type if (description_ != "for (") description_.append(", "); // ------------------------------------------- if (isMaskFor) { // {atoms|residues|molecules} <var> inmask <mask> [TOP KEYWORDS] if (argIn[iarg+2] != "inmask") { mprinterr("Error: Expected 'inmask', got %s\n", argIn[iarg+2].c_str()); return 1; } AtomMask currentMask; if (currentMask.SetMaskString( argIn.GetStringKey("inmask") )) return 1; MH.varType_ = ftype; Topology* top = State.DSL().GetTopByIndex( argIn ); if (top != 0) currentTop = top; if (currentTop == 0) return 1; MH.varname_ = argIn.GetStringNext(); if (MH.varname_.empty()) { mprinterr("Error: 'for inmask': missing variable name.\n"); return 1; } MH.varname_ = "$" + MH.varname_; // Set up mask if (currentTop->SetupIntegerMask( currentMask )) return 1; currentMask.MaskInfo(); if (currentMask.None()) return 1; // Set up indices if (MH.varType_ == ATOMS) MH.Idxs_ = currentMask.Selected(); else if (MH.varType_ == RESIDUES) { int curRes = -1; for (AtomMask::const_iterator at = currentMask.begin(); at != currentMask.end(); ++at) { int res = (*currentTop)[*at].ResNum(); if (res != curRes) { MH.Idxs_.push_back( res ); curRes = res; } } } else if (MH.varType_ == MOLECULES || MH.varType_ == MOLFIRSTRES || MH.varType_ == MOLLASTRES) { int curMol = -1; for (AtomMask::const_iterator at = currentMask.begin(); at != currentMask.end(); ++at) { int mol = (*currentTop)[*at].MolNum(); if (mol != curMol) { if (MH.varType_ == MOLECULES) MH.Idxs_.push_back( mol ); else { int res; if (MH.varType_ == MOLFIRSTRES) res = (*currentTop)[ currentTop->Mol( mol ).BeginAtom() ].ResNum(); else // MOLLASTRES res = (*currentTop)[ currentTop->Mol( mol ).EndAtom()-1 ].ResNum(); MH.Idxs_.push_back( res ); } curMol = mol; } } } Niterations = (int)MH.Idxs_.size(); description_.append(std::string(TypeStr[MH.varType_]) + MH.varname_ + " inmask " + currentMask.MaskExpression()); // ------------------------------------------- } else if (ftype == INTEGER) { // [<var>=<start>;[<var><OP><end>;]<var><OP>[<value>]] MH.varType_ = ftype; ArgList varArg( argIn[iarg], ";" ); if (varArg.Nargs() < 2 || varArg.Nargs() > 3) { mprinterr("Error: Malformed 'for' loop variable.\n" "Error: Expected '[<var>=<start>;[<var><OP><end>;]<var><OP>[<value>]]'\n" "Error: Got '%s'\n", argIn[iarg].c_str()); return 1; } // First argument: <var>=<start> ArgList startArg( varArg[0], "=" ); if (startArg.Nargs() != 2) { mprinterr("Error: Malformed 'start' argument.\n" "Error: Expected <var>=<start>, got '%s'\n", varArg[0].c_str()); return 1; } MH.varname_ = startArg[0]; if (!validInteger(startArg[1])) { // TODO allow variables mprinterr("Error: Start argument must be an integer.\n"); return 1; } else MH.start_ = convertToInteger(startArg[1]); // Second argument: <var><OP><end> size_t pos0 = MH.varname_.size(); size_t pos1 = pos0 + 1; MH.endOp_ = NO_OP; int iargIdx = 1; if (varArg.Nargs() == 3) { iargIdx = 2; if ( varArg[1][pos0] == '<' ) MH.endOp_ = LESS_THAN; else if (varArg[1][pos0] == '>') MH.endOp_ = GREATER_THAN; if (MH.endOp_ == NO_OP) { mprinterr("Error: Unrecognized end op: '%s'\n", varArg[1].substr(pos0, pos1-pos0).c_str()); return 1; } std::string endStr = varArg[1].substr(pos1); if (!validInteger(endStr)) { // TODO allow variables mprinterr("Error: End argument must be an integer.\n"); return 1; } else MH.end_ = convertToInteger(endStr); } // Third argument: <var><OP>[<value>] pos1 = pos0 + 2; MH.incOp_ = NO_OP; bool needValue = false; if ( varArg[iargIdx][pos0] == '+' ) { if (varArg[iargIdx][pos0+1] == '+') { MH.incOp_ = INCREMENT; MH.inc_ = 1; } else if (varArg[iargIdx][pos0+1] == '=') { MH.incOp_ = INCREMENT; needValue = true; } } else if ( varArg[iargIdx][pos0] == '-' ) { if (varArg[iargIdx][pos0+1] == '-' ) { MH.incOp_ = DECREMENT; MH.inc_ = 1; } else if (varArg[iargIdx][pos0+1] == '=') { MH.incOp_ = DECREMENT; needValue = true; } } if (MH.incOp_ == NO_OP) { mprinterr("Error: Unrecognized increment op: '%s'\n", varArg[iargIdx].substr(pos0, pos1-pos0).c_str()); return 1; } if (needValue) { std::string incStr = varArg[iargIdx].substr(pos1); if (!validInteger(incStr)) { mprinterr("Error: increment value is not a valid integer.\n"); return 1; } MH.inc_ = convertToInteger(incStr); if (MH.inc_ < 1) { mprinterr("Error: Extra '-' detected in increment.\n"); return 1; } } // Description MH.varname_ = "$" + MH.varname_; std::string sval = integerToString(MH.start_); description_.append("(" + MH.varname_ + "=" + sval + "; "); std::string eval; if (iargIdx == 2) { // End argument present eval = integerToString(MH.end_); description_.append(MH.varname_ + std::string(OpStr[MH.endOp_]) + eval + "; "); // Check end > start for increment, start > end for decrement int maxval, minval; if (MH.incOp_ == INCREMENT) { if (MH.start_ >= MH.end_) { mprinterr("Error: start must be less than end for increment.\n"); return 1; } minval = MH.start_; maxval = MH.end_; } else { if (MH.end_ >= MH.start_) { mprinterr("Error: end must be less than start for decrement.\n"); return 1; } minval = MH.end_; maxval = MH.start_; } // Figure out number of iterations Niterations = (maxval - minval) / MH.inc_; if (((maxval-minval) % MH.inc_) > 0) Niterations++; } description_.append( MH.varname_ + std::string(OpStr[MH.incOp_]) + integerToString(MH.inc_) + ")" ); // If decrementing just negate value if (MH.incOp_ == DECREMENT) MH.inc_ = -MH.inc_; // DEBUG //mprintf("DEBUG: start=%i endOp=%i end=%i incOp=%i val=%i startArg=%s endArg=%s\n", // MH.start_, (int)MH.endOp_, MH.end_, (int)MH.incOp_, MH.inc_, // MH.startArg_.c_str(), MH.endArg_.c_str()); // ------------------------------------------- } else if (ftype == LIST) { // <var> in <string0>[,<string1>...] MH.varType_ = ftype; // Variable name MH.varname_ = argIn.GetStringNext(); if (MH.varname_.empty()) { mprinterr("Error: 'for in': missing variable name.\n"); return 1; } MH.varname_ = "$" + MH.varname_; // Comma-separated list of strings std::string listArg = argIn.GetStringNext(); if (listArg.empty()) { mprinterr("Error: 'for in': missing comma-separated list of strings.\n"); return 1; } ArgList list(listArg, ","); if (list.Nargs() < 1) { mprinterr("Error: Could not parse '%s' for 'for in'\n", listArg.c_str()); return 1; } for (int il = 0; il != list.Nargs(); il++) { // Check if file name expansion should occur if (list[il].find_first_of("*?") != std::string::npos) { File::NameArray files = File::ExpandToFilenames( list[il] ); for (File::NameArray::const_iterator fn = files.begin(); fn != files.end(); ++fn) MH.List_.push_back( fn->Full() ); } else MH.List_.push_back( list[il] ); } Niterations = (int)MH.List_.size(); // Description description_.append( MH.varname_ + " in " + listArg ); } // Check number of values if (MaxIterations == -1) MaxIterations = Niterations; else if (Niterations != -1 && Niterations != MaxIterations) { mprintf("Warning: # iterations %i != previous # iterations %i\n", Niterations, MaxIterations); MaxIterations = std::min(Niterations, MaxIterations); } } mprintf("\tLoop will execute for %i iterations.\n", MaxIterations); if (MaxIterations < 1) { mprinterr("Error: Loop has less than 1 iteration.\n"); return 1; } description_.append(") do"); return 0; }
// Analysis_Matrix::Setup() Analysis::RetType Analysis_Matrix::Setup(ArgList& analyzeArgs, AnalysisSetup& setup, int debugIn) { #ifdef NO_MATHLIB mprinterr("Error: Compiled without LAPACK routines.\n"); return Analysis::ERR; #else // Get matrix name std::string mname = analyzeArgs.GetStringNext(); if (mname.empty()) { mprinterr("Error: Missing matrix name (first argument).\n"); return Analysis::ERR; } // Find matrix in DataSetList. matrix_ = (DataSet_2D*)setup.DSL().FindSetOfType( mname, DataSet::MATRIX_DBL ); if (matrix_ == 0) matrix_ = (DataSet_2D*)setup.DSL().FindSetOfType( mname, DataSet::MATRIX_FLT ); if (matrix_ == 0) { mprinterr("Error: Could not find matrix named %s\n",mname.c_str()); return Analysis::ERR; } // Check that matrix is symmetric (half-matrix incl. diagonal). if (matrix_->MatrixKind() != DataSet_2D::HALF) { mprinterr("Error: Only works for symmetric matrices (i.e. no mask2)\n"); return Analysis::ERR; } // nmwiz flag nmwizopt_ = analyzeArgs.hasKey("nmwiz"); if (nmwizopt_) { nmwizvecs_ = analyzeArgs.getKeyInt("nmwizvecs", 20); if (nmwizvecs_ < 1) { mprinterr("Error: nmwizvecs must be >= 1\n"); return Analysis::ERR; } nmwizfile_ = setup.DFL().AddCpptrajFile(analyzeArgs.GetStringKey("nmwizfile"), "NMwiz output", DataFileList::TEXT, true); Topology* parmIn = setup.DSL().GetTopology( analyzeArgs); // TODO: Include with matrix if (parmIn == 0) { mprinterr("Error: nmwiz: No topology specified.\n"); return Analysis::ERR; } AtomMask nmwizMask( analyzeArgs.GetStringKey("nmwizmask") ); if (parmIn->SetupIntegerMask( nmwizMask )) return Analysis::ERR; nmwizMask.MaskInfo(); Topology* nparm = parmIn->partialModifyStateByMask( nmwizMask ); if (nparm == 0) return Analysis::ERR; nmwizParm_ = *nparm; delete nparm; nmwizParm_.Brief("nmwiz topology"); } // Filenames DataFile* outfile = setup.DFL().AddDataFile( analyzeArgs.GetStringKey("out"), analyzeArgs); // Thermo flag thermopt_ = analyzeArgs.hasKey("thermo"); if (thermopt_) { outthermo_ = setup.DFL().AddCpptrajFile(analyzeArgs.GetStringKey("outthermo"), "'thermo' output", DataFileList::TEXT, true); if (outthermo_ == 0) return Analysis::ERR; } thermo_temp_ = analyzeArgs.getKeyDouble("temp", 298.15); if (thermopt_ && matrix_->Meta().ScalarType() != MetaData::MWCOVAR) { mprinterr("Error: Parameter 'thermo' only works for mass-weighted covariance matrix ('mwcovar').\n"); return Analysis::ERR; } // Number of eigenvectors; allow "0" only in case of 'thermo'. -1 means 'All' nevec_ = analyzeArgs.getKeyInt("vecs",-1); if (nevec_ == 0 && !thermopt_) { mprintf("Warning: # of eigenvectors specified is 0 and 'thermo' not specified.\n"); mprintf("Warning: Specify # eigenvectors with 'vecs <#>'. Setting to All.\n"); nevec_ = -1; } // Reduce flag reduce_ = analyzeArgs.hasKey("reduce"); // Set up DataSet_Modes. Set Modes DataSet type to be same as input matrix. MetaData md( analyzeArgs.GetStringKey("name") ); md.SetScalarType( matrix_->Meta().ScalarType() ); modes_ = (DataSet_Modes*)setup.DSL().AddSet( DataSet::MODES, md, "Modes" ); if (modes_==0) return Analysis::ERR; if (outfile != 0) outfile->AddDataSet( modes_ ); // Print Status mprintf(" DIAGMATRIX: Diagonalizing matrix %s",matrix_->legend()); if (outfile != 0) mprintf(" and writing modes to %s", outfile->DataFilename().full()); if (nevec_ > 0) mprintf("\n\tCalculating %i eigenvectors.\n", nevec_); else if (nevec_ == 0) mprintf("\n\tNot calculating eigenvectors.\n"); else mprintf("\n\tCalculating all eigenvectors.\n"); if (thermopt_) mprintf("\tCalculating thermodynamic data at %.2f K, output to %s\n", thermo_temp_, outthermo_->Filename().full()); if (nmwizopt_) mprintf("\tWriting %i modes to NMWiz file %s", nmwizvecs_, nmwizfile_->Filename().full()); if (nevec_>0 && reduce_) mprintf("\tEigenvectors will be reduced\n"); mprintf("\tStoring modes with name: %s\n", modes_->Meta().Name().c_str()); return Analysis::OK; #endif }
/** 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; }