Esempio n. 1
0
/** Given an argument with format, DataSet_Name[,min,max,step,bins], check
  * that DataSet_Name exists and is valid. Add the argument to 
  * dimensionArgs and the corresponding dataset to histdata.
  */
int Analysis_Hist::CheckDimension(std::string const& input, DataSetList& DSLin) {
  ArgList arglist;
  // Separate input string by ','
  arglist.SetList(input, ",");
  if (arglist.Nargs()<1) {
    mprinterr("Error: No arguments found in histogram argument: %s\n",input.c_str());
    return 1;
  }

  // First argument should specify dataset name
  if (debug_>0) mprintf("\tHist: Setting up histogram dimension using dataset %s\n",
                       arglist.Command());
  DataSet* dset = DSLin.GetDataSet( arglist[0] );
  if (dset == 0) {
    mprinterr("Error: Dataset %s not found.\n",arglist.Command());
    return 1;
  }

  // For now only 1D scalar data sets can be histogrammed
  if (dset->Group() != DataSet::SCALAR_1D) {
    mprinterr("Error: Cannot histogram data set '%s'\n", dset->legend());
    mprinterr("Error: Currently only 1D scalar data sets can be histogrammed.\n");
    return 1;
  }
  // TODO parse remaining args here, create data structure.
  dimensionArgs_.push_back( arglist );
  histdata_.push_back( (DataSet_1D*)dset );
  return 0;
}
Esempio n. 2
0
// Action_Grid::Init()
Action::RetType Action_Grid::Init(ArgList& actionArgs, ActionInit& init, int debugIn)
{
  debug_ = debugIn;
  nframes_ = 0;
  // Get output filename
  std::string filename = actionArgs.GetStringKey("out");
  // Get grid options
  grid_ = GridInit( "GRID", actionArgs, init.DSL() );
  if (grid_ == 0) return Action::ERR;
# ifdef MPI
  if (ParallelGridInit(init.TrajComm(), grid_)) return Action::ERR;
# endif
  // Get extra options
  max_ = actionArgs.getKeyDouble("max", 0.80);
  madura_ = actionArgs.getKeyDouble("madura", 0);
  smooth_ = actionArgs.getKeyDouble("smoothdensity", 0);
  invert_ = actionArgs.hasKey("invert");
  pdbfile_ = init.DFL().AddCpptrajFile(actionArgs.GetStringKey("pdb"),"Grid PDB",DataFileList::PDB,true);
  density_ = actionArgs.getKeyDouble("density",0.033456);
  if (actionArgs.hasKey("normframe")) normalize_ = TO_FRAME;
  else if (actionArgs.hasKey("normdensity")) normalize_ = TO_DENSITY;
  else normalize_ = NONE;
  if (normalize_ != NONE && (smooth_ > 0.0 || madura_ > 0.0)) {
    mprinterr("Error: Normalize options are not compatible with smoothdensity/madura options.\n");
    init.DSL().RemoveSet( grid_ );
    return Action::ERR;
  }
  // Get mask
  std::string maskexpr = actionArgs.GetMaskNext();
  if (maskexpr.empty()) {
    mprinterr("Error: GRID: No mask specified.\n");
    init.DSL().RemoveSet( grid_ );
    return Action::ERR;
  }
  mask_.SetMaskString(maskexpr);

  // Setup output file
  // For backwards compat., if no 'out' assume next string is filename
  if (filename.empty() && actionArgs.Nargs() > 1 && !actionArgs.Marked(1))
    filename = actionArgs.GetStringNext();
  DataFile* outfile = init.DFL().AddDataFile(filename, actionArgs);
  if (outfile != 0) outfile->AddDataSet((DataSet*)grid_);

  // Info
  mprintf("    GRID:\n");
  GridInfo( *grid_ );
  if (outfile != 0) mprintf("\tGrid will be printed to file %s\n", outfile->DataFilename().full());
  mprintf("\tGrid data set: '%s'\n", grid_->legend());
  mprintf("\tMask expression: [%s]\n",mask_.MaskString());
  if (pdbfile_ != 0)
      mprintf("\tPseudo-PDB will be printed to %s\n", pdbfile_->Filename().full());
  if (normalize_ == TO_FRAME)
    mprintf("\tGrid will be normalized by number of frames.\n");
  else if (normalize_ == TO_DENSITY)
    mprintf("\tGrid will be normalized to a density of %g molecules/Ang^3.\n", density_);
  // TODO: print extra options

  return Action::OK;
}
Esempio n. 3
0
/// \return 1 if problem with or not a Tinker Atom/Title line.
static inline int SetNatomAndTitle(ArgList& lineIn, int& natom, std::string& title) {
  if (lineIn.Nargs() < 1) return 1;
  natom = lineIn.getNextInteger( -1 );
  if (natom < 1) return 1;
  std::string nextWord = lineIn.GetStringNext();
//if (nextWord.empty()) return 1;
  while (!nextWord.empty()) {
    if (!title.empty()) title += ' ';
    title.append( nextWord );
    nextWord = lineIn.GetStringNext();
  }
  return 0;
}
Esempio n. 4
0
static inline bool IsAtomLine(ArgList& lineIn) {
  for (int i = 0; i < lineIn.Nargs(); i++) {
    std::string item = lineIn.GetStringNext();
    if (i == 0 || i >= 5) {
      try {
        convertToInteger( item );
      }
      catch (std::runtime_error e) {
        return false;
      }
    } else if (i >= 2 && i < 5) {
      try {
        convertToDouble( item );
      }
      catch (std::runtime_error e) {
        return false;
      }
    }
  }
  return true;
}
Esempio n. 5
0
/** Given an ArgList containing name,[min,max,step,bins,col,N], set up a 
  * coordinate with that name and parameters min, max, step, bins.
  * If '*' or not specified, a default value will be set.
  * \return 1 if error occurs, 0 otherwise.
  */
int Analysis_Hist::setupDimension(ArgList &arglist, DataSet_1D const& dset, size_t& offset) {
  bool minArg = false;
  bool maxArg = false;
  bool stepArg = false;
  bool binsArg = false; 

  if (debug_>1)
    arglist.PrintList();

  // Set up dimension name
  // NOTE: arglist[0] should be same as dset name from CheckDimension 
  std::string const& dLabel = arglist[0];

  // Cycle through coordinate arguments. Any argument left blank will be 
  // assigned a default value later.
  double dMin = 0.0;
  double dMax = 0.0;
  double dStep = 0.0;
  int dBins = -1;
  for (int i = 1; i < arglist.Nargs(); i++) {
    if (debug_>1) mprintf("DEBUG: setupCoord: Token %i (%s)\n", i, arglist[i].c_str());
    // '*' means default explicitly requested
    if (arglist[i] == "*") continue;
    switch (i) {
      case 1 : dMin  = convertToDouble( arglist[i]); minArg = true; break;
      case 2 : dMax  = convertToDouble( arglist[i]); maxArg = true; break;
      case 3 : dStep = convertToDouble( arglist[i]); stepArg = true; break;
      case 4 : dBins = convertToInteger(arglist[i]); binsArg = true; break;
    }
  }

  // If no min arg and no default min arg, get min from dataset
  if (!minArg) {
    if (!minArgSet_) 
      dMin = dset.Min();
    else
      dMin = default_min_;
  }
  // If no max arg and no default max arg, get max from dataset
  if (!maxArg) {
    if (!maxArgSet_)
      dMax = dset.Max();
    else
      dMax = default_max_;
  }
  // If bins/step not specified, use default
  if (!binsArg)
    dBins = default_bins_;
  if (!stepArg)
    dStep = default_step_;

  // Calculate dimension from given args.
  HistBin dim;
  if (dim.CalcBinsOrStep( dMin, dMax, dStep, dBins, dLabel )) {
    mprinterr("Error: Could not set up histogram dimension '%s'\n", dLabel.c_str());
    return 1;
  }
  dim.PrintHistBin();
  dimensions_.push_back( dim );

  // Recalculate offsets for all dimensions starting at farthest coord. This
  // follows row major ordering.
  size_t last_offset = 1UL; // For checking overflow.
  offset = 1UL;
  binOffsets_.resize( dimensions_.size() );
  OffType::iterator bOff = binOffsets_.begin();
  for (HdimType::const_iterator rd = dimensions_.begin();
                                rd != dimensions_.end(); ++rd, ++bOff)
  {
    if (debug_>0) mprintf("\tHistogram: %s offset is %zu\n", rd->label(), offset);
    *bOff = (long int)offset;
    offset *= rd->Bins();
    // Check for overflow.
    if ( offset < last_offset ) {
      mprinterr("Error: Too many bins for histogram. Try reducing the number of bins and/or\n"
                "Error:   the number of dimensions.\n");
      return 1;
    }
    last_offset = offset;
  }
  // offset should now be equal to the total number of bins across all dimensions
  if (debug_>0) mprintf("\tHistogram: Total Bins = %zu\n",offset);

  return 0;
}
Esempio n. 6
0
// 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;
}
Esempio n. 7
0
/** Replace all variables in given ArgList with their values. */
ArgList VariableArray::ReplaceVariables(ArgList const& argIn, DataSetList const& DSL, int debug)
{
  if (debug > 0) mprintf("DEBUG: Before variable replacement:  [%s]\n", argIn.ArgLine());
  ArgList modCmd = argIn;
  for (int n = 0; n < modCmd.Nargs(); n++) {
    size_t pos = modCmd[n].find("$");
    while (pos != std::string::npos) {
      // Argument is/contains a variable. Find first non-alphanumeric char
      size_t len = 1;
      for (size_t pos1 = pos+1; pos1 < modCmd[n].size(); pos1++, len++)
        if (!isalnum(modCmd[n][pos1])) break;
      std::string var_in_arg = modCmd[n].substr(pos, len);
      // See if variable occurs in CurrentVars_
      Varray::const_iterator vp = CurrentVars_.begin();
      for (; vp != CurrentVars_.end(); ++vp)
        if (vp->first == var_in_arg) break;
      // If found replace with value from CurrentVars_
      if (vp != CurrentVars_.end()) {
        if (debug > 0)
          mprintf("DEBUG: Replaced variable '%s' with value '%s'\n",
                  var_in_arg.c_str(), vp->second.c_str());
        std::string arg = modCmd[n];
        arg.replace(pos, vp->first.size(), vp->second);
        modCmd.ChangeArg(n, arg);
      } else {
        // Not found in CurrentVars_; see if this is a DataSet.
        for (size_t pos1 = pos+len; pos1 < modCmd[n].size(); pos1++, len++)
          if (!isalnum(modCmd[n][pos1]) &&
              modCmd[n][pos1] != '[' &&
              modCmd[n][pos1] != ':' &&
              modCmd[n][pos1] != ']' &&
              modCmd[n][pos1] != '_' &&
              modCmd[n][pos1] != '-' &&
              modCmd[n][pos1] != '%')
            break;
        var_in_arg = modCmd[n].substr(pos+1, len-1);
        DataSet* ds = DSL.GetDataSet( var_in_arg );
        if (ds == 0) {
          mprinterr("Error: Unrecognized variable in command: %s\n", var_in_arg.c_str());
          return ArgList();
        } else {
          if (ds->Type() != DataSet::STRING && ds->Group() != DataSet::SCALAR_1D) {
            mprinterr("Error: Only 1D data sets supported.\n");
            return ArgList();
          }
          if (ds->Size() < 1) {
            mprinterr("Error: Set is empty.\n");
            return ArgList();
          }
          if (ds->Size() > 1)
            mprintf("Warning: Only using first value.\n");
          std::string value;
          if (ds->Type() == DataSet::STRING)
            value = (*((DataSet_string*)ds))[0];
          else
            value = doubleToString(((DataSet_1D*)ds)->Dval(0));
          if (debug > 0)
            mprintf("DEBUG: Replaced variable '$%s' with value '%s' from DataSet '%s'\n",
                    var_in_arg.c_str(), value.c_str(), ds->legend());
          std::string arg = modCmd[n];
          arg.replace(pos, var_in_arg.size()+1, value);
          modCmd.ChangeArg(n, arg);
        }
      }
      pos = modCmd[n].find("$");
    } // END loop over this argument
  }
  return modCmd;
}
Esempio n. 8
0
/** 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;
}
Esempio n. 9
0
/** 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;
}
Esempio n. 10
0
// 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;
}
Esempio n. 11
0
// Action_Watershell::Init()
Action::RetType Action_Watershell::Init(ArgList& actionArgs, ActionInit& init, int debugIn)
{
  image_.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
  std::string solventmaskexpr = actionArgs.GetMaskNext();
  if (!solventmaskexpr.empty())
    solventMask_.SetMaskString( solventmaskexpr );
  // For backwards compat., if no 'out' assume next string is file name 
  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_);
  }
# ifndef CUDA
# ifdef _OPENMP
  // Determine number of parallel threads
  int numthreads = 0;
#pragma omp parallel
{
  if (omp_get_thread_num()==0)
    numthreads = omp_get_num_threads();
}
  shellStatus_thread_.resize( numthreads );
# endif
# endif
  mprintf("    WATERSHELL:");
  if (outfile != 0) mprintf(" Output to %s", outfile->DataFilename().full());
  mprintf("\n");
  if (!image_.UseImage())
    mprintf("\tImaging is disabled.\n");
  mprintf("\tThe first shell will contain solvent < %.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 (solventMask_.MaskStringSet())
    mprintf("\tSolvent atoms will be specified by [%s]\n", solventMask_.MaskString());
#ifdef CUDA
  mprintf("\tDistance calculations will be GPU-accelerated with CUDA.\n");
#else
# ifdef _OPENMP
  if (shellStatus_thread_.size() > 1)
    mprintf("\tParallelizing calculation with %zu threads.\n", shellStatus_thread_.size());
# endif
#endif
  mprintf("\t# solvent molecules in 'lower' shell stored in set '%s'\n", lower_->legend());
  mprintf("\t# solvent molecules in 'upper' shell stored in set '%s'\n", upper_->legend());

  // Pre-square upper and lower cutoffs
  lowerCutoff_ *= lowerCutoff_;
  upperCutoff_ *= upperCutoff_;

  return Action::OK;
}
Esempio n. 12
0
// DataIO_Std::Read_1D()
int DataIO_Std::Read_1D(std::string const& fname, 
                        DataSetList& datasetlist, std::string const& dsname)
{
  ArgList labels;
  bool hasLabels = false;
  // Buffer file
  BufferedLine buffer;
  if (buffer.OpenFileRead( fname )) return 1;

  // Read the first line. Attempt to determine the number of columns
  const char* linebuffer = buffer.Line();
  if (linebuffer == 0) return 1;
  int ntoken = buffer.TokenizeLine( SEPARATORS );
  if ( ntoken == 0 ) {
    mprinterr("Error: No columns detected in %s\n", buffer.Filename().full());
    return 1;
  }

  // Try to skip past any comments. If line begins with a '#', assume it
  // contains labels. 
  bool isCommentLine = true;
  const char* ptr = linebuffer;
  while (isCommentLine) {
    // Skip past any whitespace
    while ( *ptr != '\0' && isspace(*ptr) ) ++ptr;
    // Assume these are column labels until proven otherwise.
    if (*ptr == '#') {
      labels.SetList(ptr+1, SEPARATORS );
      if (!labels.empty()) {
        hasLabels = true;
        // If first label is Frame assume it is the index column
        if (labels[0] == "Frame" && indexcol_ == -1)
          indexcol_ = 0;
      }
      linebuffer = buffer.Line();
      ptr = linebuffer;
      if (ptr == 0) {
        mprinterr("Error: No data found in file.\n");
        return 1;
      }
    } else 
      // Not a recognized comment character, assume data.
      isCommentLine = false;
  }
  // Special case: check if labels are '#F1   F2 <name> [nframes <#>]'. If so, assume
  // this is a cluster matrix file.
  if ((labels.Nargs() == 3 || labels.Nargs() == 5) && labels[0] == "F1" && labels[1] == "F2")
  {
    mprintf("Warning: Header format '#F1 F2 <name>' detected, assuming cluster pairwise matrix.\n");
    return IS_ASCII_CMATRIX;
  }
  // Column user args start from 1
  if (indexcol_ > -1)
    mprintf("\tUsing column %i as index column.\n", indexcol_ + 1);

  // Should be at first data line. Tokenize the line.
  ntoken = buffer.TokenizeLine( SEPARATORS );
  // If # of data columns does not match # labels, clear labels.
  if ( !labels.empty() && ntoken != labels.Nargs() ) {
    labels.ClearList();
    hasLabels = false;
  }
  // Index column checks
  if (indexcol_ != -1 ) {
    if (indexcol_ >= ntoken) {
      mprinterr("Error: Specified index column %i is out of range (%i columns).\n",
                indexcol_+1, ntoken);
      return 1;
    }
    if (!onlycols_.Empty() && !onlycols_.InRange(indexcol_)) {
      mprinterr("Error: Index column %i specified, but not in given column range '%s'\n",
                indexcol_+1, onlycols_.RangeArg());
      return 1;
    }
  }

  // Determine the type of data stored in each column. Assume numbers should
  // be read with double precision.
  MetaData md( dsname );
  DataSetList::DataListType inputSets;
  unsigned int nsets = 0;
  for (int col = 0; col != ntoken; ++col) {
    std::string token( buffer.NextToken() );
    if (!onlycols_.Empty() && !onlycols_.InRange( col )) {
      mprintf("\tSkipping column %i\n", col+1);
      inputSets.push_back( 0 );
    } else {
      md.SetIdx( col+1 );
      if (hasLabels) md.SetLegend( labels[col] );
      if ( col == indexcol_ ) {
        // Always save the index column as floating point
        inputSets.push_back( new DataSet_double() );
      } else if (validInteger(token)) {
        // Integer number
        inputSets.push_back( datasetlist.Allocate(DataSet::INTEGER) );
      } else if (validDouble(token)) {
        // Floating point number
        inputSets.push_back( new DataSet_double() );
      } else {
        // Assume string. Not allowed for index column.
        if (col == indexcol_) {
          mprintf("Warning: '%s' index column %i has string values. No indices will be read.\n", 
                    buffer.Filename().full(), indexcol_+1);
          indexcol_ = -1;
        }
        inputSets.push_back( new DataSet_string() );
      }
      inputSets.back()->SetMeta( md );
      nsets++;
    }
  }
  if (inputSets.empty() || nsets == 0) {
    mprinterr("Error: No data detected.\n");
    return 1;
  }

  // Read in data
  while (linebuffer != 0) {
    if ( buffer.TokenizeLine( SEPARATORS ) != ntoken ) {
      PrintColumnError(buffer.LineNumber());
      break;
    }
    // Convert data in columns
    for (int i = 0; i < ntoken; ++i) {
      const char* token = buffer.NextToken();
      if (inputSets[i] != 0) {
        if (inputSets[i]->Type() == DataSet::DOUBLE)
          ((DataSet_double*)inputSets[i])->AddElement( atof(token) );
        else if (inputSets[i]->Type() == DataSet::INTEGER)
          ((DataSet_integer*)inputSets[i])->AddElement( atoi(token) );
        else
          ((DataSet_string*)inputSets[i])->AddElement( std::string(token) );
      }
    }
    //Ndata++;
    linebuffer = buffer.Line();
  }
  buffer.CloseFile();
   mprintf("\tDataFile %s has %i columns, %i lines.\n", buffer.Filename().full(),
           ntoken, buffer.LineNumber());

  // Create list containing only data sets.
  DataSetList::DataListType mySets;
  DataSet_double* Xptr = 0;
  for (int idx = 0; idx != (int)inputSets.size(); idx++) {
    if (inputSets[idx] != 0) {
      if ( idx != indexcol_ )
        mySets.push_back( inputSets[idx] );
      else
        Xptr = (DataSet_double*)inputSets[idx];
    }
  }
  mprintf("\tRead %zu data sets.\n", mySets.size());
  std::string Xlabel;
  if (indexcol_ != -1 && indexcol_ < labels.Nargs())
    Xlabel = labels[indexcol_];
  if (Xptr == 0)
    datasetlist.AddOrAppendSets(Xlabel, DataSetList::Darray(), mySets);
  else {
    datasetlist.AddOrAppendSets(Xlabel, Xptr->Data(), mySets);
    delete Xptr;
  }

  return 0;
}