Пример #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;
}
Пример #2
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;
}
Пример #3
0
// 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;
}
Пример #4
0
/** Given an array of already set up data sets (from e.g. input data files)
  * and optional X values, add the sets to this list if they do not exist
  * or append any existing sets.
  */
int DataSetList::AddOrAppendSets(std::string const& XlabelIn, Darray const& Xvals,
                                 DataListType const& Sets)
{
  if (debug_ > 0)
    mprintf("DEBUG: Calling AddOrAppendSets for %zu sets, %zu X values, Xlabel= %s.\n",
            Sets.size(), Xvals.size(), XlabelIn.c_str());
  if (Sets.empty()) return 0; // No error for now.
  // If no X label assume 'Frame' for backwards compat.
  std::string Xlabel;
  if (XlabelIn.empty())
    Xlabel.assign("Frame");
  else
    Xlabel = XlabelIn;
  Dimension Xdim;
  // First determine if X values increase monotonically with a regular step
  bool isMonotonic = true;
  double xstep = 1.0;
  if (Xvals.size() > 1) {
    xstep = (Xvals.back() - Xvals.front()) / (double)(Xvals.size() - 1);
    for (Darray::const_iterator X = Xvals.begin()+2; X != Xvals.end(); ++X)
      if ((*X - *(X-1)) - xstep > Constants::SMALL) {
        isMonotonic = false;
        break;
      }
    // Set dim even for non-monotonic sets so Label is correct. FIXME is this ok?
    Xdim = Dimension( Xvals.front(), xstep, Xlabel );
  } else
    // No X values. set generic X dim.
    Xdim = Dimension(1.0, 1.0, Xlabel);
  if (debug_ > 0) {
    mprintf("DEBUG: xstep %g xmin %g\n", Xdim.Step(), Xdim.Min());
    if (isMonotonic) mprintf("DEBUG: Xdim is monotonic.\n");
  }
  for (const_iterator ds = Sets.begin(); ds != Sets.end(); ++ds) {
    if (*ds == 0) continue; // TODO: Warn about blanks?
    if (debug_ > 0) mprintf("DEBUG: AddOrAppend set '%s'", (*ds)->legend());
    if (isMonotonic) (*ds)->SetDim(Dimension::X, Xdim);
    DataSet* existingSet = CheckForSet( (*ds)->Meta() );
    if (existingSet == 0) {
      // New set. If set is scalar 1D but X values are not monotonic,
      // convert to XY mesh if necessary.
      if ( !isMonotonic &&
           (*ds)->Group() == DataSet::SCALAR_1D &&
           (*ds)->Type() != DataSet::XYMESH )
      {
        DataSet* xyptr = AddSet( DataSet::XYMESH, (*ds)->Meta() );
        if (xyptr == 0) {
          mprinterr("Error: Could not convert set %s to XY mesh.\n", (*ds)->legend());
          continue; // TODO exit instead?
        }
        if ( (*ds)->Size() != Xvals.size() ) { // Sanity check
          mprinterr("Error: # of X values does not match set %s size.\n", (*ds)->legend());
          continue;
        }
        DataSet_1D const& set = static_cast<DataSet_1D const&>( *(*ds) );
        DataSet_Mesh& xy = static_cast<DataSet_Mesh&>( *xyptr );
        for (unsigned int i = 0; i != set.Size(); i++)
          xy.AddXY( Xvals[i], set.Dval(i) );
        xy.SetDim(Dimension::X, Xdim);
        if (debug_ > 0) mprintf(", New set, converted to XY-MESH\n");
        // Free memory since set has now been converted.
        delete *ds;
      } else { // No conversion. Just add.
        (*ds)->SetDim(Dimension::X, Xdim);
        AddSet( *ds );
        if (debug_ > 0) mprintf(", New set\n");
      }
    } else {
      if (debug_ > 0) mprintf(", appending to existing set\n");
      // Set exists. Try to append this set to existing set.
      bool canAppend = true;
      if ( (*ds)->Group() == DataSet::GENERIC ) {
        // For GENERIC sets, base Type must match. // TODO: Should this logic be in DataSets?
        if ( (*ds)->Type() != existingSet->Type() )
          canAppend = false;
      } else {
        // For non-GENERIC sets, Group must match
        if ( (*ds)->Group() != existingSet->Group() )
          canAppend = false;
      }
      if (!canAppend)
        mprinterr("Error: Cannot append set of type %s to set of type %s\n",
                  DataArray[(*ds)->Type()].Description,
                  DataArray[existingSet->Type()].Description);
      // If cannot append or attempt to append fails, rename and add as new set.
      if (!canAppend || existingSet->Append( *ds )) { // TODO Dimension check?
        if (canAppend)
          mprintf("Warning: Append currently not supported for type %s\n",
                  DataArray[existingSet->Type()].Description);
        MetaData md = (*ds)->Meta();
        md.SetName( GenerateDefaultName("X") );
        mprintf("Warning: Renaming %s to %s\n", (*ds)->Meta().PrintName().c_str(),
                md.PrintName().c_str());
        (*ds)->SetMeta( md );
       
        AddSet( *ds );
      } else // Set was appended to existing set; memory can be freed.
        delete *ds;
    }
  } // END loop over input sets
  return 0;
}
Пример #5
0
// DataIO_Std::Read_3D()
int DataIO_Std::Read_3D(std::string const& fname, 
                        DataSetList& datasetlist, std::string const& dsname)
{
  BufferedLine buffer;
  if (buffer.OpenFileRead( fname )) return 1;
  mprintf("\tData will be read as 3D grid: X Y Z Value\n");
  if (binCorners_)
    mprintf("\tAssuming X Y Z are bin corners\n");
  else
    mprintf("\tAssuming X Y Z are bin centers\n");
  const char* ptr = buffer.Line();
  // Check if #counts is present
  if (strncmp(ptr,"#counts",7)==0) {
    mprintf("\tReading grid dimensions.\n");
    unsigned int counts[3];
    sscanf(ptr+7,"%u %u %u", counts, counts+1, counts+2);
    for (int i = 0; i < 3; i++) {
      if (dims_[i] == 0)
        dims_[i] = counts[i];
      else if (dims_[i] != (size_t)counts[i])
        mprintf("Warning: Specified size for dim %i (%zu) differs from size in file (%u)\n",
                i, dims_[i], counts[i]);
    }
    ptr = buffer.Line();
  }
  if (dims_[0] == 0 || dims_[1] == 0 || dims_[2] == 0) {
    mprinterr("Error: 'dims' not specified for 'read3d' and no dims in file\n");
    return 1;
  }
  // Check if #origin is present
  if (strncmp(ptr,"#origin",7)==0) {
    mprintf("\tReading grid origin.\n");
    double oxyz[3];
    sscanf(ptr+7,"%lf %lf %lf", oxyz, oxyz+1, oxyz+2);
    for (int i = 0; i < 3; i++) {
      if (!originSpecified_)
        origin_[i] = oxyz[i];
      else if (origin_[i] != oxyz[i])
        mprintf("Warning: Specified origin for dim %i (%g) differs from origin in file (%g)\n",
                i, origin_[i], oxyz[i]);
    }
    ptr = buffer.Line();
  }
  // Check if #delta is present
  bool nonortho = false;
  Box gridBox;
  if (strncmp(ptr,"#delta",6)==0) {
    mprintf("\tReading grid deltas.\n");
    double dvals[9];
    int ndvals = sscanf(ptr+6,"%lf %lf %lf %lf %lf %lf %lf %lf %lf", dvals,
                        dvals+1, dvals+2, dvals+3, dvals+4, dvals+5,
                        dvals+6, dvals+7, dvals+8);
    if (ndvals == 3) {
      for (int i = 0; i < 3; i++) {
        if (!deltaSpecified_)
          delta_[i] = dvals[i];
        else if (delta_[i] != dvals[i])
          mprintf("Warning: Specified delta for dim %i (%g) differs from delta in file (%g)\n",
                  i, delta_[i], dvals[i]);
      }
    } else {
      nonortho = true;
      dvals[0] *= (double)dims_[0]; dvals[1] *= (double)dims_[0]; dvals[2] *= (double)dims_[0];
      dvals[3] *= (double)dims_[1]; dvals[4] *= (double)dims_[1]; dvals[5] *= (double)dims_[1];
      dvals[6] *= (double)dims_[2]; dvals[7] *= (double)dims_[2]; dvals[8] *= (double)dims_[2];
      gridBox = Box(Matrix_3x3(dvals));
    }
    ptr = buffer.Line();
  }
  // Get or allocate data set
  DataSet::DataType dtype;
  if (prec_ == DOUBLE) {
    dtype = DataSet::GRID_DBL;
    mprintf("\tGrid is double precision.\n");
  } else {
    dtype = DataSet::GRID_FLT;
    mprintf("\tGrid is single precision.\n");
  }
  MetaData md( dsname );
  DataSet_3D* ds = 0;
  DataSet* set = datasetlist.CheckForSet( md );
  if (set == 0) {
    ds = (DataSet_3D*)datasetlist.AddSet(dtype, dsname);
    if (ds == 0) return 1;
    int err = 0;
    if (nonortho)
      err = ds->Allocate_N_O_Box(dims_[0], dims_[1], dims_[2], origin_, gridBox);
    else
      err = ds->Allocate_N_O_D(dims_[0], dims_[1], dims_[2], origin_, delta_);
    if (err != 0) return 1;
  } else {
    mprintf("\tAppending to existing set '%s'\n", set->legend());
    if (set->Group() != DataSet::GRID_3D) {
      mprinterr("Error: Set '%s' is not a grid set, cannot append.\n", set->legend());
      return 1;
    }
    ds = (DataSet_3D*)set;
    // Check that dimensions line up. TODO check origin etc too?
    if (dims_[0] != ds->NX() ||
        dims_[1] != ds->NY() ||
        dims_[2] != ds->NZ())
    {
      mprintf("Warning: Specified grid dimensions (%zu %zu %zu) do not match\n"
              "Warning:   '%s' dimensions (%zu %zu %zu)\n", dims_[0], dims_[1], dims_[2],
              ds->legend(), dims_[0], dims_[1], dims_[2]);
    }
  }
  ds->GridInfo();
  // Determine if an offset is needed
  Vec3 offset(0.0);
  if (binCorners_) {
    // Assume XYZ coords are of bin corners. Need to offset coords by half
    // the voxel size.
    if (!ds->Bin().IsOrthoGrid()) {
      GridBin_Nonortho const& b = static_cast<GridBin_Nonortho const&>( ds->Bin() );
      offset = b.Ucell().TransposeMult(Vec3( 1/(2*(double)ds->NX()),
                                             1/(2*(double)ds->NY()),
                                             1/(2*(double)ds->NZ()) ));
    } else {
      GridBin_Ortho const& b = static_cast<GridBin_Ortho const&>( ds->Bin() );
      offset = Vec3(b.DX()/2, b.DY()/2, b.DZ()/2);
    }
  }
  if (debug_ > 0)
    mprintf("DEBUG: Offset: %E %E %E\n", offset[0], offset[1], offset[2]);
  // Read file
  unsigned int nvals = 0;
  while (ptr != 0) {
    if (ptr[0] != '#') {
      int ntokens = buffer.TokenizeLine( SEPARATORS );
      if (ntokens != 4) {
        mprinterr("Error: Expected 4 columns (X, Y, Z, data), got %i\n", ntokens);
        return 1;
      }
      nvals++;
      double xyzv[4];
      xyzv[0] = atof( buffer.NextToken() );
      xyzv[1] = atof( buffer.NextToken() );
      xyzv[2] = atof( buffer.NextToken() );
      xyzv[3] = atof( buffer.NextToken() );
      size_t ix, iy, iz;
      if ( ds->Bin().Calc(xyzv[0]+offset[0],
                          xyzv[1]+offset[1],
                          xyzv[2]+offset[2], ix, iy, iz ) )
        ds->UpdateVoxel(ds->CalcIndex(ix, iy, iz), xyzv[3]);
      else
        mprintf("Warning: Coordinate out of bounds (%g %g %g, ), line %i\n",
                xyzv[0], xyzv[1], xyzv[2], buffer.LineNumber());
    }
    ptr = buffer.Line();
  }
  mprintf("\tRead %u values.\n", nvals);
  return 0;
}