// Action_MultiVector::Setup(); Action::RetType Action_MultiVector::Setup(Topology* currentParm, Topology** parmAddress) { Range actualRange; // If range is empty (i.e. no resrange arg given) look through all // solute residues. if (resRange_.Empty()) actualRange = currentParm->SoluteResidues(); else { // If user range specified, create new range shifted by -1 since internal // resnums start from 0. actualRange = resRange_; actualRange.ShiftBy(-1); } // Exit if no residues specified if (actualRange.Empty()) { mprinterr("Error: No residues specified for %s\n",currentParm->c_str()); return Action::ERR; } // Set default DataSet name if not specified. if (dsetname_.empty()) dsetname_ = masterDSL_->GenerateDefaultName( "MVEC" ); // Search for specified atom names in each residue in the range CrdIdx1_.clear(); CrdIdx2_.clear(); for (Range::const_iterator res = actualRange.begin(); res != actualRange.end(); ++res) { int atom1 = currentParm->FindAtomInResidue( *res, name1_ ); int atom2 = currentParm->FindAtomInResidue( *res, name2_ ); if (atom1 != -1 && atom2 != -1) { MetaData md(dsetname_, atom1+1); md.SetScalarMode( MetaData::M_VECTOR ); if (ired_) md.SetScalarType( MetaData::IREDVEC ); DataSet_Vector* ds = (DataSet_Vector*)masterDSL_->CheckForSet( md ); if (ds == 0) { // Create DataSet ds = (DataSet_Vector*)masterDSL_->AddSet( DataSet::VECTOR, md ); if (ds == 0) return Action::ERR; ds->SetLegend( "v" + currentParm->AtomMaskName(atom1) + "->" + currentParm->AtomMaskName(atom2) ); if (outfile_ != 0) outfile_->AddDataSet( ds ); } data_.push_back( ds ); CrdIdx1_.push_back( atom1 * 3 ); // Pre calc coordinate index CrdIdx2_.push_back( atom2 * 3 ); } else if ((atom1==-1) != (atom2==-1)) { if (atom1==-1) mprintf("Warning: '%s' not found but '%s' found for residue %i.\n", *name1_, *name2_, *res + 1); else // atom2==-1 mprintf("Warning: '%s' not found but '%s' found for residue %i.\n", *name2_, *name1_, *res + 1); } } mprintf("\tSelected %zu vectors.\n", CrdIdx1_.size()); for (std::vector<DataSet_Vector*>::const_iterator it = data_.begin(); it != data_.end(); ++it) mprintf("\t %s\n", (*it)->legend()); return Action::OK; }
// Action_MultiDihedral::Setup(); Action::RetType Action_MultiDihedral::Setup(Topology* currentParm, Topology** parmAddress) { Range actualRange; // If range is empty (i.e. no resrange arg given) look through all // solute residues. if (resRange_.Empty()) actualRange.SetRange(0, currentParm->FinalSoluteRes()); else { // If user range specified, create new range shifted by -1 since internal // resnums start from 0. actualRange = resRange_; actualRange.ShiftBy(-1); } // Exit if no residues specified if (actualRange.Empty()) { mprinterr("Error: multidihedral: No residues specified for %s\n",currentParm->c_str()); return Action::ERR; } // Search for specified dihedrals in each residue in the range if (dihSearch_.FindDihedrals(*currentParm, actualRange)) return Action::ERR; mprintf("\tResRange=[%s]", resRange_.RangeArg()); dihSearch_.PrintTypes(); mprintf(", %i dihedrals.\n", dihSearch_.Ndihedrals()); // Print selected dihedrals, set up DataSets data_.clear(); if (dsetname_.empty()) dsetname_ = masterDSL_->GenerateDefaultName("MDIH"); for (DihedralSearch::mask_it dih = dihSearch_.begin(); dih != dihSearch_.end(); ++dih) { int resNum = (*dih).ResNum() + 1; // See if Dataset already present DataSet* ds = masterDSL_->GetSet(dsetname_, resNum, (*dih).Name()); if (ds == 0) { // Create new DataSet ds = masterDSL_->AddSetIdxAspect( DataSet::DOUBLE, dsetname_, resNum, (*dih).Name()); // Add to outfile if (outfile_ != 0) outfile_->AddSet( ds ); } // TODO: SetScalar if (ds != 0) data_.push_back( ds ); if (debug_ > 0) { mprintf("\tDIH [%s]:", ds->Legend().c_str()); mprintf(" :%i@%i", (*currentParm)[(*dih).A0()].ResNum()+1, (*dih).A0() + 1); mprintf(" :%i@%i", (*currentParm)[(*dih).A1()].ResNum()+1, (*dih).A1() + 1); mprintf(" :%i@%i", (*currentParm)[(*dih).A2()].ResNum()+1, (*dih).A2() + 1); mprintf(" :%i@%i\n", (*currentParm)[(*dih).A3()].ResNum()+1, (*dih).A3() + 1); } } return Action::OK; }
// Exec_PermuteDihedrals::Execute() Exec::RetType Exec_PermuteDihedrals::Execute(CpptrajState& State, ArgList& argIn) { debug_ = State.Debug(); mode_ = INTERVAL; // Get Keywords - first determine mode if (argIn.hasKey("random")) mode_ = RANDOM; else if (argIn.hasKey("interval")) mode_ = INTERVAL; // Get input COORDS set std::string setname = argIn.GetStringKey("crdset"); if (setname.empty()) { mprinterr("Error: Specify COORDS dataset name with 'crdset'.\n"); return CpptrajState::ERR; } DataSet_Coords* CRD = (DataSet_Coords*)State.DSL().FindCoordsSet( setname ); if (CRD == 0) { mprinterr("Error: Could not find COORDS set '%s'\n", setname.c_str()); return CpptrajState::ERR; } mprintf(" PERMUTEDIHEDRALS: Using COORDS '%s'\n", CRD->legend()); // Get residue range Range resRange; resRange.SetRange(argIn.GetStringKey("resrange")); if (!resRange.Empty()) resRange.ShiftBy(-1); // User res args start from 1 mprintf("\tPermutating dihedrals in"); if (resRange.Empty()) mprintf(" all solute residues.\n"); else mprintf(" residue range [%s]\n", resRange.RangeArg()); // Determine which angles to search for DihedralSearch dihSearch; dihSearch.SearchForArgs(argIn); // If nothing is enabled, enable all dihSearch.SearchForAll(); mprintf("\tSearching for types:"); dihSearch.PrintTypes(); mprintf("\n"); // Setup output trajectory outframe_ = 0; std::string outfilename = argIn.GetStringKey("outtraj"); if (!outfilename.empty()) { mprintf("\tCoordinates output to '%s'\n", outfilename.c_str()); Topology* outtop = State.DSL().GetTopology( argIn ); if (outtop == 0) { mprinterr("Error: No topology for output traj.\n"); return CpptrajState::ERR; } // Setup output trajectory FIXME: Correct frames for # of rotations if (outtraj_.PrepareTrajWrite(outfilename, argIn, CRD->TopPtr(), CRD->CoordsInfo(), CRD->Size(), TrajectoryFile::UNKNOWN_TRAJ)) return CpptrajState::ERR; } // Setup output coords outfilename = argIn.GetStringKey("crdout"); if (!outfilename.empty()) { mprintf("\tCoordinates saved to set '%s'\n", outfilename.c_str()); crdout_ = (DataSet_Coords_CRD*)State.DSL().AddSet(DataSet::COORDS, outfilename); if (crdout_ == 0) return CpptrajState::ERR; crdout_->CoordsSetup( CRD->Top(), CRD->CoordsInfo() ); } // Get specific mode options. double interval_in_deg = 60.0; if ( mode_ == INTERVAL ) { interval_in_deg = argIn.getNextDouble(60.0); mprintf("\tDihedrals will be rotated at intervals of %.2f degrees.\n", interval_in_deg); } else if (mode_ == RANDOM) { check_for_clashes_ = argIn.hasKey("check"); checkAllResidues_ = argIn.hasKey("checkallresidues"); cutoff_ = argIn.getKeyDouble("cutoff",0.8); rescutoff_ = argIn.getKeyDouble("rescutoff",10.0); backtrack_ = argIn.getKeyInt("backtrack",4); increment_ = argIn.getKeyInt("increment",1); max_factor_ = argIn.getKeyInt("maxfactor",2); int iseed = argIn.getKeyInt("rseed",-1); // Output file for # of problems DataFile* problemFile = State.DFL().AddDataFile(argIn.GetStringKey("out"), argIn); // Dataset to store number of problems number_of_problems_ = State.DSL().AddSet(DataSet::INTEGER, argIn.GetStringNext(),"Nprob"); if (number_of_problems_==0) return CpptrajState::ERR; // Add dataset to data file list if (problemFile != 0) problemFile->AddDataSet(number_of_problems_); // Check validity of args if (cutoff_ < Constants::SMALL) { mprinterr("Error: cutoff too small.\n"); return CpptrajState::ERR; } if (rescutoff_ < Constants::SMALL) { mprinterr("Error: rescutoff too small.\n"); return CpptrajState::ERR; } if (backtrack_ < 0) { mprinterr("Error: backtrack value must be >= 0\n"); return CpptrajState::ERR; } if ( increment_<1 || (360 % increment_)!=0 ) { mprinterr("Error: increment must be a factor of 360.\n"); return CpptrajState::ERR; } // Calculate max increment max_increment_ = 360 / increment_; // Seed random number gen RN_.rn_set( iseed ); // Print info mprintf("\tDihedrals will be rotated to random values.\n"); if (iseed==-1) mprintf("\tRandom number generator will be seeded using time.\n"); else mprintf("\tRandom number generator will be seeded using %i\n",iseed); if (check_for_clashes_) { mprintf("\tWill attempt to recover from bad steric clashes.\n"); if (checkAllResidues_) mprintf("\tAll residues will be checked.\n"); else mprintf("\tResidues up to the currenly rotating dihedral will be checked.\n"); mprintf("\tAtom cutoff %.2f, residue cutoff %.2f, backtrack = %i\n", cutoff_, rescutoff_, backtrack_); mprintf("\tWhen clashes occur dihedral will be incremented by %i\n",increment_); mprintf("\tMax # attempted rotations = %i times number dihedrals.\n", max_factor_); } // Square cutoffs to compare to dist^2 instead of dist cutoff_ *= cutoff_; rescutoff_ *= rescutoff_; // Increment backtrack by 1 since we need to skip over current res ++backtrack_; // Initialize CheckStructure if (checkStructure_.SetOptions( false, false, false, State.Debug(), "*", "", 0.8, 1.15, 4.0 )) { mprinterr("Error: Could not set up structure check.\n"); return CpptrajState::ERR; } // Set up CheckStructure for this parm (false = nobondcheck) if (checkStructure_.Setup(CRD->Top(), CRD->CoordsInfo().TrajBox())) return CpptrajState::ERR; } // Determine from selected mask atoms which dihedrals will be rotated. PermuteDihedralsType dst; // If range is empty (i.e. no resrange arg given) look through all // solute residues. Range actualRange; if (resRange.Empty()) actualRange = CRD->Top().SoluteResidues(); else actualRange = resRange; // Search for dihedrals if (dihSearch.FindDihedrals(CRD->Top(), actualRange)) return CpptrajState::ERR; // For each found dihedral, set up mask of atoms that will move upon // rotation. Also set up mask of atoms in this residue that will not // move, including atom2. if (debug_>0) mprintf("DEBUG: Dihedrals:\n"); for (DihedralSearch::mask_it dih = dihSearch.begin(); dih != dihSearch.end(); ++dih) { dst.checkAtoms.clear(); // Set mask of atoms that will move during dihedral rotation. dst.Rmask = DihedralSearch::MovingAtoms(CRD->Top(), dih->A1(), dih->A2()); // If randomly rotating angles, check for atoms that are in the same // residue as A1 but will not move. They need to be checked for clashes // since further rotations will not help them. if (mode_ == RANDOM && check_for_clashes_) { CharMask cMask( dst.Rmask.ConvertToCharMask(), dst.Rmask.Nselected() ); int a1res = CRD->Top()[dih->A1()].ResNum(); for (int maskatom = CRD->Top().Res(a1res).FirstAtom(); maskatom < CRD->Top().Res(a1res).LastAtom(); ++maskatom) if (!cMask.AtomInCharMask(maskatom)) dst.checkAtoms.push_back( maskatom ); dst.checkAtoms.push_back(dih->A1()); // TODO: Does this need to be added first? // Since only the second atom and atoms it is bonded to move during // rotation, base the check on the residue of the second atom. dst.resnum = a1res; } dst.atom0 = dih->A0(); // FIXME: This duplicates info dst.atom1 = dih->A1(); dst.atom2 = dih->A2(); dst.atom3 = dih->A3(); BB_dihedrals_.push_back(dst); // DEBUG: List dihedral info. if (debug_ > 0) { mprintf("\t%s-%s-%s-%s\n", CRD->Top().TruncResAtomName(dih->A0()).c_str(), CRD->Top().TruncResAtomName(dih->A1()).c_str(), CRD->Top().TruncResAtomName(dih->A2()).c_str(), CRD->Top().TruncResAtomName(dih->A3()).c_str() ); if (debug_ > 1 && mode_ == RANDOM && check_for_clashes_) { mprintf("\t\tCheckAtoms="); for (std::vector<int>::const_iterator ca = dst.checkAtoms.begin(); ca != dst.checkAtoms.end(); ++ca) mprintf(" %i", *ca + 1); mprintf("\n"); } if (debug_ > 2) { mprintf("\t\t"); dst.Rmask.PrintMaskAtoms("Rmask:"); } } } // Set up simple structure check. First step is coarse; check distances // between a certain atom in each residue (first, COM, CA, some other atom?) // to see if residues are in each others neighborhood. Second step is to // check the atoms in each close residue. if (check_for_clashes_) { ResidueCheckType rct; int res = 0; for (Topology::res_iterator residue = CRD->Top().ResStart(); residue != CRD->Top().ResEnd(); ++residue) { rct.resnum = res++; rct.start = residue->FirstAtom(); rct.stop = residue->LastAtom(); rct.checkatom = rct.start; ResCheck_.push_back(rct); } } // Perform dihedral permute Frame currentFrame = CRD->AllocateFrame(); for (unsigned int set = 0; set != CRD->Size(); set++) { CRD->GetFrame(set, currentFrame); int n_problems = 0; switch (mode_) { case RANDOM: RandomizeAngles(currentFrame, CRD->Top()); // Check the resulting structure n_problems = checkStructure_.CheckOverlaps( currentFrame ); //mprintf("%i\tResulting structure has %i problems.\n",frameNum,n_problems); number_of_problems_->Add(set, &n_problems); if (outtraj_.IsInitialized()) outtraj_.WriteSingle(outframe_++, currentFrame); if (crdout_ != 0) crdout_->AddFrame( currentFrame ); break; case INTERVAL: IntervalAngles(currentFrame, CRD->Top(), interval_in_deg); break; } } if (outtraj_.IsInitialized()) outtraj_.EndTraj(); return CpptrajState::OK; }
void dirSeedsReg2::dirSweep(Datareg2& reg2) { u_int i, j; Range resp; float min, max, t; float gradx; float grad1ya, grad1yb; float grad2ya, grad2yb; int keepflat; int prev; for(i=0; i<reg2.dim[0]-1; i++) { keepflat = 1; prev = -1; for(j=0; j<reg2.dim[1]-1; j++) { resp.MakeEmpty(); // test responsiblity for each face // left if(i == 0) { min = max = reg2.getValue(reg2.index2vert(i,j)); if((t=reg2.getValue(reg2.index2vert(i,j+1))) < min) { min = t; } if(t > max) { max = t; } if(min != max) { resp += Range(min,max); } } else { // never do anything other than on boundary } // right if(i == reg2.dim[0]-2) { // never keep a right boundary seed } else { // never keep a right boundary seed } // general case: bottom edge in middle // cell (i,j) and (i,j-1) share this x-grad gradx = reg2.getValue(reg2.index2vert(i+1,j)) - reg2.getValue(reg2.index2vert(i,j)); // compute y-grad at (i,j) and (i+1,j) grad1ya = reg2.getValue(reg2.index2vert(i,j+1)) - reg2.getValue(reg2.index2vert(i,j)); grad1yb = reg2.getValue(reg2.index2vert(i+1,j+1)) - reg2.getValue(reg2.index2vert(i+1,j)); if(keepflat) { // check to see if gradient has 'turned' // only a seed if gradx & grady disagree in sign // note that 0 gradient is not considered opposite if(sgn(grad1ya) == 0 && sgn(grad1yb) == 0) { // flat cell (in y dim) - continue } else if(sgn(gradx) == -sgn(grad1ya) || sgn(gradx) == -sgn(grad1yb)) { // extreme occurs if y components oppose each other // note that 0 gradient is not considered opposite min = max = reg2.getValue(reg2.index2vert(i,j)); if((t=reg2.getValue(reg2.index2vert(i+1,j))) < min) { min = t; } if(t > max) { max = t; } resp += Range(min,max); keepflat = 0; } } // top if(j == reg2.dim[1]-2) { if(keepflat) { min = max = reg2.getValue(reg2.index2vert(i,j+1)); if((t=reg2.getValue(reg2.index2vert(i+1,j+1))) < min) { min = t; } if(t > max) { max = t; } resp += Range(min,max); } } else { // only consider the top at the boundary if(!keepflat) { gradx = reg2.getValue(reg2.index2vert(i+1,j+1)) - reg2.getValue(reg2.index2vert(i,j+1)); grad2ya = reg2.getValue(reg2.index2vert(i,j+1)) - reg2.getValue(reg2.index2vert(i,j)); grad2yb = reg2.getValue(reg2.index2vert(i+1,j+1)) - reg2.getValue(reg2.index2vert(i+1,j)); if(sgn(gradx) != 0 && (sgn(gradx) == sgn(grad2ya) || sgn(gradx) == sgn(grad2yb))) { keepflat=1; } } else { gradx = reg2.getValue(reg2.index2vert(i+1,j+1)) - reg2.getValue(reg2.index2vert(i,j+1)); grad2ya = reg2.getValue(reg2.index2vert(i,j+1)) - reg2.getValue(reg2.index2vert(i,j)); grad2yb = reg2.getValue(reg2.index2vert(i+1,j+1)) - reg2.getValue(reg2.index2vert(i+1,j)); if(sgn(gradx) == -sgn(grad2ya) || sgn(gradx) == -sgn(grad2yb)) { keepflat=0; } } } if(!resp.Empty()) { if(prev == -1) { if(i!=0) prev = seeds.AddSeed(reg2.index2cell(i,j), resp.MinAll(), resp.MaxAll()); else seeds.AddSeed(reg2.index2cell(i,j), resp.MinAll(), resp.MaxAll()); } else { seeds.AddToRange(prev, resp.MinAll(), resp.MaxAll()); prev = -1; } } else { prev = -1; } } } }
// Preprocess() - build a segment tree for O(log n) queries void regProp2::compSeeds(void) { Datareg2& reg2 = (Datareg2&)data; int i, j; int xdim, ydim; float val[4]; Range* _prop_x, *prop_x; Range prop_y; Range propagated; Range c_prop; Range responsibility, c_respons; Range delay; Range y_comp; float min_x, min_y, max_x, max_y; float min_in, max_in, min4, max4; int nseed; xdim = reg2.dim[0]; ydim = reg2.dim[1]; _prop_x = new Range[ydim]; // proceed through the slices computing seeds nseed=0; // process the k'th slab for(i=0; i<xdim-1; i++) for(j=0; j<ydim-1; j++) { prop_x = &_prop_x[j]; // load the voxel data reg2.getCellValues(i, j, val); min_x = MIN2(val[0], val[3]); max_x = MAX2(val[0], val[3]); min_y = MIN2(val[0], val[1]); max_y = MAX2(val[0], val[1]); // set the incoming values if on a border if(i==0) { prop_x->Set(min_x, max_x); } if(j==0) { prop_y.Set(min_y, max_y); } // merge incoming information y_comp = prop_y.Complement(min_y, max_y); propagated = prop_y + ((*prop_x)-y_comp); // compute complement of incoming ranges min_in = MIN2(min_x, min_y); max_in = MAX2(max_x, max_y); c_prop.Set(min_in,max_in); c_prop -= propagated; // compute responsibility ranges min4 = MIN2(min_in, val[2]); max4 = MAX2(max_in, val[2]); responsibility.Set(min4, max4); responsibility-=c_prop; c_respons = responsibility.Complement(min4, max4); // determine range which can be delayed delay.MakeEmpty(); if(i < xdim-2) delay+=Range(MIN2(val[1], val[2]), MAX2(val[1], val[2])); if(j < ydim-2) delay+=Range(MIN2(val[2], val[3]), MAX2(val[2], val[3])); // test for propagation of entire responsibility range if(responsibility.Empty() || (!delay.Empty() && delay.MinAll() <= responsibility.MinAll() && delay.MaxAll() >= responsibility.MaxAll())) { // propagate first to the next x-slice if(i == xdim-2) { prop_x->MakeEmpty(); } else { prop_x->Set(MIN2(val[1], val[2]), MAX2(val[1], val[2])); *prop_x-=c_respons; } c_respons += *prop_x; // all remaining propagated in y-dir if(j == ydim-2) { prop_y.MakeEmpty(); } else { prop_y.Set(MIN2(val[2], val[3]), MAX2(val[2], val[3])); prop_y-= c_respons; } } else { // can't propagate all responsiblity, cell must be a seed seeds.AddSeed(reg2.index2cell(i,j), responsibility.MinAll(), responsibility.MaxAll()); nseed++; prop_y.MakeEmpty(); prop_x->MakeEmpty(); } } if(verbose) { printf("computed %d seeds\n", nseed); } }
// Exec_DataSetCmd::ModifyPoints() Exec::RetType Exec_DataSetCmd::ModifyPoints(CpptrajState& State, ArgList& argIn, bool drop) { const char* mode; if (drop) mode = "Drop"; else mode = "Kee"; // Keywords std::string name = argIn.GetStringKey("name"); int start = argIn.getKeyInt("start", 0) - 1; int stop = argIn.getKeyInt("stop", -1); int offset = argIn.getKeyInt("offset", -1); Range points; if (start < 0 && stop < 0 && offset < 0) { std::string rangearg = argIn.GetStringKey("range"); if (rangearg.empty()) { mprinterr("Error: Must specify range or start/stop/offset.\n"); return CpptrajState::ERR; } points.SetRange( rangearg ); if (points.Empty()) { mprinterr("Error: Range '%s' is empty.\n", rangearg.c_str()); return CpptrajState::ERR; } mprintf("\t%sping points in range %s\n", mode, rangearg.c_str()); // User args start from 1 points.ShiftBy(-1); } // Get data set to drop/keep points from // Loop over all DataSet arguments std::string ds_arg = argIn.GetStringNext(); while (!ds_arg.empty()) { DataSetList dsl = State.DSL().GetMultipleSets( ds_arg ); for (DataSetList::const_iterator it = dsl.begin(); it != dsl.end(); ++it) { DataSet* DS = *it; if (DS->Size() < 1) { mprinterr("Error: Set '%s' is empty.\n", DS->legend()); return CpptrajState::ERR; } // Restrict to 1D sets for now TODO more types if (DS->Group() != DataSet::SCALAR_1D) { mprinterr("Error: Currently only works for 1D scalar data sets.\n"); return CpptrajState::ERR; } DataSet_1D* ds1 = (DataSet_1D*)DS; // Output data set DataSet* out = 0; if (name.empty()) { // Modifying this set. Create new temporary set. out = State.DSL().Allocate( ds1->Type() ); if (out == 0) return CpptrajState::ERR; *out = *ds1; mprintf("\tOverwriting set '%s'\n", ds1->legend()); } else { // Write to new set MetaData md = ds1->Meta(); md.SetName( name ); out = State.DSL().AddSet(ds1->Type(), md); if (out == 0) return CpptrajState::ERR; mprintf("\tNew set is '%s'\n", out->Meta().PrintName().c_str()); } out->Allocate(DataSet::SizeArray(1, ds1->Size())); if (points.Empty()) { // Drop by start/stop/offset. Set defaults if needed if (start < 0) start = 0; if (stop < 0) stop = ds1->Size(); if (offset < 0) offset = 1; mprintf("\t%sping points from %i to %i, step %i\n", mode, start+1, stop, offset); for (int idx = start; idx < stop; idx += offset) points.AddToRange( idx ); } // TODO check that range values are valid? if (State.Debug() > 0) mprintf("DEBUG: Keeping points:"); Range::const_iterator pt = points.begin(); int idx = 0; int odx = 0; if (drop) { // Drop points for (; idx < (int)ds1->Size(); idx++) { if (pt == points.end()) break; if (*pt != idx) { if (State.Debug() > 0) mprintf(" %i", idx + 1); KeepPoint(ds1, out, idx, odx); } else ++pt; } // Keep all remaining points for (; idx < (int)ds1->Size(); idx++) { if (State.Debug() > 0) mprintf(" %i", idx + 1); KeepPoint(ds1, out, idx, odx); } } else { // Keep points for (; pt != points.end(); pt++) { if (*pt >= (int)ds1->Size()) break; if (State.Debug() > 0) mprintf(" %i", *pt + 1); KeepPoint(ds1, out, *pt, odx); } } if (State.Debug() > 0) mprintf("\n"); if (name.empty()) { // Replace old set with new set State.DSL().RemoveSet( ds1 ); State.DSL().AddSet( out ); } } // END loop over sets ds_arg = argIn.GetStringNext(); } // END loop over set args return CpptrajState::OK; }