// Action_Distance::init() Action::RetType Action_Distance::Init(ArgList& actionArgs, TopologyList* PFL, FrameList* FL, DataSetList* DSL, DataFileList* DFL, int debugIn) { // Get Keywords InitImaging( !(actionArgs.hasKey("noimage")) ); useMass_ = !(actionArgs.hasKey("geom")); DataFile* outfile = DFL->AddDataFile( actionArgs.GetStringKey("out"), actionArgs ); DataSet::scalarType stype = DataSet::UNDEFINED; std::string stypename = actionArgs.GetStringKey("type"); if ( stypename == "hbond" ) stype = DataSet::HBOND; else if (stypename == "noe" ) stype = DataSet::NOE; // TODO: Grab bound and boundh // Get Masks std::string mask1 = actionArgs.GetMaskNext(); std::string mask2 = actionArgs.GetMaskNext(); if (mask1.empty() || mask2.empty()) { mprinterr("Error: distance: Requires 2 masks\n"); return Action::ERR; } Mask1_.SetMaskString(mask1); Mask2_.SetMaskString(mask2); // Dataset to store distances dist_ = DSL->AddSet(DataSet::DOUBLE, actionArgs.GetStringNext(), "Dis"); if (dist_==0) return Action::ERR; dist_->SetScalar( DataSet::M_DISTANCE, stype ); // Add dataset to data file if (outfile != 0) outfile->AddSet( dist_ ); mprintf(" DISTANCE: %s to %s",Mask1_.MaskString(), Mask2_.MaskString()); if (!UseImage()) mprintf(", non-imaged"); if (useMass_) mprintf(", center of mass"); else mprintf(", geometric center"); mprintf(".\n"); return Action::OK; }
Action::RetType Action_DNAionTracker::Init(ArgList& actionArgs, TopologyList* PFL, DataSetList* DSL, DataFileList* DFL, int debugIn) { // Get keywords DataFile* outfile = DFL->AddDataFile(actionArgs.GetStringKey("out"), actionArgs); poffset_ = actionArgs.getKeyDouble("poffset", 5.0); InitImaging( !actionArgs.hasKey("noimage") ); if (actionArgs.hasKey("shortest")) bintype_ = SHORTEST; else if (actionArgs.hasKey("counttopcone")) bintype_ = TOPCONE; else if (actionArgs.hasKey("countbottomcone")) bintype_ = BOTTOMCONE; else if (actionArgs.hasKey("count")) bintype_ = COUNT; // Get masks - 4 must be specified std::string m1 = actionArgs.GetMaskNext(); std::string m2 = actionArgs.GetMaskNext(); std::string m3 = actionArgs.GetMaskNext(); std::string m4 = actionArgs.GetMaskNext(); if (m1.empty() || m2.empty() || m3.empty() || m4.empty()) { mprinterr("Error: dnaiontracker requires 4 masks.\n"); return Action::ERR; } p1_.SetMaskString(m1); p2_.SetMaskString(m2); base_.SetMaskString(m3); ions_.SetMaskString(m4); // Add dataset to dataset list (and datafile list if filename specified) distance_ = DSL->AddSet(DataSet::DOUBLE, MetaData(actionArgs.GetStringNext(), MetaData::M_DISTANCE), "DNAion"); if (distance_==0) return Action::ERR; if (outfile != 0) outfile->AddDataSet( distance_ ); // INFO mprintf(" DNAIONTRACKER: Data representing the "); switch (bintype_) { case COUNT : mprintf("count within the cone will be\n"); break; case SHORTEST: mprintf("shortest distance to a phosphate or base centroid will be\n"); break; case TOPCONE: mprintf("count in the top half of the cone (and sort-of bound) will be\n"); break; case BOTTOMCONE: mprintf("count in the bottom half of the cone will be\n"); break; } mprintf(" saved to array named %s\n", distance_->legend()); mprintf(" Perpendicular offset for cone is %5.2f angstroms\n", poffset_); if (!UseImage()) mprintf(" Imaging has been disabled\n"); mprintf("\tPhosphate1 Mask [%s]\n", p1_.MaskString()); mprintf("\tPhosphate2 Mask [%s]\n", p2_.MaskString()); mprintf("\tBase Mask [%s]\n", base_.MaskString()); mprintf("\tIons Mask [%s]\n", ions_.MaskString()); if (outfile != 0) mprintf("\tData will be printed to a file named %s\n", outfile->DataFilename().full()); return Action::OK; }
// Action_LIE::init() Action::RetType Action_LIE::Init(ArgList& actionArgs, ActionInit& init, int debugIn) { // Always use imaged distances InitImaging(true); double cut; // Get Keywords doelec_ = !(actionArgs.hasKey("noelec")); dovdw_ = !(actionArgs.hasKey("novdw")); DataFile* datafile = init.DFL().AddDataFile(actionArgs.GetStringKey("out"), actionArgs); dielc_ = actionArgs.getKeyDouble("diel", 1.0); cut = actionArgs.getKeyDouble("cutvdw", 12.0); cut2vdw_ = cut * cut; // store square of cut for computational efficiency cut = actionArgs.getKeyDouble("cutelec", 12.0); cut2elec_ = cut * cut; // store square of cut for computational efficiency onecut2_ = 1 / cut2elec_; bool has_mask2 = false; if (!doelec_ && !dovdw_) { mprinterr("Error: LIE: Cannot skip both ELEC and VDW calcs\n"); return Action::ERR; } // Get Masks Mask1_.SetMaskString( actionArgs.GetMaskNext() ); std::string refmask = actionArgs.GetMaskNext(); if (!refmask.empty()) { Mask2_.SetMaskString(refmask); has_mask2 = true; } else { Mask2_ = Mask1_; Mask2_.InvertMaskExpression(); } // Get data set name std::string ds_name = actionArgs.GetStringNext(); if (ds_name.empty()) ds_name = init.DSL().GenerateDefaultName("LIE"); // Datasets if (doelec_) { elec_ = init.DSL().AddSet(DataSet::DOUBLE, MetaData(ds_name, "EELEC")); if (elec_ == 0) return Action::ERR; if (datafile != 0) datafile->AddDataSet(elec_); } if (dovdw_) { vdw_ = init.DSL().AddSet(DataSet::DOUBLE, MetaData(ds_name, "EVDW")); if (vdw_ == 0) return Action::ERR; if (datafile != 0) datafile->AddDataSet(vdw_); } mprintf(" LIE: Ligand mask is %s. Surroundings are ", Mask1_.MaskString()); if (!has_mask2) mprintf("everything else. "); else mprintf("atoms in mask %s. ", Mask2_.MaskString()); mprintf("Cutoff is %.3lf Ang. ", cut); if (!doelec_) mprintf("Skipping Electrostatic Calc. "); if (!dovdw_) mprintf("Skipping VDW Calc. "); mprintf("\n"); return Action::OK; }
// Action_Watershell::init() Action::RetType Action_Watershell::Init(ArgList& actionArgs, ActionInit& init, int debugIn) { InitImaging( !actionArgs.hasKey("noimage") ); // Get keywords std::string filename = actionArgs.GetStringKey("out"); lowerCutoff_ = actionArgs.getKeyDouble("lower", 3.4); upperCutoff_ = actionArgs.getKeyDouble("upper", 5.0); // Get solute mask std::string maskexpr = actionArgs.GetMaskNext(); if (maskexpr.empty()) { mprinterr("Error: Solute mask must be specified.\n"); return Action::ERR; } soluteMask_.SetMaskString( maskexpr ); // Check for solvent mask solventmaskexpr_ = actionArgs.GetMaskNext(); // For backwards compat., if no 'out' assume next string is if (filename.empty() && actionArgs.Nargs() > 2 && !actionArgs.Marked(2)) filename = actionArgs.GetStringNext(); DataFile* outfile = init.DFL().AddDataFile( filename, actionArgs ); // Set up datasets std::string dsname = actionArgs.GetStringNext(); if (dsname.empty()) dsname = init.DSL().GenerateDefaultName("WS"); lower_ = init.DSL().AddSet(DataSet::INTEGER, MetaData(dsname, "lower")); upper_ = init.DSL().AddSet(DataSet::INTEGER, MetaData(dsname, "upper")); if (lower_ == 0 || upper_ == 0) return Action::ERR; if (outfile != 0) { outfile->AddDataSet(lower_); outfile->AddDataSet(upper_); } # ifdef _OPENMP // Determine number of parallel threads #pragma omp parallel { if (omp_get_thread_num()==0) numthreads_ = omp_get_num_threads(); } # endif mprintf(" WATERSHELL:"); if (outfile != 0) mprintf(" Output to %s", outfile->DataFilename().full()); mprintf("\n"); if (!UseImage()) mprintf("\tImaging is disabled.\n"); mprintf("\tThe first shell will contain water < %.3f angstroms from\n", lowerCutoff_); mprintf("\t the solute; the second shell < %.3f angstroms...\n", upperCutoff_); mprintf("\tSolute atoms will be specified by [%s]\n",soluteMask_.MaskString()); if (!solventmaskexpr_.empty()) { mprintf("\tSolvent atoms will be specified by [%s]\n", solventmaskexpr_.c_str()); solventMask_.SetMaskString( solventmaskexpr_ ); } if (numthreads_ > 1) mprintf("\tParallelizing calculation with %i threads.\n", numthreads_); mprintf("\t# waters in 'lower' shell stored in set '%s'\n", lower_->legend()); mprintf("\t# waters in 'upper' shell stored in set '%s'\n", upper_->legend()); // Pre-square upper and lower cutoffs lowerCutoff_ *= lowerCutoff_; upperCutoff_ *= upperCutoff_; return Action::OK; }
// Action_Spam::init() Action::RetType Action_Spam::Init(ArgList& actionArgs, TopologyList* PFL, DataSetList* DSL, DataFileList* DFL, int debugIn) { // Always use imaged distances InitImaging(true); // This is needed everywhere in this function scope FileName filename; // See if we're doing pure water. If so, we don't need a peak file purewater_ = actionArgs.hasKey("purewater"); if (purewater_) { // We still need the cutoff double cut = actionArgs.getKeyDouble("cut", 12.0); cut2_ = cut * cut; doublecut_ = 2 * cut; onecut2_ = 1 / cut2_; // See if we write to a data file datafile_ = actionArgs.GetStringKey("out"); // Generate the data set name, and hold onto the master data set list std::string ds_name = actionArgs.GetStringKey("name"); if (ds_name.empty()) ds_name = myDSL_.GenerateDefaultName("SPAM"); // We only have one data set averaging over every water. Add it here myDSL_.AddSet(DataSet::DOUBLE, ds_name, NULL); solvname_ = actionArgs.GetStringKey("solv"); if (solvname_.empty()) solvname_ = std::string("WAT"); }else { // Get the file name with the peaks defined in it filename.SetFileName( actionArgs.GetStringNext() ); if (filename.empty() || !File::Exists(filename)) { mprinterr("Spam: Error: Peak file [%s] does not exist!\n", filename.full()); return Action::ERR; } // Get the remaining optional arguments solvname_ = actionArgs.GetStringKey("solv"); if (solvname_.empty()) solvname_ = std::string("WAT"); reorder_ = actionArgs.hasKey("reorder"); bulk_ = actionArgs.getKeyDouble("bulk", 0.0); double cut = actionArgs.getKeyDouble("cut", 12.0); cut2_ = cut * cut; doublecut_ = 2 * cut; onecut2_ = 1 / cut2_; std::string infoname = actionArgs.GetStringKey("info"); if (infoname.empty()) infoname = std::string("spam.info"); infofile_ = DFL->AddCpptrajFile(infoname, "SPAM info"); if (infofile_ == 0) return Action::ERR; // The default maskstr is the Oxygen atom of the solvent summaryfile_ = actionArgs.GetStringKey("summary"); // Divide site size by 2 to make it half the edge length (or radius) site_size_ = actionArgs.getKeyDouble("site_size", 2.5) / 2.0; sphere_ = actionArgs.hasKey("sphere"); // If it's a sphere, square the radius to compare with if (sphere_) site_size_ *= site_size_; datafile_ = actionArgs.GetStringKey("out"); std::string ds_name = actionArgs.GetStringKey("name"); if (ds_name.empty()) ds_name = myDSL_.GenerateDefaultName("SPAM"); // Parse through the peaks file and extract the peaks CpptrajFile peakfile; if (peakfile.OpenRead(filename)) { mprinterr("SPAM: Error: Could not open %s for reading!\n", filename.full()); return Action::ERR; } std::string line = peakfile.GetLine(); int npeaks = 0; while (!line.empty()) { if (sscanf(line.c_str(), "%d", &npeaks) != 1) { line = peakfile.GetLine(); continue; } line = peakfile.GetLine(); break; } while (!line.empty()) { double x, y, z, dens; if (sscanf(line.c_str(), "C %lg %lg %lg %lg", &x, &y, &z, &dens) != 4) { line = peakfile.GetLine(); continue; } line = peakfile.GetLine(); peaks_.push_back(Vec3(x, y, z)); } peakfile.CloseFile(); // Check that our initial number of peaks matches our parsed peaks. Warn // otherwise if (npeaks != (int)peaks_.size()) mprinterr("SPAM: Warning: %s claims to have %d peaks, but really has %d!\n", filename.full(), npeaks, peaks_.size()); // Now add all of the data sets MetaData md(ds_name); for (int i = 0; i < (int)peaks_.size(); i++) { md.SetAspect( integerToString(i+1) ); // TODO: Should this be Idx? if (myDSL_.AddSet(DataSet::DOUBLE, md) == 0) return Action::ERR; // Add a new list of integers to keep track of omitted frames std::vector<int> vec; peakFrameData_.push_back(vec); } } // Print info now if (purewater_) { mprintf("SPAM: Calculating bulk value for pure solvent\n"); if (!datafile_.empty()) mprintf("SPAM: Printing solvent energies to %s\n", datafile_.c_str()); mprintf("SPAM: Using a %.2f Angstrom non-bonded cutoff with shifted EEL.\n", sqrt(cut2_)); if (reorder_) mprintf("SPAM: Warning: Re-ordering makes no sense for pure solvent.\n"); if (!summaryfile_.empty()) mprintf("SPAM: Printing solvent SPAM summary to %s\n", summaryfile_.c_str()); }else { mprintf("SPAM: Solvent [%s] density peaks taken from %s.\n", solvname_.c_str(), filename.base()); mprintf("SPAM: %d density peaks will be analyzed from %s.\n", peaks_.size(), filename.base()); mprintf("SPAM: Occupation information printed to %s.\n", infofile_->Filename().full()); mprintf("SPAM: Sites are "); if (sphere_) mprintf("spheres with diameter %.3lf\n", site_size_); else mprintf("boxes with edge length %.3lf\n", site_size_); if (reorder_) { mprintf("SPAM: Re-ordering trajectory so each site always has "); mprintf("the same water molecule.\n"); } if (summaryfile_.empty() && datafile_.empty()) { if (!reorder_) { mprinterr("SPAM: Error: Not re-ordering trajectory or calculating energies. "); mprinterr("Nothing to do!\n"); return Action::ERR; } mprintf("SPAM: Not calculating any SPAM energies\n"); }else { mprintf("SPAM: Using a non-bonded cutoff of %.2lf Ang. with a EEL shifting function.\n", sqrt(cut2_)); mprintf("SPAM: Bulk solvent SPAM energy taken as %.3lf kcal/mol\n", bulk_); } } mprintf("#Citation: Cui, G.; Swails, J.M.; Manas, E.S.; \"SPAM: A Simple Approach\n" "# for Profiling Bound Water Molecules\"\n" "# J. Chem. Theory Comput., 2013, 9 (12), pp 5539–5549.\n"); return Action::OK; }