-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathCharmmTrace.cpp
More file actions
226 lines (190 loc) · 6.87 KB
/
CharmmTrace.cpp
File metadata and controls
226 lines (190 loc) · 6.87 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
/***********************************************************************
CharmmTrace - Class for molecular dynamics simulation traces in CHARMM
format.
Copyright (c) 2019-2025 Oliver Kreylos
This file is part of the MD Visualizer (MDVisualizer).
The MD Visualizer is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License as published
by the Free Software Foundation; either version 2 of the License, or (at
your option) any later version.
The MD Visualizer is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
You should have received a copy of the GNU General Public License along
with the MD Visualizer; if not, write to the Free Software Foundation,
Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
***********************************************************************/
#include "CharmmTrace.h"
#include <ctype.h>
#include <stdio.h>
#include <algorithm>
#include <Misc/StdError.h>
#include <Misc/FileNameExtensions.h>
#include <Misc/PrintfTemplateTests.h>
#include <IO/OpenFile.h>
#include <IO/ValueSource.h>
namespace MD {
/****************************
Methods of class CharmmTrace:
****************************/
CharmmTrace::CharmmTrace(const char* sTraceFileNameTemplate)
:baseDirectory(IO::openFileDirectory(sTraceFileNameTemplate)),
traceFileNameTemplate(Misc::getFileName(sTraceFileNameTemplate)),
numAtoms(0),bbox(Box::empty)
{
/* Check if the file name template is valid: */
unsigned int conversionStart,conversionLength;
if(!Misc::isValidTemplate(traceFileNameTemplate,'u',1024,&conversionStart,&conversionLength))
throw Misc::makeStdErr(__PRETTY_FUNCTION__,"%s is not a valid trace file name template",sTraceFileNameTemplate);
/* Find all files in the base directory that match the file name template: */
while(baseDirectory->readNextEntry())
if(baseDirectory->getEntryType()==Misc::PATHTYPE_FILE)
{
/* Check if the template prefix matches the file name: */
const char* fileName=baseDirectory->getEntryName();
if(traceFileNameTemplate.compare(0,conversionStart,fileName,conversionStart)==0)
{
/* Extract the file's index: */
unsigned int index=0;
const char* cPtr=fileName+conversionStart;
for(;isspace(*cPtr);++cPtr)
;
bool haveDigits=isdigit(*cPtr);
for(;isdigit(*cPtr);++cPtr)
index=index*10+(*cPtr-'0');
if(haveDigits)
{
/* Check if the template suffix matches the file name: */
if(traceFileNameTemplate.compare(conversionStart+conversionLength,std::string::npos,cPtr)==0)
{
/* Have a match; save the file number: */
timeStepNumbers.push_back(index);
}
}
}
}
/* Sort the list of time step file numbers: */
std::sort(timeStepNumbers.begin(),timeStepNumbers.end());
#if 0
/* Create a standard type map: */
Atom::createTypeMap(modifyAtomTypeMap());
#endif
/* Parse the first trace file to retrieve the number of atoms and calculate a bounding box: */
char traceFileName[1024];
snprintf(traceFileName,sizeof(traceFileName),traceFileNameTemplate.c_str(),timeStepNumbers.front());
IO::ValueSource traceFile(baseDirectory->openFile(traceFileName));
traceFile.setPunctuation('\n',true);
traceFile.skipWs();
/* Skip the file header: */
while(traceFile.peekc()=='*')
{
traceFile.skipLine();
traceFile.skipWs();
}
/* Read the number of atoms: */
numAtoms=traceFile.readUnsignedInteger();
traceFile.skipLine();
traceFile.skipWs();
/* Read all atoms and calculate the bounding box: */
size_t i;
for(i=0;i<numAtoms&&!traceFile.eof();++i)
{
/* Read the atom: */
traceFile.readUnsignedInteger(); // Skip atom index
traceFile.readUnsignedInteger(); // Skip residue index
traceFile.skipString(); // Skip residue name
/* Read the element name: */
char elementName[4];
elementName[0]=char(traceFile.getChar());
for(int i=1;i<4;++i)
elementName[i]='\0';
traceFile.skipString();
/* Create an atom type for this element: */
Atom::Type atomType;
atomType.element=Atom::parseElement(elementName);
atomType.halfBondLength=Atom::getHalfBondLength(atomType.element);
atomType.radius=Atom::getVanDerWaalsRadius(atomType.element);
atomType.color=Atom::getColor(atomType.element);
setAtomType(atomType.element,atomType);
/* Read the atom position: */
Point position;
for(int j=0;j<3;++j)
position[j]=Scalar(traceFile.readNumber());
/* Skip the rest of the line: */
traceFile.skipLine();
traceFile.skipWs();
/* Add the atom to the bounding box: */
bbox.addPoint(position);
}
if(i<numAtoms)
throw Misc::makeStdErr(__PRETTY_FUNCTION__,"Trace file %u is not a valid CHARMM trace file",timeStepNumbers.front());
}
CharmmTrace::~CharmmTrace(void)
{
}
size_t CharmmTrace::getNumTimeSteps(void) const
{
return timeStepNumbers.size();
}
double CharmmTrace::getTimePoint(size_t timeStepIndex) const
{
/* Assume that time step file numbers are time points in some arbitrary unit: */
return double(timeStepNumbers[timeStepIndex]);
}
size_t CharmmTrace::getNumAtoms(size_t timeStepIndex) const
{
return numAtoms;
}
Box CharmmTrace::calcBoundingBox(void) const
{
return bbox;
}
void CharmmTrace::loadAtoms(size_t timeStepIndex,Atom atoms[])
{
/* Open the trace file of the given index: */
char traceFileName[1024];
snprintf(traceFileName,sizeof(traceFileName),traceFileNameTemplate.c_str(),timeStepNumbers[timeStepIndex]);
IO::ValueSource traceFile(baseDirectory->openFile(traceFileName));
traceFile.setPunctuation('\n',true);
traceFile.skipWs();
/* Skip the file header: */
while(traceFile.peekc()=='*')
{
traceFile.skipLine();
traceFile.skipWs();
}
/* Read the number of atoms: */
size_t fileNumAtoms=traceFile.readUnsignedInteger();
if(fileNumAtoms!=numAtoms)
throw Misc::makeStdErr(__PRETTY_FUNCTION__,"Trace file %u has mismatching number of atoms",timeStepNumbers[timeStepIndex]);
traceFile.skipLine();
traceFile.skipWs();
/* Read all atoms: */
size_t i;
for(i=0;i<numAtoms&&!traceFile.eof();++i)
{
/* Read the atom: */
traceFile.readUnsignedInteger(); // Skip atom index
traceFile.readUnsignedInteger(); // Skip residue index
traceFile.skipString(); // Skip residue name
/* Read and parse the element name: */
char elementName[4];
elementName[0]=char(traceFile.getChar());
for(int i=1;i<4;++i)
elementName[i]='\0';
traceFile.skipString();
atoms[i].setTypeId(Atom::TypeID(Atom::parseElement(elementName)));
/* Read the atom position: */
Point pos;
for(int j=0;j<3;++j)
pos[j]=Scalar(traceFile.readNumber());
atoms[i].setPosition(pos);
/* Skip the rest of the line: */
traceFile.skipLine();
traceFile.skipWs();
}
if(i<numAtoms)
throw Misc::makeStdErr(__PRETTY_FUNCTION__,"Trace file %u is not a valid CHARMM trace file",timeStepNumbers[timeStepIndex]);
}
}