// Action_Center::Init() Action::RetType Action_Center::Init(ArgList& actionArgs, ActionInit& init, int debugIn) { // Get keywords useMass_ = actionArgs.hasKey("mass"); ReferenceFrame refFrm = init.DSL().GetReferenceFrame( actionArgs ); if (refFrm.error()) return Action::ERR; // Determine center mode. if (!refFrm.empty()) centerMode_ = REF; else if (actionArgs.hasKey("origin")) centerMode_ = ORIGIN; else if (actionArgs.hasKey("point")) { centerMode_ = POINT; refCenter_[0] = actionArgs.getNextDouble(0.0); refCenter_[1] = actionArgs.getNextDouble(0.0); refCenter_[2] = actionArgs.getNextDouble(0.0); } else centerMode_ = BOXCTR; // Get Masks Mask_.SetMaskString( actionArgs.GetMaskNext() ); // Get reference mask if reference specified. AtomMask refMask; if (centerMode_ == REF) { std::string rMaskExpr = actionArgs.GetMaskNext(); if (rMaskExpr.empty()) rMaskExpr = Mask_.MaskExpression(); refMask.SetMaskString( rMaskExpr ); if (refFrm.Parm().SetupIntegerMask( refMask, refFrm.Coord() )) return Action::ERR; // Get center of mask in reference if (useMass_) refCenter_ = refFrm.Coord().VCenterOfMass( refMask ); else refCenter_ = refFrm.Coord().VGeometricCenter( refMask ); } mprintf(" CENTER: Centering coordinates using"); if (useMass_) mprintf(" center of mass"); else mprintf(" geometric center"); mprintf(" of atoms in mask (%s) to\n", Mask_.MaskString()); switch (centerMode_) { case ORIGIN: mprintf("\tcoordinate origin.\n"); break; case BOXCTR: mprintf("\tbox center.\n"); break; case REF: mprintf("\tcenter of mask (%s) in reference '%s'.\n", refMask.MaskString(), refFrm.refName()); break; case POINT: mprintf("\tpoint (%g, %g, %g).\n", refCenter_[0], refCenter_[1], refCenter_[2]); break; } return Action::OK; }
// Action_Radial::Init() Action::RetType Action_Radial::Init(ArgList& actionArgs, ActionInit& init, int debugIn) { debug_ = debugIn; // Get Keywords image_.InitImaging( !(actionArgs.hasKey("noimage")) ); std::string outfilename = actionArgs.GetStringKey("out"); // Default particle density (mols/Ang^3) for water based on 1.0 g/mL density_ = actionArgs.getKeyDouble("density",0.033456); if (actionArgs.hasKey("center1")) rmode_ = CENTER1; else if (actionArgs.hasKey("center2")) rmode_ = CENTER2; else if (actionArgs.hasKey("nointramol")) rmode_ = NO_INTRAMOL; else rmode_ = NORMAL; useVolume_ = actionArgs.hasKey("volume"); DataFile* intrdfFile = init.DFL().AddDataFile(actionArgs.GetStringKey("intrdf")); DataFile* rawrdfFile = init.DFL().AddDataFile(actionArgs.GetStringKey("rawrdf")); spacing_ = actionArgs.getNextDouble(-1.0); if (spacing_ < 0) { mprinterr("Error: Radial: No spacing argument or arg < 0.\n"); Help(); return Action::ERR; } double maximum = actionArgs.getNextDouble(-1.0); if (maximum < 0) { mprinterr("Error: Radial: No maximum argument or arg < 0.\n"); Help(); return Action::ERR; } // Store max^2, distances^2 greater than max^2 do not need to be // binned and therefore do not need a sqrt calc. maximum2_ = maximum * maximum; // Get First Mask std::string mask1 = actionArgs.GetMaskNext(); if (mask1.empty()) { mprinterr("Error: Radial: No mask given.\n"); return Action::ERR; } Mask1_.SetMaskString(mask1); // Check for second mask - if none specified use first mask std::string mask2 = actionArgs.GetMaskNext(); if (!mask2.empty()) Mask2_.SetMaskString(mask2); else Mask2_.SetMaskString(mask1); // If filename not yet specified check for backwards compat. if (outfilename.empty() && actionArgs.Nargs() > 1 && !actionArgs.Marked(1)) outfilename = actionArgs.GetStringNext(); // Set up output dataset. Dset_ = init.DSL().AddSet( DataSet::DOUBLE, actionArgs.GetStringNext(), "g(r)"); if (Dset_ == 0) return RDF_ERR("Could not allocate RDF data set."); DataFile* outfile = init.DFL().AddDataFile(outfilename, actionArgs); if (outfile != 0) outfile->AddDataSet( Dset_ ); // Make default precision a little higher than normal Dset_->SetupFormat().SetFormatWidthPrecision(12,6); // Set DataSet legend from mask strings. Dset_->SetLegend(Mask1_.MaskExpression() + " => " + Mask2_.MaskExpression()); // TODO: Set Yaxis label in DataFile // Calculate number of bins one_over_spacing_ = 1 / spacing_; double temp_numbins = maximum * one_over_spacing_; temp_numbins = ceil(temp_numbins); numBins_ = (int) temp_numbins; // Setup output datafile. Align on bin centers instead of left. // TODO: Use Rdim for binning? Dimension Rdim( spacing_ / 2.0, spacing_, "Distance (Ang)" ); Dset_->SetDim(Dimension::X, Rdim); // Set up output for integral of mask2 if specified. if (intrdfFile != 0) { intrdf_ = init.DSL().AddSet( DataSet::DOUBLE, MetaData(Dset_->Meta().Name(), "int" )); if (intrdf_ == 0) return RDF_ERR("Could not allocate RDF integral data set."); intrdf_->SetupFormat().SetFormatWidthPrecision(12,6); intrdf_->SetLegend("Int[" + Mask2_.MaskExpression() + "]"); intrdf_->SetDim(Dimension::X, Rdim); intrdfFile->AddDataSet( intrdf_ ); } else intrdf_ = 0; // Set up output for raw rdf if (rawrdfFile != 0) { rawrdf_ = init.DSL().AddSet( DataSet::DOUBLE, MetaData(Dset_->Meta().Name(), "raw" )); if (rawrdf_ == 0) return RDF_ERR("Could not allocate raw RDF data set."); rawrdf_->SetupFormat().SetFormatWidthPrecision(12,6); rawrdf_->SetLegend("Raw[" + Dset_->Meta().Legend() + "]"); rawrdf_->SetDim(Dimension::X, Rdim); rawrdfFile->AddDataSet( rawrdf_ ); } else rawrdf_ = 0; // Set up histogram RDF_ = new int[ numBins_ ]; std::fill(RDF_, RDF_ + numBins_, 0); # ifdef _OPENMP // Since RDF is shared by all threads and we cant guarantee that a given // bin in RDF wont be accessed at the same time by the same thread, // each thread needs its own bin space. #pragma omp parallel { if (omp_get_thread_num()==0) numthreads_ = omp_get_num_threads(); } rdf_thread_ = new int*[ numthreads_ ]; for (int i=0; i < numthreads_; i++) { rdf_thread_[i] = new int[ numBins_ ]; std::fill(rdf_thread_[i], rdf_thread_[i] + numBins_, 0); } # endif mprintf(" RADIAL: Calculating RDF for atoms in mask [%s]",Mask1_.MaskString()); if (!mask2.empty()) mprintf(" to atoms in mask [%s]",Mask2_.MaskString()); mprintf("\n"); if (outfile != 0) mprintf(" Output to %s.\n", outfile->DataFilename().full()); if (intrdf_ != 0) mprintf(" Integral of mask2 atoms will be output to %s\n", intrdfFile->DataFilename().full()); if (rawrdf_ != 0) mprintf(" Raw RDF bin values will be output to %s\n", rawrdfFile->DataFilename().full()); if (rmode_==CENTER1) mprintf(" Using center of atoms in mask1.\n"); else if (rmode_==CENTER2) mprintf(" Using center of atoms in mask2.\n"); mprintf(" Histogram max %f, spacing %f, bins %i.\n",maximum, spacing_,numBins_); if (useVolume_) mprintf(" Normalizing based on cell volume.\n"); else mprintf(" Normalizing using particle density of %f molecules/Ang^3.\n",density_); if (!image_.UseImage()) mprintf(" Imaging disabled.\n"); if (numthreads_ > 1) mprintf(" Parallelizing RDF calculation with %i threads.\n",numthreads_); return Action::OK; }
// Action_Diffusion::Init() Action::RetType Action_Diffusion::Init(ArgList& actionArgs, ActionInit& init, int debugIn) { # ifdef MPI trajComm_ = init.TrajComm(); # endif debug_ = debugIn; image_.InitImaging( !(actionArgs.hasKey("noimage")) ); // Determine if this is old syntax or new. if (actionArgs.Nargs() > 2 && actionArgs.ArgIsMask(1) && validDouble(actionArgs[2])) { // Old syntax: <mask> <time per frame> [average] [<prefix>] printIndividual_ = !(actionArgs.hasKey("average")); calcDiffConst_ = false; mprintf("Warning: Deprecated syntax for 'diffusion'. Consider using new syntax:\n"); ShortHelp(); mask_.SetMaskString( actionArgs.GetMaskNext() ); time_ = actionArgs.getNextDouble(1.0); if (CheckTimeArg(time_)) return Action::ERR; std::string outputNameRoot = actionArgs.GetStringNext(); // Default filename: 'diffusion' if (outputNameRoot.empty()) outputNameRoot.assign("diffusion"); // Open output files ArgList oldArgs("prec 8.3 noheader"); DataFile::DataFormatType dft = DataFile::DATAFILE; outputx_ = init.DFL().AddDataFile(outputNameRoot+"_x.xmgr", dft, oldArgs); outputy_ = init.DFL().AddDataFile(outputNameRoot+"_y.xmgr", dft, oldArgs); outputz_ = init.DFL().AddDataFile(outputNameRoot+"_z.xmgr", dft, oldArgs); outputr_ = init.DFL().AddDataFile(outputNameRoot+"_r.xmgr", dft, oldArgs); outputa_ = init.DFL().AddDataFile(outputNameRoot+"_a.xmgr", dft, oldArgs); } else { // New syntax: [{separateout <suffix> | out <filename>}] [time <time per frame>] // [<mask>] [<set name>] [individual] [diffout <filename>] [nocalc] printIndividual_ = actionArgs.hasKey("individual"); calcDiffConst_ = !(actionArgs.hasKey("nocalc")); std::string suffix = actionArgs.GetStringKey("separateout"); std::string outname = actionArgs.GetStringKey("out"); if (!outname.empty() && !suffix.empty()) { mprinterr("Error: Specify either 'out' or 'separateout', not both.\n"); return Action::ERR; } diffout_ = init.DFL().AddDataFile(actionArgs.GetStringKey("diffout")); time_ = actionArgs.getKeyDouble("time", 1.0); if (CheckTimeArg(time_)) return Action::ERR; mask_.SetMaskString( actionArgs.GetMaskNext() ); // Open output files. if (!suffix.empty()) { FileName FName( suffix ); outputx_ = init.DFL().AddDataFile(FName.PrependFileName("x_"), actionArgs); outputy_ = init.DFL().AddDataFile(FName.PrependFileName("y_"), actionArgs); outputz_ = init.DFL().AddDataFile(FName.PrependFileName("z_"), actionArgs); outputr_ = init.DFL().AddDataFile(FName.PrependFileName("r_"), actionArgs); outputa_ = init.DFL().AddDataFile(FName.PrependFileName("a_"), actionArgs); if (diffout_ == 0 && calcDiffConst_) diffout_ = init.DFL().AddDataFile(FName.PrependFileName("diff_"), actionArgs); } else if (!outname.empty()) { outputr_ = init.DFL().AddDataFile( outname, actionArgs ); outputx_ = outputy_ = outputz_ = outputa_ = outputr_; } } if (diffout_ != 0) calcDiffConst_ = true; // Add DataSets dsname_ = actionArgs.GetStringNext(); if (dsname_.empty()) dsname_ = init.DSL().GenerateDefaultName("Diff"); avg_x_ = init.DSL().AddSet(DataSet::DOUBLE, MetaData(dsname_, "X")); avg_y_ = init.DSL().AddSet(DataSet::DOUBLE, MetaData(dsname_, "Y")); avg_z_ = init.DSL().AddSet(DataSet::DOUBLE, MetaData(dsname_, "Z")); avg_r_ = init.DSL().AddSet(DataSet::DOUBLE, MetaData(dsname_, "R")); avg_a_ = init.DSL().AddSet(DataSet::DOUBLE, MetaData(dsname_, "A")); if (avg_x_ == 0 || avg_y_ == 0 || avg_z_ == 0 || avg_r_ == 0 || avg_a_ == 0) return Action::ERR; if (outputr_ != 0) outputr_->AddDataSet( avg_r_ ); if (outputx_ != 0) outputx_->AddDataSet( avg_x_ ); if (outputy_ != 0) outputy_->AddDataSet( avg_y_ ); if (outputz_ != 0) outputz_->AddDataSet( avg_z_ ); if (outputa_ != 0) outputa_->AddDataSet( avg_a_ ); // Set X dim Xdim_ = Dimension(0.0, time_, "Time"); avg_x_->SetDim(Dimension::X, Xdim_); avg_y_->SetDim(Dimension::X, Xdim_); avg_z_->SetDim(Dimension::X, Xdim_); avg_r_->SetDim(Dimension::X, Xdim_); avg_a_->SetDim(Dimension::X, Xdim_); // Add DataSets for diffusion constant calc if (calcDiffConst_) { MetaData::tsType ts = MetaData::NOT_TS; diffConst_ = init.DSL().AddSet(DataSet::DOUBLE, MetaData(dsname_, "D", ts)); diffLabel_ = init.DSL().AddSet(DataSet::STRING, MetaData(dsname_, "Label", ts)); diffSlope_ = init.DSL().AddSet(DataSet::DOUBLE, MetaData(dsname_, "Slope", ts)); diffInter_ = init.DSL().AddSet(DataSet::DOUBLE, MetaData(dsname_, "Intercept", ts)); diffCorrl_ = init.DSL().AddSet(DataSet::DOUBLE, MetaData(dsname_, "Corr", ts)); if (diffConst_ == 0 || diffLabel_ == 0 || diffSlope_ == 0 || diffInter_ == 0 || diffCorrl_ == 0) return Action::ERR; # ifdef MPI // No sync needed since these are not time series diffConst_->SetNeedsSync( false ); diffLabel_->SetNeedsSync( false ); diffSlope_->SetNeedsSync( false ); diffInter_->SetNeedsSync( false ); diffCorrl_->SetNeedsSync( false ); # endif if (diffout_ != 0) { diffout_->AddDataSet( diffConst_ ); diffout_->AddDataSet( diffSlope_ ); diffout_->AddDataSet( diffInter_ ); diffout_->AddDataSet( diffCorrl_ ); diffout_->AddDataSet( diffLabel_ ); } Dimension Ddim( 1, 1, "Set" ); diffConst_->SetDim(Dimension::X, Ddim); diffLabel_->SetDim(Dimension::X, Ddim); diffSlope_->SetDim(Dimension::X, Ddim); diffInter_->SetDim(Dimension::X, Ddim); diffCorrl_->SetDim(Dimension::X, Ddim); } // Save master data set list, needed when printIndividual_ masterDSL_ = init.DslPtr(); mprintf(" DIFFUSION:\n"); mprintf("\tAtom Mask is [%s]\n", mask_.MaskString()); if (printIndividual_) mprintf("\tBoth average and individual diffusion will be calculated.\n"); else mprintf("\tOnly average diffusion will be calculated.\n"); mprintf("\tData set base name: %s\n", avg_x_->Meta().Name().c_str()); if (image_.UseImage()) mprintf("\tCorrections for imaging enabled.\n"); else mprintf("\tCorrections for imaging disabled.\n"); // If one file defined, assume all are. if (outputx_ != 0) { mprintf("\tOutput files:\n" "\t %s: (x) Mean square displacement(s) in the X direction (in Ang.^2).\n" "\t %s: (y) Mean square displacement(s) in the Y direction (in Ang.^2).\n" "\t %s: (z) Mean square displacement(s) in the Z direction (in Ang.^2).\n" "\t %s: (r) Overall mean square displacement(s) (in Ang.^2).\n" "\t %s: (a) Total distance travelled (in Ang.).\n", outputx_->DataFilename().full(), outputy_->DataFilename().full(), outputz_->DataFilename().full(), outputr_->DataFilename().full(), outputa_->DataFilename().full()); } mprintf("\tThe time between frames is %g ps.\n", time_); if (calcDiffConst_) { mprintf("\tCalculating diffusion constants by fitting slope to MSD vs time\n" "\t and multiplying by 10.0/2*N (where N is # of dimensions), units\n" "\t are 1x10^-5 cm^2/s.\n"); if (diffout_ != 0) mprintf("\tDiffusion constant output to '%s'\n", diffout_->DataFilename().full()); else mprintf("\tDiffusion constant output to STDOUT.\n"); } else mprintf("\tTo calculate diffusion constant from mean squared displacement plots,\n" "\t calculate the slope of MSD vs time and multiply by 10.0/2*N (where N\n" "\t is # of dimensions); this will give units of 1x10^-5 cm^2/s.\n"); 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; }
// Action_DihedralScan::Init() Action::RetType Action_DihedralScan::Init(ArgList& actionArgs, ActionInit& init, int debugIn) { if (init.DSL().EnsembleNum() > -1) { mprinterr("Error: DIHEDRALSCAN currently cannot be used in ensemble mode.\n"); return Action::ERR; } TrajectoryFile::TrajFormatType outfmt = TrajectoryFile::UNKNOWN_TRAJ; Topology* outtop = 0; int iseed = -1; debug_ = debugIn; // Get Keywords - first determine mode if (actionArgs.hasKey("random")) mode_ = RANDOM; else if (actionArgs.hasKey("interval")) mode_ = INTERVAL; else mode_ = INTERVAL; // Get residue range resRange_.SetRange(actionArgs.GetStringKey("resrange")); if (!resRange_.Empty()) resRange_.ShiftBy(-1); // User res args start from 1 // Determine which angles to search for dihSearch_.SearchForArgs(actionArgs); // If nothing is enabled, enable all dihSearch_.SearchForAll(); // For interval, get value to shift by, set max rotations and set up // output trajectory. if ( mode_ == INTERVAL ) { interval_ = actionArgs.getNextDouble(60.0); maxVal_ = (int) (360.0 / interval_); if (maxVal_ < 0) maxVal_ = -maxVal_; outfilename_ = actionArgs.GetStringKey("outtraj"); if (!outfilename_.empty()) { outfmt = TrajectoryFile::GetFormatFromArg( actionArgs ); outtop = init.DSL().GetTopology( actionArgs ); if (outtop == 0) { mprinterr("Error: dihedralscan: No topology for output traj.\n"); return Action::ERR; } } } // Get 'random' args if (mode_ == RANDOM) { check_for_clashes_ = actionArgs.hasKey("check"); checkAllResidues_ = actionArgs.hasKey("checkallresidues"); cutoff_ = actionArgs.getKeyDouble("cutoff",0.8); rescutoff_ = actionArgs.getKeyDouble("rescutoff",10.0); backtrack_ = actionArgs.getKeyInt("backtrack",4); increment_ = actionArgs.getKeyInt("increment",1); max_factor_ = actionArgs.getKeyInt("maxfactor",2); // Check validity of args if (cutoff_ < Constants::SMALL) { mprinterr("Error: cutoff too small.\n"); return Action::ERR; } if (rescutoff_ < Constants::SMALL) { mprinterr("Error: rescutoff too small.\n"); return Action::ERR; } if (backtrack_ < 0) { mprinterr("Error: backtrack value must be >= 0\n"); return Action::ERR; } if ( increment_<1 || (360 % increment_)!=0 ) { mprinterr("Error: increment must be a factor of 360.\n"); return Action::ERR; } // Calculate max increment max_increment_ = 360 / increment_; // Seed random number gen iseed = actionArgs.getKeyInt("rseed",-1); RN_.rn_set( iseed ); } // Output file for # of problems DataFile* problemFile = init.DFL().AddDataFile(actionArgs.GetStringKey("out"), actionArgs); // Dataset to store number of problems number_of_problems_ = init.DSL().AddSet(DataSet::INTEGER, actionArgs.GetStringNext(),"Nprob"); if (number_of_problems_==0) return Action::ERR; // Add dataset to data file list if (problemFile != 0) problemFile->AddDataSet(number_of_problems_); mprintf(" DIHEDRALSCAN: Dihedrals in"); if (resRange_.Empty()) mprintf(" all solute residues.\n"); else mprintf(" residue range [%s]\n", resRange_.RangeArg()); switch (mode_) { case RANDOM: 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_); } break; case INTERVAL: mprintf("\tDihedrals will be rotated at intervals of %.2f degrees.\n", interval_); if (!outfilename_.empty()) mprintf("\tCoordinates output to %s, format %s\n",outfilename_.c_str(), TrajectoryFile::FormatString(outfmt)); break; } // Setup output trajectory if (!outfilename_.empty()) { if (outtraj_.InitTrajWrite(outfilename_, ArgList(), outfmt)) return Action::ERR; outframe_ = 0; } // 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_.SeparateInit( false, "*", "", "", 0.8, 1.15, false, init.DFL() )) { mprinterr("Error: Could not set up structure check for DIHEDRALSCAN.\n"); return Action::ERR; } return Action::OK; }