FreeEnergyParse.C

Go to the documentation of this file.
00001 
00007 // written by David Hurwitz, March to May 1998.
00008 
00009 #include <ctype.h>
00010 #include <string.h>
00011 #include <stdlib.h>
00012 #include "common.h"
00013 #include "InfoStream.h"
00014 #include "FreeEnergyEnums.h"
00015 #include "FreeEnergyAssert.h"
00016 #include "Vector.h"
00017 #include "FreeEnergyVector.h"
00018 #include "FreeEnergyGroup.h"
00019 #include "FreeEnergyRestrain.h"
00020 #include "FreeEnergyRMgr.h"
00021 #include "FreeEnergyLambda.h"
00022 #include "FreeEnergyLambdMgr.h"
00023 
00024 #include "NamdTypes.h"
00025 #include "GlobalMaster.h"
00026 #include "GlobalMasterFreeEnergy.h"
00027 
00028 #include "FreeEnergyParse.h"
00029 
00030 
00031 void ProblemParsing(const char* Message, const char* Str, Bool_t Terminate) {
00032 //----------------------------------------------------------------------------
00033 // print this message if there's a problem parsing
00034 //----------------------------------------------------------------------------
00035   iout << "FreeEnergy: " << std::endl << endi;
00036   iout << "FreeEnergy: ";
00037   iout << "Problem parsing input parameters" << std::endl << endi;
00038   iout << "FreeEnergy: ";
00039   if (Terminate) {
00040     iout << "  Error:       " << Message << std::endl << endi;
00041   }
00042   else {
00043     iout << "  Warning:     " << Message << std::endl << endi;
00044   }
00045   iout << "FreeEnergy: ";
00046   iout << "  Read Until:  " << Str << std::endl << endi;
00047   iout << "FreeEnergy: " << std::endl << endi;
00048   if (Terminate) {
00049     NAMD_die("FreeEnergy: Fatal Parsing Error");
00050   }
00051 }
00052 
00053 
00054 void CheckParentheses(const char* Str) {
00055 //----------------------------------------------------------------------------
00056 // check for balanced '(' ')' and '{' '}'
00057 //----------------------------------------------------------------------------
00058   int  ParenthesesCount = 0;
00059   int  CurlyBracketCount = 0;
00060 
00061   for (unsigned int i=0; i<strlen(Str); i++) {
00062     if (Str[i] == '(') {ParenthesesCount++;}
00063     if (Str[i] == ')') {ParenthesesCount--;}
00064     if (Str[i] == '{') {CurlyBracketCount++;}
00065     if (Str[i] == '}') {CurlyBracketCount--;}
00066     if ((ParenthesesCount<0) || (CurlyBracketCount<0)) {
00067       ProblemParsing("Mismatched Parentheses", Str+i);
00068     }
00069   }
00070 }
00071 
00072 
00073 void ReadInput(char* Str, ARestraintManager& RMgr,
00074                           ALambdaManager& LMgr,
00075                           GlobalMasterFreeEnergy& CFE,
00076                           double dT) {
00077 //----------------------------------------------------------------------------
00078 // parse the input string.  Add restraints to RMgr.  Add PmfBlocks to LMgr.
00079 //----------------------------------------------------------------------------
00080   int             Count;
00081   char*           OldStr=NULL;   //make sure it's not equal Str to start
00082   ALambdaControl  PmfBlock, OldPmfBlock;
00083   // Bool_t          Terminate;
00084 
00085   // read from Str until can't read anymore
00086   ToLower(Str);
00087   CheckParentheses(Str);
00088   Str += ReadWhite(Str);
00089   while (OldStr != Str) {
00090     OldStr = Str;
00091     // add restraints to restraint manager
00092     Str += ReadRestraints(Str, RMgr, CFE);
00093     // read a single PmfBlock
00094     Count = ReadPmfBlock(Str, PmfBlock, dT);
00095     if (Count) {
00096       Str += Count;
00097       // add it to the Lambda manger
00098       LMgr.Add(PmfBlock);
00099       // initialize the default parameters of the next PmfBlock
00100       OldPmfBlock = PmfBlock;
00101       PmfBlock.Init(OldPmfBlock);
00102     }
00103   }
00104   Str += ReadWhite(Str);
00105   if (strlen(Str) > 0) {
00106     ProblemParsing("Unable to Read Entire Input File", Str, /* Terminate= */ kFalse);
00107   }
00108 }
00109 
00110 
00111 int ReadPmfBlock(char* Str, ALambdaControl& PmfBlock, double dT) {
00112 //----------------------------------------------------------------------------
00113 // if str starts with "pmf" or "mcti", read all the specs for this block
00114 // and initialize PmfBlock.
00115 //
00116 // PmfBlock will already have default values for all parameters.
00117 // The parameters that are read will be used to override the defaults.
00118 // LambdaKf and LambdaRef are initialized after all parameters have been
00119 // read, because the meaning of these parameters depends upon the task.
00120 //
00121 // If time-units (fs, ps, ns) are not specified, use ps
00122 //
00123 // return the number of chars to read past this block.
00124 // return 0 if Str does not start with "pmf" or "mcti"
00125 //----------------------------------------------------------------------------
00126   int     Count, Count1, Count2;
00127   Bool_t  Finished=kFalse;
00128   char*   FullString=Str;
00129   char*   TempStr;
00130   pmf_t   PmfSpec;
00131   // if time-units are not specified, then they're in ps.
00132   TimeUnits_t  TimeUnits;
00133   TimeUnits_t  DefaultTimeUnits = k_ps;
00134   // illegal default value.  user will have to specify this.
00135   feptask_t  Task=kUnknownTask;
00136   double  Lambda=-1, LambdaT=-1, Time;
00137   double  Dummy;
00138   int     NumRepeats=-1;
00139 
00140   const Bool_t  kPrintErrMsg=kTrue; // kNoErrMsg=kFalse;
00141 
00142   // if Str does not begin with "pmf" or "mcti" return 0
00143   Count1 = ReadWord(Str, "pmf");
00144   Count2 = ReadWord(Str, "mcti");
00145   Count = Count1 + Count2;
00146   if (Count==0) {
00147     return(0);
00148   }
00149 
00150   // skip past "pmf" or "mcti"
00151   Str += Count;
00152   // skip past "{"
00153   Str += ReadChar(Str, '{');
00154   // read spec's until "}" is found or can't read a spec
00155   do {
00156     Count = ReadNextPmfSpec(Str, PmfSpec);
00157     Str += Count;
00158     if (Count==0) {
00159       ProblemParsing("Unable to Read PMF Specification", Str);
00160     }
00161     // skip past "="
00162     Str += ReadChar(Str, '=');
00163     switch (PmfSpec) {
00164       case kTask:
00165         TempStr = Str;
00166         Str += ReadTaskType(Str, Task);
00167         if (Str == TempStr) {
00168           ProblemParsing("Can't Read Task", Str);
00169         }
00170         PmfBlock.SetTask(Task);
00171         break;
00172       case kTime:
00173         Str += ReadAValue(Str, Time, kPrintErrMsg);
00174         Str += ReadTimeUnits(Str, TimeUnits, DefaultTimeUnits);
00175         Time = GetTime(Time, TimeUnits);
00176         PmfBlock.SetNumSteps((int)(Time/dT));
00177         break;
00178       case kLambda:
00179         Str += ReadAValue(Str, Lambda, kPrintErrMsg);
00180         break;
00181       case kLambdaT:
00182         Str += ReadAValue(Str, LambdaT, kPrintErrMsg);
00183         break;
00184       case kPrint:
00185         Str += ReadAValue(Str, Time, kPrintErrMsg);
00186         Str += ReadTimeUnits(Str, TimeUnits, DefaultTimeUnits);
00187         Time = GetTime(Time, TimeUnits);
00188         PmfBlock.SetNumPrintSteps((int)(Time/dT));
00189         break;
00190       case kNoPrint:
00191         PmfBlock.SetNumPrintSteps(-1);
00192         break;
00193       case kEquilTime:
00194         Str += ReadAValue(Str, Time, kPrintErrMsg);
00195         Str += ReadTimeUnits(Str, TimeUnits, DefaultTimeUnits);
00196         Time = GetTime(Time, TimeUnits);
00197         PmfBlock.SetNumEquilSteps((int)(Time/dT));
00198         break;
00199       case kAccumTime:
00200         Str += ReadAValue(Str, Time, kPrintErrMsg);
00201         Str += ReadTimeUnits(Str, TimeUnits, DefaultTimeUnits);
00202         Time = GetTime(Time, TimeUnits);
00203         PmfBlock.SetNumAccumSteps((int)(Time/dT));
00204         break;
00205       case kNumRepeats:
00206         Str += ReadAValue(Str, Dummy, kPrintErrMsg);
00207         NumRepeats = (int)Dummy;
00208         PmfBlock.SetNumRepeats(NumRepeats);
00209         break;
00210       default:
00211         ASSERT(kFalse);
00212     }
00213     Count = ReadChar(Str, '}');
00214     Str += Count;
00215     // if "}" was read, then we're finished
00216     if (Count!=0) {Finished=kTrue;}
00217   }
00218   while(!Finished);
00219 
00220   // if Task was not specified above, then use PmfBlock's default task
00221   if (Task==kUnknownTask) {
00222     Task = PmfBlock.GetTask();
00223   }
00224   // if Task wasn't specified earlier, die.
00225   if (Task==kUnknownTask) {
00226     ProblemParsing("Must Specify Task", FullString);
00227   }
00228 
00229   // set LambdaKf and LambdaRef, using Lambda and LambdaT
00230   // (the former is the internal representation, the latter is the user's)
00231   // there's no need to set them if they haven't been read in this routine
00232   switch(Task) {
00233     case kStop:
00234       PmfBlock.SetLambdaKf(1.0);
00235       if (Lambda >= -kALittle) {
00236         PmfBlock.SetLambdaRef(Lambda);
00237       }
00238       break;
00239     case kNoGrow:
00240       if (Lambda >= -kALittle) {
00241         PmfBlock.SetLambdaKf(Lambda);
00242       }
00243     case kGrow:
00244     case kFade:
00245     case kStepGrow:
00246     case kStepFade:
00247       if (LambdaT >= -kALittle) {
00248         PmfBlock.SetLambdaRef(LambdaT);
00249       }
00250       break;
00251     default:
00252       ASSERT((Task==kUp)||(Task==kDown)||(Task==kStepUp)||(Task==kStepDown));
00253       PmfBlock.SetLambdaKf(1.0);
00254       break;
00255   }
00256   
00257   return(Str-FullString);
00258 }
00259 
00260 
00261 double GetTime(double Val, TimeUnits_t Units) {
00262 //----------------------------------------------------------------------------
00263 // convert (Val Units) to fs, where Units is either fs, ps, or ns
00264 //----------------------------------------------------------------------------
00265   switch (Units) {
00266     case k_fs:  return(Val);
00267     case k_ps:  return(Val*1000);
00268     case k_ns:  return(Val*1000000);
00269     default:
00270       ASSERT(kFalse);
00271       return(Val);
00272   }
00273 }
00274 
00275 
00276 int ReadTimeUnits(char* Str, TimeUnits_t& Units, TimeUnits_t DefaultUnits) {
00277 //----------------------------------------------------------------------------
00278 // Str should start with one of:
00279 //   "fs", "ps", or "ns"
00280 //
00281 // If Str starts with one of the above, return an identifier for the above.
00282 // if Str does not start with one of the above, set Units to DefaultUnits.
00283 //
00284 // return the number of chars to read past the time units.  return 0 if
00285 // Str does not start with one of the above.
00286 //----------------------------------------------------------------------------
00287   char*   FullString=Str;
00288   Bool_t  FoundIt=kFalse;
00289 
00290   if (strncmp(Str,"fs",2)==0) {Units=k_fs; FoundIt=kTrue;}
00291   if (strncmp(Str,"ps",2)==0) {Units=k_ps; FoundIt=kTrue;}
00292   if (strncmp(Str,"ns",2)==0) {Units=k_ns; FoundIt=kTrue;}
00293 
00294   if (FoundIt) {
00295     Str += ReadAlpha(Str);
00296     Str += ReadWhite(Str);
00297   }
00298   else {
00299     Units = DefaultUnits;
00300   }
00301   return(Str-FullString);
00302 }
00303 
00304 
00305 int ReadTaskType(char* Str, feptask_t& Task) {
00306 //----------------------------------------------------------------------------
00307 // Str should start with a task, one of:
00308 //   "up", "down", "stop", "grow", "fade", "nogrow",
00309 //   "stepup", "stepdown", "stepgrow", "stepfade"
00310 //
00311 // return an identifer for the above.
00312 // return the number of chars to read past the task.  return 0 if Str does
00313 // not start with one of the above.
00314 //----------------------------------------------------------------------------
00315   char*   FullString=Str;
00316 
00317   Task = kUnknownTask;
00318   if (strncmp(Str,"up",2)==0)       {Task=kUp;       goto GotIt;}
00319   if (strncmp(Str,"down",4)==0)     {Task=kDown;     goto GotIt;}
00320   if (strncmp(Str,"stop",4)==0)     {Task=kStop;     goto GotIt;}
00321   if (strncmp(Str,"grow",4)==0)     {Task=kGrow;     goto GotIt;}
00322   if (strncmp(Str,"fade",4)==0)     {Task=kFade;     goto GotIt;}
00323   if (strncmp(Str,"nogrow",6)==0)   {Task=kNoGrow;   goto GotIt;}
00324   if (strncmp(Str,"stepup",6)==0)   {Task=kStepUp;   goto GotIt;}
00325   if (strncmp(Str,"stepdown",8)==0) {Task=kStepDown; goto GotIt;}
00326   if (strncmp(Str,"stepgrow",8)==0) {Task=kStepGrow; goto GotIt;}
00327   if (strncmp(Str,"stepfade",8)==0) {Task=kStepFade; goto GotIt;}
00328   return(0);
00329 
00330 GotIt:
00331   Str += ReadAlpha(Str);
00332   Str += ReadWhite(Str);
00333   return(Str-FullString);
00334 }
00335 
00336 
00337 int ReadNextPmfSpec(char* Str, pmf_t& PmfSpec) {
00338 //----------------------------------------------------------------------------
00339 // Str should start with the next spec for a pmf or mcti block, one of:
00340 //   "task", "time", "lambda", "lambdaT", "print",
00341 //   "equiltime", "accumtime", "numsteps"
00342 //
00343 // Return an identifier of the above.
00344 // Return number of characters, including trailing white space to read past
00345 // this word.  Return NumChars=0 if Str does not begin with one of the above.
00346 //----------------------------------------------------------------------------
00347   char*  FullString=Str;
00348 
00349   PmfSpec = kUnknownPmf;
00350   if (strncmp(Str,"task",4)==0)    {PmfSpec=kTask;       goto GotIt;}
00351   if (strncmp(Str,"time",4)==0)    {PmfSpec=kTime;       goto GotIt;}
00352   // check for lambdat first, else PmfSpec will be kLambda for "lambdat"
00353   if (strncmp(Str,"lambdat",7)==0) {PmfSpec=kLambdaT;    goto GotIt;}
00354   if (strncmp(Str,"lambda",6)==0)  {PmfSpec=kLambda;     goto GotIt;}
00355   if (strncmp(Str,"print",5)==0)   {PmfSpec=kPrint;      goto GotIt;}
00356   if (strncmp(Str,"nopr",4)==0)    {PmfSpec=kNoPrint;    goto GotIt;}
00357   if (strncmp(Str,"equil",5)==0)   {PmfSpec=kEquilTime;  goto GotIt;}
00358   if (strncmp(Str,"accum",5)==0)   {PmfSpec=kAccumTime;  goto GotIt;}
00359   if (strncmp(Str,"numstep",7)==0) {PmfSpec=kNumRepeats; goto GotIt;}
00360   return(0);
00361 
00362 GotIt:
00363   Str += ReadAlpha(Str);
00364   Str += ReadWhite(Str);
00365   return(Str-FullString);
00366 }
00367 
00368 
00369 int ReadRestraints(char* Str, ARestraintManager& AllRestraints,
00370                               GlobalMasterFreeEnergy& CFE) {
00371 //----------------------------------------------------------------------------
00372 // if Str starts with "urestr", read each restraint spec, create
00373 // a restraint, and put a pointer to the restraint into AllRestraints
00374 //
00375 // return the number of chars to read past all restraints
00376 // return 0 if Str does not start with "urestr"
00377 //----------------------------------------------------------------------------
00378   int          Count;
00379   Bool_t       Finished=kFalse;
00380   char*        FullString=Str;
00381   ARestraint*  pRestraint;
00382 
00383   Count = ReadWord(Str, "urest");
00384   // when "urestraint" is found
00385   if (Count) {
00386     // skip past "urest..."
00387     Str += Count;
00388     // skip past "{"
00389     Str += ReadChar(Str, '{');
00390     // read restraints until "}" is found or can't read a restraint
00391     do {
00392       pRestraint = GetRestraint(Str, Count, CFE);
00393       Str += Count;
00394       // if a restraint could not be read, then we're finished
00395       if (Count==0) {Finished=kTrue;}
00396       if (!Finished) {
00397         AllRestraints.Add(pRestraint);
00398         Count = ReadChar(Str, '}');
00399         Str += Count;
00400         // if "}" was read, then we're finished
00401         if (Count!=0) {Finished=kTrue;}
00402       }
00403     }
00404     while(!Finished);
00405   }
00406   return(Str-FullString);
00407 }
00408 
00409 
00410 ARestraint* GetRestraint(char* Str, int& NumChars, GlobalMasterFreeEnergy& CFE) {
00411 //----------------------------------------------------------------------------
00412 // read spec's for a restraint, from the input string.
00413 // allocate space for and initialize a restraint object with these specs.
00414 // note:  memory is allocated here, and free'd elsewhere.
00415 //
00416 // return a pointer to this object.
00417 // return the number of characters to read past these specs.
00418 // return NumChars=0 for illegal restraint specs.
00419 //----------------------------------------------------------------------------
00420   AGroup      Group1, Group2, Group3, Group4;
00421   ARestraint* pRestraint = NULL;
00422   restr_t     Restraint;
00423   Bound_t     Bound;
00424   int         Count;
00425   double      Kf;
00426   double      D,   D0,   D1;
00427   double      A=0, A0=0, A1=0, A2=0;
00428   AVector     Pos, Pos0, Pos1;
00429   char*       FullStr;
00430   char*       TempStr;
00431 
00432   const Bool_t  kPrintErrMsg=kTrue; // kNoErrMsg=kFalse;
00433 
00434   // save pointer to full string
00435   FullStr = Str;
00436   NumChars = 0;
00437 
00438   // get restraint type
00439   Restraint = ReadNextRestraintType(Str, Count);
00440   if (Count == 0) {
00441     ProblemParsing("Can't Read Restraint Type", Str);
00442     return(pRestraint);
00443   }
00444 
00445   // skip past restraint type
00446   ASSERT(Restraint != kUnknownRestr);
00447   Str += Count;
00448   
00449   // read in appropriate number of atoms or groups-of-atoms for
00450   // this restraint type, put the atoms in Group1 thru Group4
00451   switch (Restraint) {
00452     case kDihe:  case kDiheBound:  case kDihePMF:
00453       Str += AddAtoms(Group4, Str, CFE);
00454     case kAngle: case kAngleBound: case kAnglePMF:
00455       Str += AddAtoms(Group3, Str, CFE);
00456     case kDist:  case kDistBound:  case kDistPMF:
00457       Str += AddAtoms(Group2, Str, CFE);
00458     case kPosi:  case kPosiBound:  case kPosiPMF:
00459       Str += AddAtoms(Group1, Str, CFE);
00460     default: ;
00461   }
00462 
00463   // for dihedrals, allow keywords of "barr=", "gap=", OR "kf="
00464   // for other restraints, just allow "kf="
00465   TempStr = Str;
00466   switch(Restraint) {
00467     case kDihe:
00468     case kDiheBound:
00469     case kDihePMF:
00470       Str += ReadWord(Str, "barr");
00471       Str += ReadWord(Str, "gap");
00472     default:
00473       Str += ReadWord(Str, "kf");
00474       // make sure the word "barr", "gap", or "kf" was read
00475       if (Str==TempStr) {
00476         ProblemParsing("Word Missing: barr, gap, or kf", Str);
00477       }
00478       Str += ReadChar(Str, '=');
00479   }
00480   // get the Kf value
00481   Str += ReadAValue(Str, Kf,          kPrintErrMsg);
00482   
00483   // read the reference positions, distances or angles
00484   switch (Restraint) {
00485     case kPosi:  
00486       Str += ReadWord(Str, "ref",    kPrintErrMsg);
00487       Str += ReadChar(Str, '=');
00488       Str += ReadChar(Str, '(');
00489       Str += ReadAValue(Str, Pos[0],  kPrintErrMsg);
00490       Str += ReadAValue(Str, Pos[1],  kPrintErrMsg);
00491       Str += ReadAValue(Str, Pos[2],  kPrintErrMsg);
00492       Str += ReadChar(Str, ')');
00493       break;
00494     case kDist:
00495       Str += ReadWord(Str, "ref",    kPrintErrMsg);
00496       Str += ReadChar(Str, '=');
00497       Str += ReadAValue(Str, D,       kPrintErrMsg);
00498       break;
00499     case kAngle:
00500       Str += ReadWord(Str, "ref",    kPrintErrMsg);
00501       Str += ReadChar(Str, '=');
00502       Str += ReadAValue(Str, A,       kPrintErrMsg);
00503       break;
00504     case kDihe:
00505       Str += ReadWord(Str, "ref",    kPrintErrMsg);
00506       Str += ReadChar(Str, '=');
00507       Str += ReadAValue(Str, A,       kPrintErrMsg);
00508       break;
00509     case kPosiBound:
00510       if (ReadBound(Str, Bound) == 0) {ProblemParsing("Missing Bound", Str);}
00511       Str += ReadWord(Str, "low");
00512       Str += ReadWord(Str, "hi");
00513       Str += ReadChar(Str, '=');
00514       Str += ReadChar(Str, '(');
00515       Str += ReadAValue(Str, Pos[0],  kPrintErrMsg);
00516       Str += ReadAValue(Str, Pos[1],  kPrintErrMsg);
00517       Str += ReadAValue(Str, Pos[2],  kPrintErrMsg);
00518       Str += ReadAValue(Str, D,       kPrintErrMsg);
00519       Str += ReadChar(Str, ')');
00520       break;
00521     case kDistBound:
00522       if (ReadBound(Str, Bound) == 0) {ProblemParsing("Missing Bound", Str);}
00523       Str += ReadWord(Str, "low");
00524       Str += ReadWord(Str, "hi");
00525       Str += ReadChar(Str, '=');
00526       Str += ReadAValue(Str, D,       kPrintErrMsg);
00527       break;
00528     case kAngleBound:
00529       if (ReadBound(Str, Bound) == 0) {ProblemParsing("Missing Bound", Str);}
00530       Str += ReadWord(Str, "low");
00531       Str += ReadWord(Str, "hi");
00532       Str += ReadChar(Str, '=');
00533       Str += ReadAValue(Str, A,       kPrintErrMsg);
00534       break;
00535     case kDiheBound:
00536       Str += ReadWord(Str, "low",    kPrintErrMsg);
00537       Str += ReadChar(Str, '=');
00538       Str += ReadAValue(Str, A0,      kPrintErrMsg);
00539       Str += ReadWord(Str, "hi",     kPrintErrMsg);
00540       Str += ReadChar(Str, '=');
00541       Str += ReadAValue(Str, A1,      kPrintErrMsg);
00542       Str += ReadWord(Str, "delta",  kPrintErrMsg);
00543       Str += ReadChar(Str, '=');
00544       Str += ReadAValue(Str, A2,      kPrintErrMsg);
00545       break;
00546     case kPosiPMF:
00547       Str += ReadWord(Str, "low",    kPrintErrMsg);
00548       Str += ReadChar(Str, '=');
00549       Str += ReadChar(Str, '(');
00550       Str += ReadAValue(Str, Pos0[0], kPrintErrMsg);
00551       Str += ReadAValue(Str, Pos0[1], kPrintErrMsg);
00552       Str += ReadAValue(Str, Pos0[2], kPrintErrMsg);
00553       Str += ReadChar(Str, ')');
00554       Str += ReadWord(Str, "hi",     kPrintErrMsg);
00555       Str += ReadChar(Str, '=');
00556       Str += ReadChar(Str, '(');
00557       Str += ReadAValue(Str, Pos1[0], kPrintErrMsg);
00558       Str += ReadAValue(Str, Pos1[1], kPrintErrMsg);
00559       Str += ReadAValue(Str, Pos1[2], kPrintErrMsg);
00560       Str += ReadChar(Str, ')');
00561       break;
00562     case kDistPMF:
00563       Str += ReadWord(Str, "low",    kPrintErrMsg);
00564       Str += ReadChar(Str, '=');
00565       Str += ReadAValue(Str, D0,      kPrintErrMsg);
00566       Str += ReadWord(Str, "hi",     kPrintErrMsg);
00567       Str += ReadChar(Str, '=');
00568       Str += ReadAValue(Str, D1,      kPrintErrMsg);
00569       break;
00570     case kAnglePMF:
00571       Str += ReadWord(Str, "low",    kPrintErrMsg);
00572       Str += ReadChar(Str, '=');
00573       Str += ReadAValue(Str, A0,      kPrintErrMsg);
00574       Str += ReadWord(Str, "hi",     kPrintErrMsg);
00575       Str += ReadChar(Str, '=');
00576       Str += ReadAValue(Str, A1,      kPrintErrMsg);
00577       break;
00578     case kDihePMF:
00579       Str += ReadWord(Str, "low",    kPrintErrMsg);
00580       Str += ReadChar(Str, '=');
00581       Str += ReadAValue(Str, A0,      kPrintErrMsg);
00582       Str += ReadWord(Str, "hi",     kPrintErrMsg);
00583       Str += ReadChar(Str, '=');
00584       Str += ReadAValue(Str, A1,      kPrintErrMsg);
00585       break;
00586     default: ;
00587   }
00588 
00589   // convert degrees to radians
00590   A  *= (kPi/180);
00591   A0 *= (kPi/180);
00592   A1 *= (kPi/180);
00593   A2 *= (kPi/180);
00594 
00595   // initialize the restraint
00596   switch (Restraint) {
00597     case kPosi:
00598       pRestraint = new AFixedPosRestraint;
00599       pRestraint->SetKf(Kf);
00600       pRestraint->SetGroups(Group1);
00601       pRestraint->SetRefPos(Pos);
00602       break;
00603     case kDist:
00604       pRestraint = new AFixedDistRestraint;
00605       pRestraint->SetKf(Kf);
00606       pRestraint->SetGroups(Group2, Group1);
00607       pRestraint->SetRefDist(D);
00608       break;
00609     case kAngle:
00610       pRestraint = new AFixedAngleRestraint;
00611       pRestraint->SetKf(Kf);
00612       pRestraint->SetGroups(Group3, Group2, Group1);
00613       pRestraint->SetRefAngle(A);
00614       break;
00615     case kDihe:
00616       pRestraint = new AFixedDiheRestraint;
00617       pRestraint->SetKf(Kf);
00618       pRestraint->SetGroups(Group4, Group3, Group2, Group1);
00619       pRestraint->SetRefAngle(A);
00620       break;
00621     case kPosiBound:
00622       pRestraint = new ABoundPosRestraint;
00623       pRestraint->SetKf(Kf);
00624       pRestraint->SetGroups(Group1);
00625       pRestraint->SetRefPos(Pos);
00626       pRestraint->SetRefDist(D);
00627       pRestraint->SetBound(Bound);
00628       break;
00629     case kDistBound:
00630       pRestraint = new ABoundDistRestraint;
00631       pRestraint->SetKf(Kf);
00632       pRestraint->SetGroups(Group2, Group1);
00633       pRestraint->SetRefDist(D);
00634       pRestraint->SetBound(Bound);
00635       break;
00636     case kAngleBound:
00637       pRestraint = new ABoundAngleRestraint;
00638       pRestraint->SetKf(Kf);
00639       pRestraint->SetGroups(Group3, Group2, Group1);
00640       pRestraint->SetRefAngle(A);
00641       pRestraint->SetBound(Bound);
00642       break;
00643     case kDiheBound:
00644       pRestraint = new ABoundDiheRestraint;
00645       pRestraint->SetKf(Kf);
00646       pRestraint->SetGroups(Group4, Group3, Group2, Group1);
00647       pRestraint->SetLowerAngle(A0);
00648       pRestraint->SetUpperAngle(A1);
00649       pRestraint->SetIntervalAngle(A2);
00650       break;
00651     case kPosiPMF:
00652       pRestraint = new AForcingPosRestraint;
00653       pRestraint->SetKf(Kf);
00654       pRestraint->SetGroups(Group1);
00655       pRestraint->SetStartPos(Pos0);
00656       pRestraint->SetStopPos(Pos1);
00657       break;
00658     case kDistPMF:
00659       pRestraint = new AForcingDistRestraint;
00660       pRestraint->SetKf(Kf);
00661       pRestraint->SetGroups(Group2, Group1);
00662       pRestraint->SetStartDist(D0);
00663       pRestraint->SetStopDist(D1);
00664       break;
00665     case kAnglePMF:
00666       pRestraint = new AForcingAngleRestraint;
00667       pRestraint->SetKf(Kf);
00668       pRestraint->SetGroups(Group3, Group2, Group1);
00669       pRestraint->SetStartAngle(A0);
00670       pRestraint->SetStopAngle(A1);
00671       break;
00672     case kDihePMF:
00673       pRestraint = new AForcingDiheRestraint;
00674       pRestraint->SetKf(Kf);
00675       pRestraint->SetGroups(Group4, Group3, Group2, Group1);
00676       pRestraint->SetStartAngle(A0);
00677       pRestraint->SetStopAngle(A1);
00678       break;
00679     default: ;
00680   }
00681   // calc number of chars to read restraint specs
00682   NumChars = Str-FullStr;
00683   return(pRestraint);
00684 }
00685 
00686 
00687 int ReadBound(char* Str, Bound_t& Bound) {
00688 //----------------------------------------------------------------------------
00689 // Str should start with "low" or "hi".  determine which it is and
00690 // count the number of characters to read past this word + white-space.
00691 // return NumChars=0 if Str does not start with "low" or "hi"
00692 //----------------------------------------------------------------------------
00693   int  Count;
00694 
00695   Bound = kUnknownBound;
00696   Count = ReadWord(Str, "low");
00697   if (Count) {
00698     Bound=kLower;
00699     return(Count);
00700   }
00701 
00702   Count = ReadWord(Str, "hi");
00703   if (Count) {
00704     Bound=kUpper;
00705     return(Count);
00706   }
00707 
00708   return(Count);  // Count will be 0 if "low" or "hi" wasn't found
00709 }
00710 
00711 
00712 int ReadAValue(char* Str, double& Value, Bool_t ErrMsg) {
00713 //----------------------------------------------------------------------------
00714 // Str should start with a floating point number.  convert it to a double.
00715 // also, return the number of chars to read past the value + white-space
00716 // return NumChars = 0 if Str does not start with a valid fp number.
00717 // Print an error message if ErrMsg is kTrue, and no value is read.
00718 //----------------------------------------------------------------------------
00719   int    NumChars;
00720   char*  NewStr;
00721 
00722   // read f.p. number and trailing white-space
00723   Value = strtod(Str, &NewStr);
00724   if (NewStr != Str) {
00725     NewStr += ReadWhite(NewStr);
00726   }
00727   NumChars = NewStr - Str;
00728 
00729   // if no number was read, and ErrMsg is kTrue, print a message
00730   if ((NumChars==0) && (ErrMsg)) {
00731     ProblemParsing("Floating Point Number Expected", Str);
00732   }
00733 
00734   return(NumChars);
00735 }
00736 
00737 
00738 int ReadChar(char* Str, char Char, Bool_t ErrMsg) {
00739 //----------------------------------------------------------------------------
00740 // Str should start with Char plus trailing white space.
00741 // return the number of chars, including the white space, to read past Char
00742 // return 0 if Str does not start with Char.
00743 // Print an error message if ErrMsg is kTrue, and Char is not read.
00744 //----------------------------------------------------------------------------
00745   int    NumChars;
00746   char*  FullString=Str;
00747   char   Message[64];
00748   
00749   // initial part of Message
00750   strcpy(Message, "Character Missing:  ");
00751 
00752   // read char and trailing white-space
00753   if (Str[0] == Char) {
00754     Str += 1;
00755     Str += ReadWhite(Str);
00756   }
00757   NumChars = Str - FullString;
00758 
00759   // if Char was not read, and ErrMsg is kTrue, print a message
00760   if ((NumChars==0) && (ErrMsg)) {
00761     // add the character that's missing to Message
00762     Message[strlen(Message)-1] = Char;
00763     ProblemParsing(Message, Str);
00764   }
00765 
00766   return(NumChars);
00767 }
00768 
00769 
00770 int ReadWord(const char* Str, const char* Word, Bool_t ErrMsg) {
00771 //----------------------------------------------------------------------------
00772 // Str should start with Word plus, perhaps, some extra alphabetic
00773 // characters, plus trailing white space.
00774 //
00775 // (do NOT read past numeric characters which follow Word, so that
00776 //  this routine can be used on the following:  ReadWord(Str, "="),
00777 //  where Str is, for example, "=123 ...")
00778 //
00779 // return the number of chars, including the white space, to read past Word
00780 // return 0 if Str does not start with Word.
00781 //
00782 // Print an error message if ErrMsg is kTrue, and word is not read.
00783 //----------------------------------------------------------------------------
00784   const char*  FullString=Str;
00785   int    NumChars, StrLen;
00786   char   Message[64];
00787   
00788   // initial part of message
00789   strcpy(Message, "Word Missing: ");
00790 
00791   StrLen = strlen(Word);
00792   if (strncmp(Str, Word, StrLen) == 0) {
00793     Str += StrLen;
00794     Str += ReadAlpha(Str);
00795     Str += ReadWhite(Str);
00796   }
00797   NumChars = Str - FullString;
00798 
00799   // if Word was not read, and ErrMsg is kTrue, print a message
00800   if ((NumChars==0) && (ErrMsg)) {
00801     strcat(Message, Word);
00802     ProblemParsing(Message, Str);
00803   }
00804 
00805   return(NumChars);
00806 }
00807 
00808 
00809 restr_t ReadNextRestraintType(char* Str, int& NumChars) {
00810 //----------------------------------------------------------------------------
00811 // Str should start with the next restraint type (no leading white space),
00812 // namely one of:
00813 // 
00814 //   "posi",       "dist",       "angle",       "dihe"
00815 //   "posi bound", "dist bound", "angle bound", "dihe bound"
00816 //   "posi pmf",   "dist pmf",   "angle pmf",   "dihe pmf"
00817 //
00818 // figure out which it is.
00819 // also, return the number of characters, including trailing white space.
00820 // return NumChars=0 for an illegal restraint-type
00821 //
00822 // the words "pos*", "dist*", "angle*", "dihe*", "bound*", and "pmf*"
00823 // are all recognized.
00824 //----------------------------------------------------------------------------
00825   restr_t  RestraintType=kUnknownRestr;
00826   char*    FullString=Str;
00827 
00828   // check if Str starts with "pos", "dist", "angl", or "dihe"
00829   if (strncmp(Str,"pos", 3)==0)  {RestraintType=kPosi;  goto GotIt;}
00830   if (strncmp(Str,"dist",4)==0)  {RestraintType=kDist;  goto GotIt;}
00831   if (strncmp(Str,"angl",4)==0)  {RestraintType=kAngle; goto GotIt;}
00832   if (strncmp(Str,"dihe",4)==0)  {RestraintType=kDihe;  goto GotIt;}
00833   NumChars = 0;
00834   return(RestraintType);
00835 
00836   // skip to the end of the white space following this word
00837 GotIt:
00838   Str += 3;
00839   Str += ReadAlphaNum(Str);
00840   Str += ReadWhite(Str);
00841 
00842   // check if the next word is "bound", skip to the end of this word
00843   if (strncmp(Str,"bound",5)==0) {
00844     switch (RestraintType) {
00845       case kPosi:   RestraintType=kPosiBound;   break;
00846       case kDist:   RestraintType=kDistBound;   break;
00847       case kAngle:  RestraintType=kAngleBound;  break;
00848       case kDihe:   RestraintType=kDiheBound;   break;
00849       default: break;
00850     }
00851     Str += 5;
00852     Str += ReadAlphaNum(Str);
00853   }
00854 
00855   // check if the next word is "pmf", skip to the end of this word
00856   if (strncmp(Str,"pmf",3)==0) {
00857     switch (RestraintType) {
00858       case kPosi:   RestraintType=kPosiPMF;   break;
00859       case kDist:   RestraintType=kDistPMF;   break;
00860       case kAngle:  RestraintType=kAnglePMF;  break;
00861       case kDihe:   RestraintType=kDihePMF;   break;
00862       default: break;
00863     }
00864     Str += 3;
00865     Str += ReadAlphaNum(Str);
00866   }
00867 
00868   // skip past trailing white space, calcuate num chars string has been advanced
00869   Str += ReadWhite(Str);
00870   NumChars = Str-FullString;
00871   return(RestraintType);
00872 }
00873 
00874 
00875 int AddAtoms(AGroup& Group, char* Str, GlobalMasterFreeEnergy& CFE) {
00876 //----------------------------------------------------------------------------
00877 // Str contains specifications for which atoms to add to Group.
00878 // The atoms may be:
00879 //   a) a single atom, b) all atoms of a residue, c) a list of atoms
00880 //   d) all atoms in a list of residues, e) all atoms in a range of residues,
00881 //   e) one or more atomnames in a list of residues, or
00882 //   f) one or more atomnames in a range of residues
00883 // Add the AtomID's for these specified atoms to Group.
00884 // return the number of characters in Str that were read.
00885 //----------------------------------------------------------------------------
00886   int     NumChars;
00887   int     RetNumChars = 0;
00888   Bool_t  GroupMode = kFalse;
00889   Bool_t  AtomList =  kFalse;
00890   Bool_t  Finished =  kFalse;
00891   char*   SavePtr = 0;
00892 
00893   while (!Finished) {
00894     switch(ReadNextItem(Str, NumChars)) {
00895       case kStartGroup:
00896         GroupMode = kTrue;
00897         break;
00898       case kEndGroup:
00899         Finished = kTrue;
00900         break;
00901       case kAtom:
00902         AddAtom(Group, Str, CFE);
00903         if (!GroupMode) {
00904           Finished = kTrue;
00905         }
00906         break;
00907       case kAtomName:
00908       case kAtomNameList:
00909         AtomList = kTrue;
00910         SavePtr = Str;
00911         break;
00912       case kResidue:
00913       case kResidueRange:
00914         if (AtomList) {
00915           AddAtomsInResidues(Group, SavePtr, Str, CFE);
00916         }
00917         else {
00918           AddResidues(Group, Str, CFE);
00919         }
00920         if (!GroupMode) {
00921           Finished = kTrue;
00922         }
00923         break;
00924       default:
00925         Finished = kTrue;
00926         ProblemParsing("Can't Read Atoms", Str);
00927         break;
00928     }
00929     Str += NumChars;
00930     RetNumChars += NumChars;
00931   }
00932   RetNumChars += ReadWhite(Str);
00933   return(RetNumChars);
00934 }
00935 
00936 
00937 void AddAtomsInResidues(AGroup& Group, char* AtomNames, char* ResRange,
00938                         GlobalMasterFreeEnergy& CFE) {
00939 //-------------------------------------------------------------------
00940 // Group contains a list of int's representing AtomID's.
00941 // ResRange should be "(segname, resnum) to (segname, resnum)"
00942 //                 or "(segname, resnum)"
00943 // AtomNames should be "(atomname, atomname, ...):" or "atomname:"
00944 // get the atomID's for each atomname in ResRange, add them to Group.
00945 //-------------------------------------------------------------------
00946   int   Count, ArrayIndex, i;
00947   char  AtomNamesArray[21][30];
00948 
00949   // skip to start of first atomname
00950   if (AtomNames[0] == '(') {
00951     AtomNames++;
00952     Count = ReadWhite(AtomNames);
00953     AtomNames += Count;
00954   }
00955   // put each atomname into the array, finish when ':' or ')' is found
00956   ArrayIndex = 0;
00957   while ( (AtomNames[0]!=':') && (AtomNames[0]!=')') ) {
00958     Count = ReadAlphaNum(AtomNames);
00959     strncpy(AtomNamesArray[ArrayIndex], AtomNames, Count);
00960     AtomNamesArray[ArrayIndex][Count] = '\0';
00961     AtomNames += Count;
00962     Count = ReadWhite(AtomNames);
00963     AtomNames += Count;
00964     ArrayIndex++;
00965   }
00966   // now add each atomname of Res to Group.
00967   // if "all" is specified, add all atoms of Res to Group.
00968   for (i=0; i<ArrayIndex; i++) {
00969     if (strcmp(AtomNamesArray[i], "all") == 0) {
00970       AddResidues(Group, ResRange, CFE);
00971     }
00972     else {
00973       AddAtom(Group, ResRange, AtomNamesArray[i], CFE);
00974     }
00975   }
00976 }
00977 
00978 
00979 void AddResidues(AGroup& Group, char* ResRange, GlobalMasterFreeEnergy& CFE) {
00980 //-------------------------------------------------------------------
00981 // Group contains a list of int's representing AtomID's.
00982 // ResRange should be "(segname, resnum) to (segname, resnum)"
00983 //                 or "(segname, resnum)"
00984 // get the atomID's for each atom of ResRange, and add them to Group.
00985 //-------------------------------------------------------------------
00986   char  SegName[21];
00987   int   ResNum1, ResNum2, ResNum;
00988   int   i, NumAtoms, AtomID, RetVal;
00989 
00990   // get start and stop residue numbers
00991   GetSegName(ResRange, SegName);
00992   GetResRange(ResRange, ResNum1, ResNum2);
00993 
00994   // for each residue of residue range
00995   for (ResNum=ResNum1; ResNum<=ResNum2; ResNum++) {
00996     // for each atom of residue
00997     NumAtoms = CFE.getNumAtoms(SegName, ResNum);
00998     if (NumAtoms < 1) { ProblemParsing("No Atoms in Residue", ResRange); }
00999     for (i=0; i<NumAtoms; i++) {
01000       // get atomID, register it, add it to Group
01001       AtomID = CFE.getAtomID(SegName, ResNum, i);
01002       if (AtomID < 0) { ProblemParsing("Invalid AtomID", ResRange); }
01003       RetVal = CFE.requestAtom(AtomID);
01004       if (RetVal < 0) { ProblemParsing("Unable to requestAtom", ResRange); }
01005       Group.Add(AtomID);
01006     }
01007   }
01008 }
01009 
01010 
01011 void AddAtom(AGroup& Group, char* Atom, GlobalMasterFreeEnergy& CFE) {
01012 //-------------------------------------------------------------------
01013 // Group contains a list of int's representing AtomID's.
01014 // Atom should be "(segname, resnum, atomname)"
01015 // get the atomID for Atom, and add it to Group.
01016 //-------------------------------------------------------------------
01017   char  AtomName[21];
01018 
01019   GetAtomName(Atom, AtomName);
01020   AddAtom(Group, Atom, AtomName, CFE);
01021 }
01022 
01023 
01024 void AddAtom(AGroup& Group, char* ResRange, char* AtomName,
01025              GlobalMasterFreeEnergy& CFE) {
01026 //-------------------------------------------------------------------
01027 // Group contains a list of int's representing AtomID's.
01028 // ResRange should be "(segname, resnum) to (segname, resnum)"
01029 //                 or "(segname, resnum)"
01030 // AtomName is specified separately.
01031 // get the atomID, and add it to Group.
01032 //-------------------------------------------------------------------
01033   char  SegName[21];
01034   int   ResNum, ResNum1, ResNum2, AtomID, RetVal;
01035 
01036   // convert "(segname, resnum1) to (segname, resnum2)"
01037   //  -> SegName, ResNum1, ResNum2
01038   GetSegName(ResRange, SegName);
01039   GetResRange(ResRange, ResNum1, ResNum2);
01040 
01041   // get atomID for each atom in the specified residue range
01042   // register it, add it to Group
01043   for (ResNum=ResNum1; ResNum<=ResNum2; ResNum++) {
01044     AtomID = CFE.getAtomID(SegName, ResNum, AtomName);
01045     if (AtomID < 0) { ProblemParsing("Invalid AtomID", ResRange); }
01046     RetVal = CFE.requestAtom(AtomID);
01047     if (RetVal < 0) { ProblemParsing("Unable to requestAtom", ResRange); }
01048     Group.Add(AtomID);
01049   }
01050 }
01051 
01052 
01053 void GetResRange(char* ResRange, int& ResNum1, int& ResNum2) {
01054 //-------------------------------------------------------------------
01055 // ResRange should be "(segname, resnum1) to (segname, resnum2)"
01056 // return ResNum1 & ResNum2
01057 // if "to" is missing, return resnum1 in both ResNum1 & ResNum2
01058 //-------------------------------------------------------------------
01059   char SegName1[21], SegName2[21];
01060 
01061   // get start residue number
01062   GetSegName(ResRange, SegName1);
01063   GetResNum(ResRange, ResNum1);
01064 
01065   // skip to where "to" should appear
01066   ResRange += ReadParentheses(ResRange);
01067   ResRange += ReadWhite(ResRange);
01068 
01069   // if "to" is found
01070   if (strncmp(ResRange, "to", 2) == 0) {
01071     //skip to next residue
01072     ResRange += ReadAlphaNum(ResRange);
01073     ResRange += ReadWhite(ResRange);
01074     // get final residue number
01075     GetSegName(ResRange, SegName2);
01076     GetResNum(ResRange, ResNum2);
01077     // do some checks
01078     if (strcmp(SegName1, SegName2)!=0) {
01079       ProblemParsing("SegNames Differ", ResRange);
01080     }
01081     if (ResNum2 < ResNum1) {
01082       ProblemParsing("Decreasing Residues", ResRange);
01083     }
01084   }
01085 
01086   // otherwise, ResNum2 = ResNum1
01087   else {
01088     ResNum2 = ResNum1;
01089   }
01090 }
01091 
01092 
01093 int GetSegName(char* Str, char* SegName) {
01094 //-------------------------------------------------------------------
01095 // Str should be (segname, resnum) or (segname, resnum, atomname)
01096 // put segname into SegName
01097 // return the number of characters from start-of-Str thru segname
01098 //-------------------------------------------------------------------
01099   int    Count;
01100   char*  FullString=Str;
01101 
01102   if (Str[0] != '(') {ProblemParsing("Missing (", Str);}
01103   Str += 1;
01104   Str += ReadWhite(Str);
01105   Count = ReadAlphaNum(Str);
01106   if (Count == 0)    {ProblemParsing("Missing Segment Name", Str);}
01107   strncpy(SegName, Str, Count);
01108   SegName[Count] = '\0';
01109   Str += Count;
01110   return(Str-FullString);
01111 }
01112 
01113 
01114 int  GetResNum(char* Str, int& ResNum) {
01115 //-------------------------------------------------------------------
01116 // Str should be (segname, resnum) or (segname, resnum, atomname)
01117 // convert resnum to an int and return it
01118 // return the number of characters from start-of-Str thru resnum
01119 //-------------------------------------------------------------------
01120   int    Count;
01121   char   SegName[21];
01122   char*  FullString=Str;
01123 
01124   Str += GetSegName(Str, SegName);
01125   Str += ReadWhite(Str);
01126   ResNum = (int) strtol(Str, NULL, 10);
01127   Count = ReadDigits(Str);
01128   if (Count == 0) {ProblemParsing("Missing Residue Number", Str);}
01129   Str += Count;
01130   return(Str-FullString);
01131 }
01132 
01133 
01134 int GetAtomName(char* Str, char* AtomName) {
01135 //-------------------------------------------------------------------
01136 // Str should be (segname, resnum, atomname)
01137 // put atomname into AtomName
01138 // return the number of characters from start-of-Str thru ')'
01139 //-------------------------------------------------------------------
01140   int    Count, ResNum;
01141   char*  FullString=Str;
01142 
01143   Str += GetResNum(Str, ResNum);
01144   Str += ReadWhite(Str);
01145   Count = ReadAlphaNum(Str);
01146   if (Count == 0)    {ProblemParsing("Missing Atom Name", Str);}
01147   strncpy(AtomName, Str, Count);
01148   AtomName[Count] = '\0';
01149   Str += Count;
01150   Str += ReadWhite(Str);
01151   if (Str[0] != ')') {ProblemParsing("Missing )", Str);}
01152   Str += 1;
01153   return(Str-FullString);
01154 }
01155 
01156 
01157 item_t ReadNextItem(char* Str, int& NumChars) {
01158 //-------------------------------------------------------------------
01159 // Figure out what the next item in Str is, and how many characters
01160 // long it is.  The next item should be one of the following:
01161 //   1.  kStartGroup:       Group {
01162 //   2.  kEndGroup:         }
01163 //   3.  kAtomName:         atomname:
01164 //   4.  kAtomNameList:     (atomname, atomname, ... ):
01165 //   5.  kAtom:             (segname, resno, atomname)
01166 //   6.  kResidue:          (segname, resno)
01167 //   7.  kResidueRange:     (segname, resno) to (segname, resno)
01168 // The following assumptions may be made:
01169 //   1. Str is all lowercase
01170 //   2. There are NO leading white-char's
01171 // Return:
01172 //   The length of the next item, plus the white space that follows.
01173 //-------------------------------------------------------------------
01174   int     Num;
01175   item_t  RetVal=kUnknownItem;
01176 
01177   Num=IsStartGroup(Str);     if (Num)  {RetVal=kStartGroup;   goto Found;}
01178   Num=IsEndGroup(Str);       if (Num)  {RetVal=kEndGroup;     goto Found;}
01179   Num=IsAtomName(Str);       if (Num)  {RetVal=kAtomName;     goto Found;}
01180   Num=IsAtomNameList(Str);   if (Num)  {RetVal=kAtomNameList; goto Found;}
01181   Num=IsAtom(Str);           if (Num)  {RetVal=kAtom;         goto Found;}
01182   Num=IsResidue(Str);        if (Num)  {RetVal=kResidue;      goto Found;}
01183   Num=IsResidueRange(Str);   if (Num)  {RetVal=kResidueRange; goto Found;}
01184 
01185   // add the white-space after the item to the length of the item.
01186 Found:
01187   NumChars = Num;
01188   Str += NumChars;
01189   NumChars += ReadWhite(Str);
01190   return(RetVal);
01191 }
01192 
01193 
01194 int IsStartGroup(char* Str) {
01195 //-------------------------------------------------------------------
01196 // see if Str starts with "group {"
01197 // return:     the number of characters, including white space.
01198 //             0, if Str does not start with "group {"
01199 //-------------------------------------------------------------------
01200   char*  FullString=Str;
01201 
01202   if (strncmp(Str, "group", 5) == 0) {
01203     Str += 5;
01204     Str += ReadWhite(Str);
01205     if (Str[0] == '{') {
01206       Str += 1;
01207       return(Str-FullString);
01208     }
01209   }
01210   return(0);
01211 }
01212 
01213 
01214 int IsEndGroup(char* Str) {
01215 //-------------------------------------------------------------------
01216 // see if Str starts with "}"
01217 // return:    the number of characters, including white space.
01218 //            0, if Str does not start with "}"
01219 //-------------------------------------------------------------------
01220   if (Str[0] == '}') {
01221     return(1);
01222   }
01223   return(0);
01224 }
01225 
01226 
01227 int IsAtomName(char* Str) {
01228 //-------------------------------------------------------------------
01229 // see if Str starts with "atomname:"
01230 // return:    the number of characters, including white space.
01231 //            0, if Str does not start with "atomname:"
01232 //-------------------------------------------------------------------
01233   int    Count;
01234   char*  FullString=Str;
01235 
01236   Count = ReadAlphaNum(Str);
01237   if (Count) {
01238     Str += Count;
01239     Str += ReadWhite(Str);
01240     if (Str[0] == ':') {
01241       Str += 1;
01242       return(Str-FullString);
01243     }
01244   }
01245   return(0);
01246 }
01247 
01248 
01249 int IsAtomNameList(char* Str) {
01250 //------------------------------------------------------------------------
01251 // see if Str starts with "(atomname, atomname, ...):"
01252 // return:    the number of characters, including white space.
01253 //            0, if Str does not start with "(atomname, atomname, ...):"
01254 //------------------------------------------------------------------------
01255   int    Count;
01256   char*  FullString=Str;
01257 
01258   // Str will be considered an atom-name-list if it contains the following:
01259   // '(', anything, ')', ':'
01260   Count = ReadParentheses(Str);
01261   if (Count > 0) {
01262     Str += Count;
01263     Str += ReadWhite(Str);
01264     if (Str[0] == ':') {
01265       Str += 1;
01266       return(Str-FullString);
01267     }
01268   }
01269   return(0);
01270 }
01271 
01272 
01273 int IsAtom(char* Str) {
01274 //------------------------------------------------------------------------
01275 // see if Str starts with "(segname, resnum, atomname)"
01276 // return:    the number of characters, including white space.
01277 //            0, if Str does not start with "(segname, resnum, atomname)"
01278 //------------------------------------------------------------------------
01279   int    Count;
01280   char*  FullString=Str;
01281 
01282   // if char following the parentheses is ':', this isn't an atom
01283   if (IsAtomNameList(Str)) {
01284     return(0);
01285   }
01286   // Str must contain the following in sequence to be a legit atom
01287   // <ws> = optional white-space
01288   // '(', <ws>, alphanumeric, <ws>, numeric, <ws>, alphanumeric, <ws>, ')'
01289   if (Str[0] == '(') {
01290     Str += 1;
01291     Str += ReadWhite(Str);
01292     Count = ReadAlphaNum(Str);
01293     if (Count) {
01294       Str += Count;
01295       Str += ReadWhite(Str);
01296       Count = ReadDigits(Str);
01297       if (Count) {
01298         Str += Count;
01299         Str += ReadWhite(Str);
01300         Count = ReadAlphaNum(Str);
01301         if (Count) {
01302           Str += Count;
01303           Str += ReadWhite(Str);
01304           if (Str[0] == ')') {
01305             Str += 1;
01306             return(Str-FullString);
01307           }
01308         }
01309       }
01310     }
01311   }
01312   return(0);
01313 }
01314 
01315 
01316 int IsResidueRange(char* Str) {
01317 //------------------------------------------------------------------------
01318 // see if Str starts with "(segname, resnum) to (segname, resnum)"
01319 // return:    the number of characters, including white space.
01320 //            0, if Str does not start with "(sn, rn) to (sn, rn)"
01321 //------------------------------------------------------------------------
01322   int    Count;
01323   char*  FullString=Str;
01324 
01325   // Str must contain the following in sequence to be a legit res range
01326   // <ws> = optional white-space
01327   // residue, <ws>, "to", <ws>, residue
01328   Count = IsAResidue(Str);
01329   if (Count) {
01330     Str += Count;
01331     Str += ReadWhite(Str);
01332     if (strncmp(Str, "to", 2) == 0) {
01333       Str += 2;
01334       Str += ReadWhite(Str);
01335       Count = IsAResidue(Str);
01336       if (Count) {
01337         Str += Count;
01338         return(Str-FullString);
01339       }
01340     }
01341   }
01342   return(0);
01343 }
01344 
01345 
01346 int IsResidue(char* Str) {
01347 //------------------------------------------------------------------------
01348 // see if Str starts with "(segname, resnum)"
01349 // but not "(segname, resnum) to (segname, resnum)"
01350 //------------------------------------------------------------------------
01351   int Count;
01352 
01353   Count = IsAResidue(Str);
01354   if (Count) {
01355     if (IsResidueRange(Str)) {
01356       return(0);
01357     }
01358     else {
01359       return(Count);
01360     }
01361   }
01362   return(0);
01363 }
01364 
01365 
01366 int IsAResidue(char* Str) {
01367 //------------------------------------------------------------------------
01368 // see if Str starts with "(segname, resnum)"
01369 // return:    the number of characters, including white space.
01370 //            0, if Str does not start with "(segname, resnum)"
01371 //------------------------------------------------------------------------
01372   int    Count;
01373   char*  FullString=Str;
01374 
01375   // if char following the parentheses is ':', this isn't a residue
01376   if (IsAtomNameList(Str)) {
01377     return(0);
01378   }
01379   // Str must contain the following in sequence to be a legit residue
01380   // <ws> = optional white-space
01381   // '(', <ws>, alphanumeric, <ws>, numeric, <ws>, ')'
01382   if (Str[0] == '(') {
01383     Str += 1;
01384     Str += ReadWhite(Str);
01385     Count = ReadAlphaNum(Str);
01386     if (Count) {
01387       Str += Count;
01388       Str += ReadWhite(Str);
01389       Count = ReadDigits(Str);
01390       if (Count) {
01391         Str += Count;
01392         Str += ReadWhite(Str);
01393         if (Str[0] == ')') {
01394           Str += 1;
01395           return(Str-FullString);
01396         }
01397       }
01398     }
01399   }
01400   return(0);
01401 }
01402 
01403 
01404 int ReadParentheses(const char* Str) {
01405 //-------------------------------------------------------------------
01406 // count the number of characters from the leading '('
01407 // to the first ')' of Str (inclusive).
01408 //     no leading '('  =>  return  0
01409 //     no closing ')'  =>  return -1
01410 //-------------------------------------------------------------------
01411   const char* Str2;
01412 
01413   if (Str[0] != '(') {
01414     return(0);
01415   }
01416   Str2 = strchr(Str, ')');
01417   if (Str2 == NULL) {
01418     return(-1);
01419   }
01420   return((Str2-Str)+1);
01421 }
01422 
01423 
01424 int ReadAlpha(const char* Str) {
01425 //-------------------------------------------------------------------
01426 // determine the leading number of alphabetic characters in Str.
01427 //-------------------------------------------------------------------
01428   int  i=0;
01429 
01430   while (1) {
01431     if (isalpha(Str[i]) || Str[i]=='\'' || Str[i]=='\"' || Str[i] == '*') {
01432       i++;
01433     }
01434     else {
01435       break;
01436     }
01437   }
01438   return(i);
01439 }
01440 
01441 
01442 int ReadAlphaNum(const char* Str) {
01443 //-------------------------------------------------------------------
01444 // determine the leading number of alphanumeric characters in Str.
01445 //-------------------------------------------------------------------
01446   int  i=0;
01447 
01448   while (1) {
01449     if (isalnum(Str[i]) || Str[i]=='\'' || Str[i]=='\"' || Str[i] == '*') {
01450       i++;
01451     }
01452     else {
01453       break;
01454     }
01455   }
01456   return(i);
01457 }
01458 
01459 
01460 int ReadDigits(const char* Str) {
01461 //-------------------------------------------------------------------
01462 // determine the leading number of numeric characters in Str.
01463 //-------------------------------------------------------------------
01464   int  i=0;
01465 
01466   while (1) {
01467     if (isdigit(Str[i])) {
01468       i++;
01469     }
01470     else {
01471       break;
01472     }
01473   }
01474   return(i);
01475 }
01476 
01477 
01478 int ReadWhite(const char* Str) {
01479 //-------------------------------------------------------------------
01480 // determine the leading number of white characters in Str.
01481 // a white char is:
01482 //   space, tab, linefeed, carriage-return, formfeed,
01483 //   vertical-tab, and newline characters.
01484 // a white char is also (for the sake of this program):
01485 //   comma, semi-colon, and period.
01486 //-------------------------------------------------------------------
01487   int  i=0;
01488 
01489   // count the number of white-char's.  break at first non-white-char.
01490   while (1) {
01491     if (
01492          (Str[i] == 9)   ||      // tab
01493          (Str[i] == 10)  ||      // LF
01494          (Str[i] == 11)  ||      // vertical-tab
01495          (Str[i] == 12)  ||      // form-feed
01496          (Str[i] == 13)  ||      // CR
01497          (Str[i] == 32)  ||      // space
01498          (Str[i] == ',') ||      // comma
01499          (Str[i] == ';')         // semi-colon
01500 //         (Str[i] == '.')         // period  (took this out in case of =.4, eg)
01501        )
01502     {    
01503       i++;
01504     }
01505     else {
01506       break;
01507     }
01508   }
01509   return(i);
01510 }
01511 
01512 
01513 void ToLower(char* Str) {
01514 //-------------------------------------------------------------------
01515 // convert Str to all lower case
01516 //-------------------------------------------------------------------
01517   for (unsigned int i=0; i<strlen(Str); i++) {
01518     Str[i] = (char)tolower(Str[i]);
01519   }
01520 }
01521 

Generated on Mon Nov 20 01:17:12 2017 for NAMD by  doxygen 1.4.7