/** Open the Charmm PSF file specified by filename and set up topology data. * Mask selection requires natom, nres, names, resnames, resnums. */ int Parm_CharmmPsf::ReadParm(FileName const& fname, Topology &parmOut) { const size_t TAGSIZE = 10; char tag[TAGSIZE]; tag[0]='\0'; CpptrajFile infile; if (infile.OpenRead(fname)) return 1; mprintf(" Reading Charmm PSF file %s as topology file.\n",infile.Filename().base()); // Read the first line, should contain PSF... const char* buffer = 0; if ( (buffer=infile.NextLine()) == 0 ) return 1; // Advance to <ntitle> !NTITLE int ntitle = FindTag(tag, "!NTITLE", 7, infile); // Only read in 1st title. Skip any asterisks. std::string psftitle; if (ntitle > 0) { buffer = infile.NextLine(); const char* ptr = buffer; while (*ptr != '\0' && (*ptr == ' ' || *ptr == '*')) ++ptr; psftitle.assign( ptr ); } parmOut.SetParmName( NoTrailingWhitespace(psftitle), infile.Filename() ); // Advance to <natom> !NATOM int natom = FindTag(tag, "!NATOM", 6, infile); if (debug_>0) mprintf("\tPSF: !NATOM tag found, natom=%i\n", natom); // If no atoms, probably issue with PSF file if (natom < 1) { mprinterr("Error: No atoms in PSF file.\n"); return 1; } // Read the next natom lines int psfresnum = 0; char psfresname[6]; char psfname[6]; char psftype[6]; double psfcharge; double psfmass; for (int atom=0; atom < natom; atom++) { if ( (buffer=infile.NextLine()) == 0 ) { mprinterr("Error: ReadParmPSF(): Reading atom %i\n",atom+1); return 1; } // Read line // ATOM# SEGID RES# RES ATNAME ATTYPE CHRG MASS (REST OF COLUMNS ARE LIKELY FOR CMAP AND CHEQ) sscanf(buffer,"%*i %*s %i %s %s %s %lf %lf",&psfresnum, psfresname, psfname, psftype, &psfcharge, &psfmass); parmOut.AddTopAtom( Atom( psfname, psfcharge, psfmass, psftype), Residue( psfresname, psfresnum, ' ', ' '), 0 ); } // END loop over atoms // Advance to <nbond> !NBOND int bondatoms[9]; int nbond = FindTag(tag, "!NBOND", 6, infile); if (nbond > 0) { if (debug_>0) mprintf("\tPSF: !NBOND tag found, nbond=%i\n", nbond); int nlines = nbond / 4; if ( (nbond % 4) != 0) nlines++; for (int bondline=0; bondline < nlines; bondline++) { if ( (buffer=infile.NextLine()) == 0 ) { mprinterr("Error: ReadParmPSF(): Reading bond line %i\n",bondline+1); return 1; } // Each line has 4 pairs of atom numbers int nbondsread = sscanf(buffer,"%i %i %i %i %i %i %i %i",bondatoms,bondatoms+1, bondatoms+2,bondatoms+3, bondatoms+4,bondatoms+5, bondatoms+6,bondatoms+7); // NOTE: Charmm atom nums start from 1 for (int bondidx=0; bondidx < nbondsread; bondidx+=2) parmOut.AddBond(bondatoms[bondidx]-1, bondatoms[bondidx+1]-1); } } else mprintf("Warning: PSF has no bonds.\n"); // Advance to <nangles> !NTHETA int nangle = FindTag(tag, "!NTHETA", 7, infile); if (nangle > 0) { if (debug_>0) mprintf("\tPSF: !NTHETA tag found, nangle=%i\n", nangle); int nlines = nangle / 3; if ( (nangle % 3) != 0) nlines++; for (int angleline=0; angleline < nlines; angleline++) { if ( (buffer=infile.NextLine()) == 0) { mprinterr("Error: Reading angle line %i\n", angleline+1); return 1; } // Each line has 3 groups of 3 atom numbers int nanglesread = sscanf(buffer,"%i %i %i %i %i %i %i %i %i",bondatoms,bondatoms+1, bondatoms+2,bondatoms+3, bondatoms+4,bondatoms+5, bondatoms+6,bondatoms+7, bondatoms+8); for (int angleidx=0; angleidx < nanglesread; angleidx += 3) parmOut.AddAngle( bondatoms[angleidx ]-1, bondatoms[angleidx+1]-1, bondatoms[angleidx+2]-1 ); } } else mprintf("Warning: PSF has no angles.\n"); // Advance to <ndihedrals> !NPHI int ndihedral = FindTag(tag, "!NPHI", 5, infile); if (ndihedral > 0) { if (debug_>0) mprintf("\tPSF: !NPHI tag found, ndihedral=%i\n", ndihedral); int nlines = ndihedral / 2; if ( (ndihedral % 2) != 0) nlines++; for (int dihline = 0; dihline < nlines; dihline++) { if ( (buffer=infile.NextLine()) == 0) { mprinterr("Error: Reading dihedral line %i\n", dihline+1); return 1; } // Each line has 2 groups of 4 atom numbers int ndihread = sscanf(buffer,"%i %i %i %i %i %i %i %i",bondatoms,bondatoms+1, bondatoms+2,bondatoms+3, bondatoms+4,bondatoms+5, bondatoms+6,bondatoms+7); for (int dihidx=0; dihidx < ndihread; dihidx += 4) parmOut.AddDihedral( bondatoms[dihidx ]-1, bondatoms[dihidx+1]-1, bondatoms[dihidx+2]-1, bondatoms[dihidx+3]-1 ); } } else mprintf("Warning: PSF has no dihedrals.\n"); mprintf("\tPSF contains %i atoms, %i residues.\n", parmOut.Natom(), parmOut.Nres()); infile.CloseFile(); return 0; }