InputDataLoader.cpp
上传用户:chinafayin
上传日期:2022-04-05
资源大小:153k
文件大小:42k
源码类别:

并行计算

开发平台:

Visual C++

  1. /*
  2.     FastGrid (formerly AutoGrid)
  3.     Copyright (C) 2009 The Scripps Research Institute. All rights reserved.
  4.     Copyright (C) 2009 Masaryk University. All rights reserved.
  5.     AutoGrid is a Trade Mark of The Scripps Research Institute.
  6.     This program is free software; you can redistribute it and/or
  7.     modify it under the terms of the GNU General Public License
  8.     as published by the Free Software Foundation; either version 2
  9.     of the License, or (at your option) any later version.
  10.     This program is distributed in the hope that it will be useful,
  11.     but WITHOUT ANY WARRANTY; without even the implied warranty of
  12.     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13.     GNU General Public License for more details.
  14.     You should have received a copy of the GNU General Public License
  15.     along with this program; if not, write to the Free Software
  16.     Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
  17. */
  18. #include <cstring>
  19. #include <cctype>
  20. #include <climits>
  21. #include "InputDataLoader.h"
  22. #include "Utils.h"
  23. #include "Exceptions.h"
  24. // GPF tokens
  25. enum GPFTokens
  26. {
  27.     GPF_NULL = 0,
  28.     GPF_COMMENT,
  29.     GPF_RECEPTOR,
  30.     GPF_GRIDFLD,
  31.     GPF_NPTS,
  32.     GPF_SPACING,
  33.     GPF_GRIDCENTER,
  34.     GPF_LIGAND_TYPES,
  35.     GPF_MAP,
  36.     GPF_NBP_COEFFS,
  37.     GPF_NBP_R_EPS,
  38.     GPF_ELECMAP,
  39.     GPF_DIEL,
  40.     GPF_FMAP,
  41.     GPF_DISORDER,
  42.     GPF_SMOOTH,
  43.     GPF_SOL_PAR,
  44.     GPF_CONSTANT,
  45.     GPF_COVALENTMAP,
  46.     GPF_RECEPTOR_TYPES,
  47.     GPF_PARAM_FILE,
  48.     GPF_DSOLVMAP,
  49.     GPF_QASP
  50. };
  51. InputDataLoader::InputDataLoader(LogFile *logFile): logFile(logFile)
  52. {
  53.     fldFilenameAVS[0] = 0;
  54.     floatingGridFilename[0] = 0;
  55.     receptorFilename[0] = 0;
  56.     xyzFilename[0] = 0;
  57.     parameterLibraryFilename[0] = 0;
  58.     memset(receptorTypes, 0, sizeof(receptorTypes));
  59.     numReceptorTypes = 0;
  60.     numGridPointsPerMap = INIT_NUM_GRID_PTS;
  61.     numReceptorAtoms = 0;
  62.     covalentPoint = 0;
  63.     // for NEW3 desolvation terms
  64.     solparQ = .01097;   // unweighted value restored 3:9:05
  65.     invDielCal = 0;
  66.     rSmooth = 0;
  67.     gridSpacing = 0.375;     // One quarter of a C-C bond length.
  68.     covHalfWidthSquaredInv = 1.0;
  69.     covBarrier = 1000.0;
  70.     distDepDiel = false;
  71.     disorderH = false;
  72.     receptorAtom = 0;
  73. }
  74. InputDataLoader::~InputDataLoader()
  75. {
  76.     if (receptorAtom)
  77.     {
  78.         delete [] charge;
  79.         delete [] vol;
  80.         delete [] solpar;
  81.         delete [] atomType;
  82.         delete [] hbond;
  83.         delete [] receptorAtom;
  84.     }
  85. }
  86. void InputDataLoader::load(const char *gridParameterFilename, GridMapList &gridmaps, ParameterLibrary &parameterLibrary)
  87. {
  88.     // LIGAND: maximum is MAX_MAPS
  89.     // each type is now at most two characters plus ''
  90.     // currently ligandAtomTypes is sparse... some types are not set
  91.     char ligandTypes[MAX_MAPS][3] = {0};
  92.     // number of different receptor atom types declared on receptorTypes line in GPF
  93.     int receptor_types_gpf_ct = 0;
  94.     int has_receptor_types_in_gpf = 0;
  95.     // array of numbers of each type
  96.     // NB: this is a sparse int array, some entries are 0
  97.     int receptor_atom_type_count[NUM_RECEPTOR_TYPES] = {0};
  98.     Vec3d gridExtent;
  99.     Vec3d gridCornerMax;
  100.     Vec3d cmax = -BIG;
  101.     Vec3d cmin = BIG;
  102.     Vec3d csum = 0;
  103.     Vec3d cmean;
  104.     // LINE_LEN
  105.     char line[LINE_LEN];
  106.     char GPFLine[LINE_LEN];
  107.     int length = LINE_LEN;
  108.     char atom_name[6];
  109.     char record[LINE_LEN];
  110.     char temp_char = ' ';
  111.     char token[LINE_LEN];
  112.     static const char xyz[] = "xyz"; // used to print headings
  113.     FILE *receptorFile, *xyz_fileptr = 0;
  114.     double q_tot = 0.0;
  115.     double diel;
  116.     double q_max = -BIG, q_min = BIG;
  117.     double ri;
  118.     double temp_vol, temp_solpar;
  119.     int GPF_keyword = -1;
  120.     int indcom = 0;
  121.     int infld;
  122.     int mapIndex = -1;
  123.     // Initializes the grid parameter file
  124.     FILE *GPF = stdin;
  125.     if (gridParameterFilename[0])
  126.     {
  127.         GPF = boincOpenFile(gridParameterFilename, "r");
  128.         if (!GPF)
  129.         {
  130.             logFile->printErrorFormatted(ERROR, "Sorry, I can't find or open Grid Parameter File "%s"", gridParameterFilename);
  131.             logFile->printErrorFormatted(ERROR, "Unsuccessful Completion.n");
  132.             throw ExitProgram(911);
  133.         }
  134.     }
  135.     // Read in the grid parameter file...
  136.     ParameterEntry thisparm;
  137.     ParameterEntry *foundParam;
  138.     while (fgets(GPFLine, LINE_LEN, GPF) != 0)
  139.     {
  140.         GPF_keyword = parseGPFLine(GPFLine);
  141.         // This first "switch" figures out how to echo the current GPF line.
  142.         switch (GPF_keyword)
  143.         {
  144.         case -1:
  145.             logFile->printFormatted("GPF> %s", GPFLine);
  146.             logFile->printError(WARNING, "Unrecognized keyword in grid parameter file.n");
  147.             continue;           // while fgets GPFLine...
  148.         case GPF_NULL:
  149.         case GPF_COMMENT:
  150.             logFile->printFormatted("GPF> %s", GPFLine);
  151.             break;
  152.         default:
  153.             logFile->printFormatted("GPF> %s", GPFLine);
  154.             indcom = strIndex(GPFLine, "#");
  155.             if (indcom != -1)
  156.                 GPFLine[indcom] = '';    // Truncate str. at the comment
  157.             break;
  158.         }                       // first switch
  159.         // This second switch interprets the current GPF line.
  160.         switch (GPF_keyword)
  161.         {
  162.         case GPF_NULL:
  163.         case GPF_COMMENT:
  164.             break;
  165.         case GPF_RECEPTOR:
  166.             {
  167.                 // read in the receptor gridParameterFilename
  168.                 sscanf(GPFLine, "%*s %s", receptorFilename);
  169.                 logFile->printFormatted("nReceptor Input File :t%snnReceptor Atom Type Assignments:nn", receptorFilename);
  170.                 // try to open receptor file
  171.                 if ((receptorFile = boincOpenFile(receptorFilename, "r")) == 0)
  172.                 {
  173.                     logFile->printErrorFormatted(ERROR, "can't find or open receptor PDBQT file "%s".n", receptorFilename);
  174.                     logFile->printError(FATAL_ERROR, "Unsuccessful completion.nn");
  175.                 }
  176.                 // get the upper bound of total number of atoms
  177.                 fseek(receptorFile, 0, SEEK_END);
  178.                 int sizeOfFile = ftell(receptorFile);
  179.                 fseek(receptorFile, 0, SEEK_SET);
  180.                 char *fileContent = new char[sizeOfFile];
  181.                 if (!fread(fileContent, sizeOfFile, 1, receptorFile))
  182.                     logFile->printError(FATAL_ERROR, "Cannot read the receptor file.");
  183.                 fseek(receptorFile, 0, SEEK_SET);
  184.                 int numAtomsMax = 1;
  185.                 for (int i = 0; i < sizeOfFile; i++)
  186.                     if (fileContent[i] == 'n')
  187.                         ++numAtomsMax;
  188.                 
  189.                 delete [] fileContent; 
  190.                 
  191.                 // reserve space for atoms
  192.                 charge = new double[numAtomsMax];
  193.                 vol = new double[numAtomsMax];
  194.                 solpar = new double[numAtomsMax];
  195.                 atomType = new int[numAtomsMax];
  196.                 hbond = new HBondType[numAtomsMax];
  197.                 receptorAtom = new Vec4d[numAtomsMax];
  198.                 // start to read in the lines of the receptor file
  199.                 int ia = 0;
  200.                 while ((fgets(line, length, receptorFile)) != 0)
  201.                 {
  202.                     sscanf(line, "%6s", record);
  203.                     if (strncmp(record, "ATOM", 4) == 0 || // Amino Acid or DNA/RNA atoms
  204.                         strncmp(record, "HETA", 4) == 0 || // Non-standard heteroatoms
  205.                         strncmp(record, "CHAR", 4) == 0)
  206.                     {
  207.                         // Partial Atomic Charge - not a PDB record
  208.                         strncpy(atom_name, &line[12], 4);
  209.                         /* atom_name is declared as an array of 6 characters, the PDB atom name is 4 characters (C indices 0, 1, 2 and 3) but let's ensure that the fifth character (C index 4)
  210.                            is a null character, which terminates the string. */
  211.                         atom_name[4] = '';
  212.                         // Output the serial number of this atom...
  213.                         logFile->printFormatted("Atom no. %2d, "%s"", ia + 1, atom_name);
  214.                         // Read in this receptor atom's coordinates,partial charges, and solvation parameters in PDBQS format...
  215.                         sscanf(&line[30], "%lf", &receptorAtom[ia].x);
  216.                         sscanf(&line[38], "%lf", &receptorAtom[ia].y);
  217.                         sscanf(&line[46], "%lf", &receptorAtom[ia].z);
  218.                         // Output the coordinates of this atom...
  219.                         logFile->printFormatted(" at (%.3lf, %.3lf, %.3lf), ", receptorAtom[ia].x, receptorAtom[ia].y, receptorAtom[ia].z);
  220.                         // 1:CHANGE HERE: need to set up vol and solpar
  221.                         sscanf(&line[70], "%lf", &charge[ia]);
  222.                         sscanf(&line[77], "%s", thisparm.autogridType);
  223.                         foundParam = parameterLibrary.findAtomParameter(thisparm.autogridType);
  224.                         if (foundParam != 0)
  225.                         {
  226.                             logFile->printFormatted("DEBUG: foundParam->recIndex = %d", foundParam->recIndex);
  227.                             if (foundParam->recIndex < 0)
  228.                             {
  229.                                 strncpy(receptorTypes[numReceptorTypes], foundParam->autogridType, 3);
  230.                                 foundParam->recIndex = numReceptorTypes++;
  231.                                 logFile->printFormatted("DEBUG: foundParam->recIndex => %d", foundParam->recIndex);
  232.                             }
  233.                             atomType[ia] = foundParam->recIndex;
  234.                             solpar[ia] = foundParam->solpar;
  235.                             vol[ia] = foundParam->vol;
  236.                             hbond[ia] = foundParam->hbond;  // NON=0, DS,D1, AS, A1, A2
  237.                             ++receptor_atom_type_count[foundParam->recIndex];
  238.                         }
  239.                         else
  240.                         {
  241.                             logFile->printFormatted("nnreceptor file contains unknown type: '%s'nadd parameters for it to the parameter library firstn", thisparm.autogridType);
  242.                             throw ExitProgram(-1);
  243.                         }
  244.                         // if from pdbqs: convert cal/molA**3 to kcal/molA**3
  245.                         // solpar[ia] *= 0.001;
  246.                         q_max = Mathd::Max(q_max, charge[ia]);
  247.                         q_min = Mathd::Min(q_min, charge[ia]);
  248.                         if (atom_name[0] == ' ')
  249.                         {
  250.                             // truncate the first character...
  251.                             atom_name[0] = atom_name[1];
  252.                             atom_name[1] = atom_name[2];
  253.                             atom_name[2] = atom_name[3];
  254.                             atom_name[3] = '';
  255.                         }
  256.                         else if ((atom_name[0] == '0' || atom_name[0] == '1' || atom_name[0] == '2' ||
  257.                                  atom_name[0] == '3' || atom_name[0] == '4' || atom_name[0] == '5' ||
  258.                                  atom_name[0] == '6' || atom_name[0] == '7' || atom_name[0] == '8' ||
  259.                                  atom_name[0] == '9') && atom_name[1] == 'H')
  260.                         {
  261.                             /* Assume this is the 'mangled' name of a hydrogen atom, after the atom name has been changed from 'HD21' to '1HD2' for example. [0-9]H(.)(.) 0 1 2 3 : : :
  262.                                : V V V V tmp 0 1 2 tmp : V 0 1 2 3 : : : : V V V V H(.)(.)[0-9] */
  263.                             temp_char = atom_name[0];
  264.                             atom_name[0] = atom_name[1];
  265.                             atom_name[1] = atom_name[2];
  266.                             atom_name[2] = atom_name[3];
  267.                             atom_name[3] = temp_char;
  268.                         }
  269.                         // Tell the user what you thought this atom was...
  270.                         logFile->printFormatted(" was assigned atom type "%s" (recIndex= %d, atomType= %d).n", foundParam->autogridType, foundParam->recIndex, atomType[ia]);
  271.                         // Count the number of each atom type
  272.                         // ++receptor_atom_type_count[ atomType[ia] ];
  273.                         // Keep track of the extents of the receptor
  274.                         for (int i = 0; i < 3; i++)
  275.                         {
  276.                             cmax[i] = Mathd::Max(cmax[i], receptorAtom[ia][i]);
  277.                             cmin[i] = Mathd::Min(cmin[i], receptorAtom[ia][i]);
  278.                         }
  279.                         csum += Vec3d(receptorAtom[ia]);
  280.                         // Total up the partial charges as we go...
  281.                         q_tot += charge[ia];
  282.                         // Increment the atom counter
  283.                         ia++;
  284.                         // Check that there aren't too many atoms...
  285.                         if (ia > AG_MAX_ATOMS)
  286.                         {
  287.                             logFile->printErrorFormatted(ERROR, "Too many atoms in receptor PDBQT file %s;", receptorFilename);
  288.                             logFile->printErrorFormatted(ERROR, "-- the maximum number of atoms, AG_MAX_ATOMS, allowed is %ul.", AG_MAX_ATOMS);
  289.                             logFile->printErrorFormatted(SUGGESTION, "Increase the value in the "#define AG_MAX_ATOMS %ul" line", AG_MAX_ATOMS);
  290.                             logFile->printError(SUGGESTION, "in the source file "autogrid.h", and re-compile " APPNAME ".");
  291.                             // FATAL_ERROR will cause this program to exit...
  292.                             logFile->printError(FATAL_ERROR, "Sorry, " APPNAME " cannot continue.");
  293.                         }           // endif
  294.                     }               // endif
  295.                 }                   // endwhile
  296.                 // Finished reading in the lines of the receptor file
  297.                 fclose(receptorFile);
  298.                 if (has_receptor_types_in_gpf == 1)
  299.                     // Check that the number of atom types found in the receptor PDBQT
  300.                     // file match the number parsed in by the "receptorTypes" command
  301.                     // in the GPF; if they do not match, exit!
  302.                     if (numReceptorTypes != receptor_types_gpf_ct)
  303.                     {
  304.                         logFile->printErrorFormatted(ERROR,
  305.                             "The number of atom types found in the receptor PDBQT (%d) does not match the number specified by the "receptor_types" command (%d) in the GPF!nn",
  306.                             numReceptorTypes, receptor_types_gpf_ct);
  307.                         // FATAL_ERROR will cause this program to exit...
  308.                         logFile->printError(FATAL_ERROR, "Sorry, " APPNAME " cannot continue.");
  309.                     }
  310.                 // Update the total number of atoms in the receptor
  311.                 numReceptorAtoms = ia;
  312.                 logFile->printFormatted("nMaximum partial atomic charge found = %+.3lf en", q_max);
  313.                 logFile->printFormatted("Minimum partial atomic charge found = %+.3lf enn", q_min);
  314.                 // Check there are partial charges...
  315.                 if (q_max == 0 && q_min == 0)
  316.                 {
  317.                     logFile->printErrorFormatted(ERROR, "No partial atomic charges were found in the receptor PDBQT file %s!nn", receptorFilename);
  318.                     // FATAL_ERROR will cause this program to exit...
  319.                     logFile->printError(FATAL_ERROR, "Sorry, " APPNAME " cannot continue.");
  320.                 }                   // if there are no charges EXIT
  321.                 logFile->print("AtomtAtomtNumber of this Typen"
  322.                               "Typet ID t in Receptorn"
  323.                               "____t____t___________________n");
  324.                 // 2. CHANGE HERE: need to count number of each receptor_type
  325.                 for (int ia = 0; ia < numReceptorTypes; ia++)
  326.                     if (receptor_atom_type_count[ia] != 0)
  327.                         logFile->printFormatted(" %dt %stt%6dn", (ia), receptorTypes[ia], receptor_atom_type_count[ia]);
  328.                 logFile->printFormatted("nTotal number of atoms :tt%d atoms n"
  329.                                        "Total charge :ttt%.2lf en"
  330.                                        "nnReceptor coordinates fit within the following volume:nn"
  331.                                        "                   _______(%.1lf, %.1lf, %.1lf)n"
  332.                                        "                  /|     /|n"
  333.                                        "                 / |    / |n"
  334.                                        "                /______/  |n"
  335.                                        "                |  |___|__| Midpoint = (%.1lf, %.1lf, %.1lf)n"
  336.                                        "                |  /   |  /n"
  337.                                        "                | /    | /n"
  338.                                        "                |/_____|/n"
  339.                                        "(%.1lf, %.1lf, %.1lf)      n"
  340.                                        "nMaximum coordinates :tt(%.3lf, %.3lf, %.3lf)n"
  341.                                        "Minimum coordinates :tt(%.3lf, %.3lf, %.3lf)nn"
  342.                                        "n",
  343.                                        numReceptorAtoms, q_tot, cmax.x, cmax.y, cmax.z,
  344.                                        (cmax.x + cmin.x) / 2, (cmax.y + cmin.y) / 2, (cmax.z + cmin.z) / 2,
  345.                                        cmin.x, cmin.y, cmin.z, cmax.x, cmax.y, cmax.z, cmin.x, cmin.y, cmin.z);
  346.                 cmean[0] = csum[0] / numReceptorAtoms;
  347.                 cmean[1] = csum[1] / numReceptorAtoms;
  348.                 cmean[2] = csum[2] / numReceptorAtoms;
  349.             }
  350.             break;
  351.         case GPF_GRIDFLD:
  352.             sscanf(GPFLine, "%*s %s", fldFilenameAVS);
  353.             infld = strIndex(fldFilenameAVS, ".fld");
  354.             if (infld == -1)
  355.                 logFile->printError(FATAL_ERROR, "Grid data file needs the extension ".fld" for AVS inputnn");
  356.             else
  357.             {
  358.                 infld = strIndex(fldFilenameAVS, "fld");
  359.                 strncpy(xyzFilename, fldFilenameAVS, MAX_CHARS);
  360.                 xyzFilename[infld] = 'x';
  361.                 xyzFilename[infld + 1] = 'y';
  362.                 xyzFilename[infld + 2] = 'z';
  363.             }
  364.             if ((xyz_fileptr = boincOpenFile(xyzFilename, "w")) == 0)
  365.             {
  366.                 logFile->printErrorFormatted(ERROR, "can't create grid extrema data file %sn", xyzFilename);
  367.                 logFile->printError(ERROR, "SORRY!    unable to create the ".xyz" file.nn");
  368.                 logFile->printError(FATAL_ERROR, "Unsuccessful completion.nn");
  369.             }
  370.             else
  371.                 logFile->printFormatted("nCreating (AVS-readable) grid-coordinates extrema file : %snn", xyzFilename);
  372.             break;
  373.         case GPF_NPTS:
  374.             {
  375.                 Vec3i numGridPointsMinusOne;
  376.                 sscanf(GPFLine, "%*s %d %d %d", &numGridPointsMinusOne.x, &numGridPointsMinusOne.y, &numGridPointsMinusOne.z);
  377.                 // numGridPointsMinusOne mustn't be negative, shouldn't be zero or larger than MAX_GRID_PTS and should be even
  378.                 for (int i = 0; i < 3; i++)
  379.                     numGridPointsMinusOne[i] = checkSize(numGridPointsMinusOne[i], xyz[i]);
  380.                 numGridPointsDiv2 = numGridPointsMinusOne / 2;
  381.                 numGridPoints = numGridPointsMinusOne + 1;
  382.                 logFile->printFormatted("nNumber of grid points in x-direction:t%dn"
  383.                                        "Number of grid points in y-direction:t%dn"
  384.                                        "Number of grid points in z-direction:t%dnn",
  385.                                        numGridPoints.x, numGridPoints.y, numGridPoints.z);
  386.                 numGridPointsPerMap = numGridPoints.Cube();
  387.             }
  388.             break;
  389.         case GPF_SPACING:
  390.             sscanf(GPFLine, "%*s %lf", &gridSpacing);
  391.             logFile->printFormatted("Grid Spacing :ttt%.3lf Angstromnn", gridSpacing);
  392.             break;
  393.         case GPF_GRIDCENTER:
  394.             sscanf(GPFLine, "%*s %s", token);
  395.             if (strncmp(token, "auto", 4) == 0)
  396.             {
  397.                 gridCenter = cmean;
  398.                 logFile->printFormatted("Grid maps will be centered on the center of mass.n"
  399.                                        "Coordinates of center of mass : (%.3lf, %.3lf, %.3lf)n", gridCenter.x, gridCenter.y, gridCenter.z);
  400.             }
  401.             else
  402.             {
  403.                 sscanf(GPFLine, "%*s %lf %lf %lf", &gridCenter.x, &gridCenter.y, &gridCenter.z);
  404.                 logFile->printFormatted("nGrid maps will be centered on user-defined coordinates:nntt(%.3lf, %.3lf, %.3lf)n", gridCenter.x, gridCenter.y, gridCenter.z);
  405.             }
  406.             // centering stuff...
  407.             for (int ia = 0; ia < numReceptorAtoms; ia++)
  408.                 *((Vec3d*)&receptorAtom[ia]) -= gridCenter;  // transform to center of gridmaps
  409.             gridExtent = Vec3d(numGridPointsDiv2) * gridSpacing;
  410.             gridCornerMax = gridCenter + gridExtent;
  411.             gridCornerMin = gridCenter - gridExtent;
  412.             logFile->printFormatted("nGrid maps will cover the following volume:nn"
  413.                                    "                   _______(%.1lf, %.1lf, %.1lf)n"
  414.                                    "                  /|     /|n"
  415.                                    "                 / |    / |n"
  416.                                    "                /______/  |n"
  417.                                    "                |  |___|__| Midpoint = (%.1lf, %.1lf, %.1lf)n"
  418.                                    "                |  /   |  /n"
  419.                                    "                | /    | /n"
  420.                                    "                |/_____|/n"
  421.                                    "(%.1lf, %.1lf, %.1lf)      nn", gridCornerMax.x, gridCornerMax.y, gridCornerMax.z,
  422.                                    gridCenter.x, gridCenter.y, gridCenter.z, gridCornerMin.x, gridCornerMin.y, gridCornerMin.z);
  423.             for (int i = 0; i < 3; i++)
  424.                 logFile->printFormatted("Grid map %c-dimension :tt%.1lf Angstromsn", xyz[i], 2 * gridExtent[i]);
  425.             logFile->printFormatted("nMaximum coordinates :tt(%.3lf, %.3lf, %.3lf)n"
  426.                                    "Minimum coordinates :tt(%.3lf, %.3lf, %.3lf)nn", gridCornerMax.x, gridCornerMax.y, gridCornerMax.z, gridCornerMin.x, gridCornerMin.y, gridCornerMin.z);
  427.             for (int i = 0; i < 3; i++)
  428.                 fprintf(xyz_fileptr, "%.3lf %.3lfn", gridCornerMin[i], gridCornerMax[i]);
  429.             fclose(xyz_fileptr);
  430.             break;
  431.         case GPF_LIGAND_TYPES:
  432.             {
  433.                 // Read in the list of atom types in the ligand.
  434.                 // GPFLine e.g.: "ligand_types N O A C HH NH"
  435.                 // array of ptrs used to parse input line
  436.                 char *ligandAtomTypes[MAX_MAPS];
  437.                 int numAtomMaps = parseTypes(GPFLine, ligandAtomTypes, MAX_ATOM_TYPES);
  438.                 for (int i = 0; i < numAtomMaps; i++)
  439.                     strncpy(ligandTypes[i], ligandAtomTypes[i], 3);
  440.                 for (int i = 0; i < numAtomMaps; i++)
  441.                 {
  442.                     foundParam = parameterLibrary.findAtomParameter(ligandTypes[i]);
  443.                     if (foundParam)
  444.                         foundParam->mapIndex = i;
  445.                     else
  446.                     {
  447.                         // return error here
  448.                         logFile->printFormatted("unknown ligand atom type %snadd parameters for it to the parameter library first!n", ligandAtomTypes[i]);
  449.                         throw ExitProgram(-1);
  450.                     }
  451.                 }
  452.                 // Check to see if there is enough memory to store these map objects
  453.                 gridmaps.setNumMaps(numAtomMaps+2);
  454.                 if (numGridPointsPerMap == INIT_NUM_GRID_PTS)
  455.                 {
  456.                     logFile->printError(ERROR, "You need to set the number of grid points using "npts" before setting the ligand atom types, using "ligand_types".n");
  457.                     logFile->printError(FATAL_ERROR, "Unsuccessful completion.nn");
  458.                 }
  459.                 for (int i = 0; i < numAtomMaps; i++)
  460.                 {
  461.                     strncpy(gridmaps[i].type, ligandTypes[i], 3);   // eg HD or OA or NA or N
  462.                     foundParam = parameterLibrary.findAtomParameter(ligandTypes[i]);
  463.                     if (strcmp(ligandTypes[i], "Z") == 0)
  464.                     {
  465.                         logFile->print("Found covalent map atomtypen");
  466.                         gridmaps[i].isCovalent = true;
  467.                     }
  468.                     gridmaps[i].atomType = foundParam->mapIndex;
  469.                     gridmaps[i].solparProbe = foundParam->solpar;
  470.                     gridmaps[i].volProbe = foundParam->vol;
  471.                     gridmaps[i].Rij = foundParam->Rij;
  472.                     gridmaps[i].epsij = foundParam->epsij;
  473.                     gridmaps[i].hbond = foundParam->hbond;
  474.                     gridmaps[i].RijHB = foundParam->RijHB;
  475.                     gridmaps[i].epsijHB = foundParam->epsijHB;
  476.                     if (gridmaps[i].hbond > 0)
  477.                         gridmaps[i].isHBonder = true;
  478.                     for (int j = 0; j < numReceptorTypes; j++)
  479.                     {
  480.                         foundParam = parameterLibrary.findAtomParameter(receptorTypes[j]);
  481.                         gridmaps[i].nbpR[j] = (gridmaps[i].Rij + foundParam->Rij) / 2;
  482.                         gridmaps[i].nbpEps[j] = sqrt(gridmaps[i].epsij * foundParam->epsij);
  483.                         // apply the vdW forcefield parameter/weight here
  484.                         // This was removed because "setup_p_l" does this for us... gridmaps[i].nbpEps[j] *= FE_coeff_vdW;
  485.                         gridmaps[i].xA[j] = 12;
  486.                         // setup hbond dependent stuff
  487.                         gridmaps[i].xB[j] = 6;
  488.                         gridmaps[i].hbonder[j] = 0;
  489.                         if (gridmaps[i].hbond > D1 && (foundParam->hbond == DS || foundParam->hbond == D1))
  490.                         {
  491.                             // AS,A1,A2 map vs DS,D1 probe
  492.                             gridmaps[i].xB[j] = 10;
  493.                             gridmaps[i].hbonder[j] = 1;
  494.                             gridmaps[i].isHBonder = true;
  495.                             // Rij and epsij for this hb interaction in parm_data.dat file as Rii and epsii for heavy atom hb factors
  496.                             gridmaps[i].nbpR[j] = gridmaps[i].RijHB;
  497.                             gridmaps[i].nbpEps[j] = gridmaps[i].epsijHB;
  498.                             // apply the hbond forcefield parameter/weight here
  499.                             // This was removed because "setup_p_l" does this for us... gridmaps[i].nbpEps[j] *= FE_coeff_hbond;
  500.                         }
  501.                         else if ((gridmaps[i].hbond == DS || gridmaps[i].hbond == D1) && foundParam->hbond > D1)
  502.                         {
  503.                             // DS,D1 map vs AS,A1,A2 probe
  504.                             gridmaps[i].xB[j] = 10;
  505.                             gridmaps[i].hbonder[j] = 1;
  506.                             gridmaps[i].isHBonder = true;
  507.                             // Rij and epsij for this hb interaction in parm_data.dat file as Rii and epsii for heavy atom hb factors
  508.                             gridmaps[i].nbpR[j] = foundParam->RijHB;
  509.                             gridmaps[i].nbpEps[j] = foundParam->epsijHB;
  510.                             // apply the hbond forcefield parameter/weight here
  511.                             // This was removed because "setup_p_l" does this for us... gridmaps[i].nbpEps[j] *= FE_coeff_hbond;
  512.                         }
  513.                     }              // initialize energy parms for each possible receptor type
  514.                 }                   // for each map
  515.                 logFile->printFormatted("nAtom type names for ligand atom types 1-%d used for ligand-atom affinity grid maps:nn", numAtomMaps);
  516.                 for (int i = 0; i < numAtomMaps; i++)
  517.                 {
  518.                     logFile->printFormatted("tttAtom type number %d corresponds to atom type name "%s".n", i, gridmaps[i].type);
  519.                     if (gridmaps[i].isCovalent)
  520.                         logFile->printFormatted("nAtom type number %d will be used to calculate a covalent affinity grid mapnn", i + 1);
  521.                 }
  522.                 logFile->print("nn");
  523.             }
  524.             break;
  525.         case GPF_RECEPTOR_TYPES:
  526.             {
  527.                 // Read in the list of atom types in the receptor.
  528.                 // GPFLine e.g.: "receptorTypes N O A C HH NH"
  529.                 //
  530.                 // NOTE: This line is not guaranteed to match the actual
  531.                 // atom types present in the receptor PDBQT file
  532.                 // specified by the "receptor" command.
  533.                 // array of ptrs used to parse input line
  534.                 char *receptor_atom_types[NUM_RECEPTOR_TYPES];
  535.                 numReceptorTypes = parseTypes(GPFLine, receptor_atom_types, MAX_ATOM_TYPES);
  536.                 receptor_types_gpf_ct = numReceptorTypes;
  537.                 has_receptor_types_in_gpf = 1;
  538.                 for (int i = 0; i < numReceptorTypes; i++)
  539.                     strncpy(receptorTypes[i], receptor_atom_types[i], 3);
  540.                 for (int i = 0; i < numReceptorTypes; i++)
  541.                 {
  542.                     foundParam = parameterLibrary.findAtomParameter(receptor_atom_types[i]);
  543.                     if (foundParam != 0)
  544.                         foundParam->recIndex = i;
  545.                     else
  546.                     {
  547.                         logFile->printErrorFormatted(ERROR, "Unknown receptor type: "%s"n -- Add parameters for it to the parameter library first!n", receptor_atom_types[i]);
  548.                         logFile->printError(FATAL_ERROR, "Unsuccessful completion.nn");
  549.                     }
  550.                 }
  551.             }
  552.             break;
  553.         case GPF_SOL_PAR:      // THIS IS OBSOLETE!!!
  554.             // Read volume and solvation parameter for probe:
  555.             sscanf(GPFLine, "%*s %s %lf %lf", thisparm.autogridType, &temp_vol, &temp_solpar);
  556.             foundParam = parameterLibrary.findAtomParameter(thisparm.autogridType);
  557.             if (foundParam != 0)
  558.             {
  559.                 foundParam->vol = temp_vol;
  560.                 foundParam->solpar = temp_solpar;
  561.                 int i = foundParam->mapIndex;
  562.                 if (i >= 0)
  563.                 {
  564.                     // DON'T!!!
  565.                     // convert cal/molA^3 to kcal/molA^3
  566.                     // gridmaps[i].solparProbe = temp_solpar * 0.001;
  567.                     gridmaps[i].solparProbe = temp_solpar;
  568.                     logFile->printFormatted("nProbe %s solvation parameters: nntatomic fragmental volume: %.2f A^3ntatomic solvation parameter: %.4f cal/mol A^3nn",
  569.                                   foundParam->autogridType, foundParam->vol, foundParam->solpar);
  570.                 }
  571.             }
  572.             else
  573.                 logFile->printFormatted("%s key not foundn", thisparm.autogridType);
  574.             break;              // end solvation parameter
  575.         case GPF_MAP:
  576.             /* The variable "mapIndex" is the 0-based index of the ligand atom type we are calculating a map for. If the "types" line was CNOSH, there would be 5 ligand atom maps to
  577.                calculate, and since "mapIndex" is initialized to -1, mapIndex will increment each time there is a "map" keyword in the GPF.  The value of mapIndex should therefore go
  578.                from 0 to 4 for each "map" keyword. In this example, numAtomMaps would be 5, and numAtomMaps-1 would be 4, so if mapIndex is > 4, there is something wrong in the
  579.                number of "map" keywords. */
  580.             ++mapIndex;
  581.             if (mapIndex >= gridmaps.getNumAtomMaps())
  582.             {
  583.                 logFile->printErrorFormatted(ERROR,
  584.                     "Too many "map" keywords (%d);  the "ligand_types" command declares only %d atom types.nRemove a "map" keyword from the GPF.n",
  585.                     mapIndex + 1, gridmaps.getNumAtomMaps());
  586.                 logFile->printError(FATAL_ERROR, "Unsuccessful completion.nn");
  587.             }
  588.             // Read in the gridParameterFilename for this grid map
  589.             sscanf(GPFLine, "%*s %s", gridmaps[mapIndex].filename);
  590.             logFile->printFormatted("nOutput Grid Map %d:   %snn", (mapIndex + 1), gridmaps[mapIndex].filename);
  591.             break;
  592.         case GPF_ELECMAP:
  593.             sscanf(GPFLine, "%*s %s", gridmaps.getElectrostaticMap().filename);
  594.             logFile->printFormatted("nOutput Electrostatic Potential Energy Grid Map: %snn", gridmaps.getElectrostaticMap().filename);
  595.             break;
  596.         case GPF_DSOLVMAP:
  597.             sscanf(GPFLine, "%*s %s", gridmaps.getDesolvationMap().filename);
  598.             logFile->printFormatted("nOutput Desolvation Free Energy Grid Map: %snn", gridmaps.getDesolvationMap().filename);
  599.             break;
  600.         case GPF_COVALENTMAP:
  601.             {
  602.                 double covHalfWidth;
  603.                 sscanf(GPFLine, "%*s %lf %lf %lf %lf %lf", &covHalfWidth, &covBarrier, &(covalentPoint.x), &(covalentPoint.y), &(covalentPoint.z));
  604.                 covHalfWidthSquaredInv = 1 / Mathd::Sqr(covHalfWidth);
  605.                 logFile->printFormatted("ncovalentmap <half-width in Angstroms> <barrier> <x> <y> <z>n"
  606.                                        "nCovalent well's half-width in Angstroms:         %8.3fn"
  607.                                        "nCovalent barrier energy in kcal/mol:             %8.3fn"
  608.                                        "nCovalent attachment point will be positioned at: (%8.3f, %8.3f, %8.3f)nn",
  609.                                        covHalfWidth, covBarrier, covalentPoint.x, covalentPoint.y, covalentPoint.z);
  610.                 // center covalentPoint in the grid maps frame of reference,
  611.                 covalentPoint -= gridCenter;
  612.             }
  613.             break;
  614.         case GPF_DISORDER:
  615.             disorderH = true;
  616.             logFile->print("nHydroxyls will be disordered nn");
  617.             break;
  618.         case GPF_SMOOTH:
  619.             sscanf(GPFLine, "%*s %lf", &rSmooth);
  620.             logFile->printFormatted("nPotentials will be smoothed by: %.3lf Angstromnn", rSmooth);
  621.             break;
  622.         case GPF_QASP:
  623.             sscanf(GPFLine, "%*s %lf", &solparQ);
  624.             logFile->printFormatted("nCharge component of the atomic solvation parameter: %.3lfnn", solparQ);
  625.             // Typical value of solparQ is 0.001118
  626.             break;
  627.         case GPF_DIEL:
  628.             sscanf(GPFLine, "%*s %lf", &diel);
  629.             if (diel < 0)
  630.             {
  631.                 // negative...
  632.                 distDepDiel = true;
  633.                 // calculate inverted ddd of Mehler & Solmajer
  634.                 for (int indexR = 0; indexR < MAX_DIST; indexR++)
  635.                     epsilon[indexR] = calculateDistDepDielInv(indexToAngstrom<double>(indexR));
  636.                 logFile->print("nUsing *distance-dependent* dielectric function of Mehler and Solmajer, Prot.Eng.4, 903-910.nn"
  637.                               "  d   Dielectricn ___  __________n");
  638.                 for (int i = 0; i <= 500; i += 10)
  639.                 {
  640.                     ri = indexToAngstrom<double>(i);
  641.                     logFile->printFormatted("%4.1lf%9.2lfn", ri, DDD_FACTOR / epsilon[i]);
  642.                 }
  643.                 logFile->print("n");
  644.             }
  645.             else
  646.             {
  647.                 // positive or zero...
  648.                 distDepDiel = false;
  649.                 if (diel <= APPROX_ZERO)
  650.                     diel = 40;
  651.                 logFile->printFormatted("Using a *constant* dielectric of:  %.2fn", diel);
  652.                 invDielCal = DDD_FACTOR / diel;
  653.             }
  654.             break;
  655.         case GPF_FMAP:
  656.             sscanf(GPFLine, "%*s %s", floatingGridFilename);
  657.             logFile->printFormatted("nFloating Grid file name = %sn", floatingGridFilename);
  658.             break;
  659.         case GPF_PARAM_FILE:
  660.             // open and read the AD4 parameters .dat file
  661.             sscanf(GPFLine, "%*s %s ", parameterLibraryFilename);
  662.             break;
  663.         }                       // second switch
  664.     }                           // while: finished reading gpf
  665.     // Map files checkpoint  (number of maps, desolv and elec maps) SF
  666.     // Number of maps defined for atom types
  667.     if (mapIndex < gridmaps.getNumAtomMaps() - 1)
  668.     {
  669.         logFile->printFormatted("Too few "map" keywords (%d);  the "ligand_types" command declares %d atom types.nAdd a "map" keyword from the GPF.n", mapIndex + 1, gridmaps.getNumAtomMaps());
  670.         logFile->printError(ERROR, "Not enough map keywords found.n");
  671.         logFile->printError(FATAL_ERROR, "Unsuccessful completion.nn");
  672. }
  673.     // Desolvation map
  674.     if (!gridmaps.getDesolvationMap().filename[0])
  675.     {
  676.         logFile->print("The desolvation map file is not defined in the GPF.n");
  677.         logFile->printError(ERROR, "No desolvation map file defined.n");
  678.         logFile->printError(FATAL_ERROR, "Unsuccessful completion.nn");
  679. }
  680.     // Electrostatic map
  681.     if (!gridmaps.getElectrostaticMap().filename[0])
  682.     {
  683.         logFile->print("The electrostatic map file is not defined in the GPF.n");
  684.         logFile->printError(ERROR, "No electrostatic map file defined.n");
  685.         logFile->printError(FATAL_ERROR, "Unsuccessful completion.nn");
  686. }
  687.     // End of map files checkpoint SF
  688.     logFile->print("n>>> Closing the grid parameter file (GPF)... <<<nn" UnderLine);
  689.     fclose(GPF);
  690.     if (!floatingGridFilename[0])
  691.         logFile->print("nnNo Floating Grid was requested.n");
  692.     // apply the estat forcefield coefficient/weight here
  693.     if (distDepDiel)
  694.         for (int ia = 0; ia < numReceptorAtoms; ia++)
  695.             receptorAtom[ia].w = charge[ia] * parameterLibrary.coeff_estat;
  696.     else
  697.         // apply the constant dielectric
  698.         for (int ia = 0; ia < numReceptorAtoms; ia++)
  699.             receptorAtom[ia].w = charge[ia] * parameterLibrary.coeff_estat * invDielCal;
  700. }
  701. int InputDataLoader::parseGPFLine(const char *line)
  702. {
  703.     size_t l;
  704. int i, token = -1; // return -1 if nothing is recognized
  705.     char c[LINE_LEN];
  706.     l = strIndex(line, " ");
  707.     if (l == -1)
  708.     {
  709.         l = strIndex(line, "t");
  710.         if (l == -1)
  711.             l = strlen(line);
  712.     }
  713.     for(i=0; i<l; i++)
  714.         c[i] = char(tolower(line[i]));
  715.     if ((c[0]=='n')||(c[0]==''))
  716.         token = GPF_NULL;
  717.     else if (c[0]=='#')
  718.         token = GPF_COMMENT;
  719.     else if (strncmp(c, "receptor_types", 14) == 0)
  720.         token = GPF_RECEPTOR_TYPES;
  721.     else if (strncmp(c, "receptor", 8) == 0)
  722.         token = GPF_RECEPTOR;
  723.     else if (strncmp(c, "gridfld", 7) == 0)
  724.         token = GPF_GRIDFLD;
  725.     else if (strncmp(c, "npts", 4) == 0)
  726.         token = GPF_NPTS;
  727.     else if (strncmp(c, "spacing", 7) == 0)
  728.         token = GPF_SPACING;
  729.     else if (strncmp(c, "gridcenter", 10) == 0)
  730.         token = GPF_GRIDCENTER;
  731.     else if (strncmp(c, "types", 5) == 0)
  732.         token = GPF_LIGAND_TYPES;
  733.     else if (strncmp(c, "ligand_types", 12) == 0)
  734.         token = GPF_LIGAND_TYPES;
  735.     else if (strncmp(c, "map", 3) == 0)
  736.         token = GPF_MAP;
  737.     else if (strncmp(c, "elecmap", 7) == 0)
  738.         token = GPF_ELECMAP;
  739.     else if (strncmp(c, "dsolvmap", 8) == 0)
  740.         token = GPF_DSOLVMAP;
  741.     else if (strncmp(c, "covalentmap", 11) == 0)
  742.         token = GPF_COVALENTMAP;
  743.     else if (strncmp(c, "nbp_coeffs", 10) == 0)
  744.         token = GPF_NBP_COEFFS;
  745.     else if (strncmp(c, "nbp_r_eps", 9) == 0)
  746.         token = GPF_NBP_R_EPS;
  747.     else if (strncmp(c, "dielectric", 10) == 0)
  748.         token = GPF_DIEL;
  749.     else if (strncmp(c, "qasp", 4) == 0)
  750.         token = GPF_QASP;
  751.     else if (strncmp(c, "fmap", 4) == 0)
  752.         token = GPF_FMAP;
  753.     else if (strncmp(c, "disorder_h", 10) == 0)
  754.         token = GPF_DISORDER;
  755.     else if (strncmp(c, "smooth", 6) == 0)
  756.         token = GPF_SMOOTH;
  757.     else if (strncmp(c, "sol_par", 7) == 0)
  758.         token = GPF_SOL_PAR;
  759.     else if (strncmp(c, "constant", 8) == 0)
  760.         token = GPF_CONSTANT;
  761.     else if (strncmp(c, "parameter_file", 14) == 0)
  762.         token = GPF_PARAM_FILE;
  763.     return token;
  764. }
  765. // checks that number of grid elements is valid
  766. int InputDataLoader::checkSize(int numGridPointsMinusOne, char axischar)
  767. {
  768.     // numGridPointsMinusOne mustn't be negative, shouldn't be zero or larger than MAX_GRID_PTS and should be even
  769.     if (numGridPointsMinusOne < 0)
  770.         logFile->printErrorFormatted(FATAL_ERROR, "Negative number of %c-grid elements!  Aborting.nn", axischar);
  771.     else if (numGridPointsMinusOne == 0)
  772.         logFile->printErrorFormatted(WARNING, "0 %c-grid elements!nn", axischar);
  773.     else if (numGridPointsMinusOne > MAX_GRID_PTS)
  774.     {
  775.         logFile->printErrorFormatted(WARNING, "Maximum number of %c-grid elements allowed is %d. Using this value.n", axischar, MAX_GRID_PTS);
  776.         numGridPointsMinusOne = MAX_GRID_PTS;
  777.     }
  778.     else if (numGridPointsMinusOne % 2 == 1)
  779.     {
  780.         logFile->printTitledFormatted("Number of grid elements must be even; %c-elements changed to: %dn", axischar, numGridPointsMinusOne);
  781.         numGridPointsMinusOne -= 1;
  782.     }
  783.     return numGridPointsMinusOne;
  784. }
  785. // utility func for parsing types
  786. int InputDataLoader::parseTypes(char *line, char **words, int maxwords)
  787. {
  788.     char *char_ptr = line;
  789.     int num_types = 0;
  790.     // flag for first word which is always a keyword
  791.     int found_keyword = 0;
  792.     int index = 0;
  793.     for (;;)
  794.     {
  795.         // skip spaces
  796.         while (isspace(*char_ptr))
  797.         {
  798.             char_ptr++;
  799.             index++;
  800.         }
  801.         // done parsing when get eol 'null' character
  802.         // could get null after a space
  803.         if (*char_ptr == '')
  804.             return num_types; // return number of 'types' found
  805.         // the first word is the keyword not a type
  806.         if (!found_keyword)
  807.             found_keyword++;
  808.         else
  809.             words[num_types++] = char_ptr; // words is a list of indicies of beginning of 1 or 2 char types
  810.         // once in a type, skip possible 2nd characters up to a space or null character
  811.         while (!isspace(*char_ptr) && *char_ptr != '')
  812.         {
  813.             char_ptr++;
  814.             index++;
  815.         }
  816.         // done parsing when get eol 'null' character
  817.         // could get null after a character
  818.         if (*char_ptr == '')
  819.             return num_types;
  820.         // make each 'type' a null terminated string
  821.         *char_ptr++ = '';
  822.         index++;
  823.         //if there are too many types, return
  824.         if (num_types >= maxwords)
  825.             return num_types;
  826.     }
  827. }
  828. // returns index of t in s, -1 if none.
  829. int InputDataLoader::strIndex(const char *s, const char *t)
  830. {
  831.     const char *r = strstr(s, t);
  832.     return r? int(r-s) : -1;
  833. }