LOOS  v2.3.2
dcdwriter.cpp
1 /*
2  This file is part of LOOS.
3 
4  LOOS (Lightweight Object-Oriented Structure library)
5  Copyright (c) 2008, Tod D. Romo, Alan Grossfield
6  Department of Biochemistry and Biophysics
7  School of Medicine & Dentistry, University of Rochester
8 
9  This package (LOOS) is free software: you can redistribute it and/or modify
10  it under the terms of the GNU General Public License as published by
11  the Free Software Foundation under version 3 of the License.
12 
13  This package is distributed in the hope that it will be useful,
14  but WITHOUT ANY WARRANTY; without even the implied warranty of
15  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16  GNU General Public License for more details.
17 
18  You should have received a copy of the GNU General Public License
19  along with this program. If not, see <http://www.gnu.org/licenses/>.
20 */
21 
22 
23 
24 
25 #include <dcdwriter.hpp>
26 
27 
28 namespace loos {
29 
30  namespace {
31  const double default_unit_cell_angle = 90.0; // This should make VMD happy...
32  };
33 
34 
35 
36  void DCDWriter::writeF77Line(const char* const data, const unsigned int len) {
37  DataOverlay d;
38 
39  d.ui = len;
40 
41  stream_->write((char *)&d, sizeof(len));
42  stream_->write(data, len);
43  stream_->write((char *)&d, sizeof(len));
44  }
45 
46 
47  std::string DCDWriter::fixStringSize(const std::string& s, const unsigned int n) {
48  std::string result(s);
49 
50  if (s.size() < n) {
51  int i = n - s.size();
52  result += std::string (i, ' ');
53  } else if (s.size() > n)
54  result = s.substr(0, n);
55 
56  return(result);
57  }
58 
59 
60  void DCDWriter::writeHeader(void) {
61  unsigned int icntrl[21];
62  DataOverlay *dop = (DataOverlay *)(&icntrl[0]);
63  unsigned int i;
64  for (i=0; i<21; i++)
65  icntrl[i] = 0;
66 
67  icntrl[1] = _nsteps;
68  icntrl[2] = 1;
69  icntrl[3] = 1;
70  icntrl[4] = _nsteps;
71  icntrl[8] = _natoms * 3 - 6;
72  icntrl[9] = 0;
73  dop[10].f = _timestep;
74  icntrl[11] = _has_box;
75  icntrl[20] = 27;
76  dop[0].c[0] = 'C'; dop[0].c[1] = 'O'; dop[0].c[2] = 'R'; dop[0].c[3] = 'D';
77 
78  writeF77Line((char *)dop, 21 * sizeof(unsigned int));
79 
80  unsigned int size = 4 + 80 * _titles.size();
81  char *ptr = new char[size];
82  unsigned int *iptr = (unsigned int *)ptr;
83  *iptr = _titles.size();
84  for (i=0; i<_titles.size(); i++) {
85  std::string s = fixStringSize(_titles[i], 80);
86  memcpy(ptr + sizeof(unsigned int) + 80*i, s.c_str(), 80);
87  }
88  writeF77Line(ptr, size);
89  delete[] ptr;
90 
91 
92  dop[0].ui = _natoms;
93  writeF77Line((char *)dop, 1 * sizeof(unsigned int));
94 
95  _header_written = true;
96  }
97 
98 
99 
100  void DCDWriter::writeBox(const GCoord& box) {
101  double xtal[6] = { box[0], default_unit_cell_angle, box[1],
102  default_unit_cell_angle, default_unit_cell_angle, box[2] };
103 
104  writeF77Line((char *)xtal, 6*sizeof(double));
105  }
106 
107 
108 
110 
111  if (_natoms == 0) { // Assume this is the first frame being written...
112  _natoms = grp.size();
113  _has_box = grp.isPeriodic();
114 
115  } else {
116 
117  if (grp.size() != _natoms)
118  throw(LOOSError("Frame group atom count mismatch"));
119 
120  if (_has_box && !grp.isPeriodic())
121  throw(LOOSError("Periodic box data was requested for the DCD but the passed frame is missing it"));
122 
123  }
124 
125  if (_current >= _nsteps) {
126  stream_->seekp(0);
127  ++_nsteps;
128  writeHeader();
129  stream_->seekp(0, std::ios_base::end);
130  if (stream_->fail())
131  throw(FileWriteError(_filename, "Error while re-writing DCD header"));
132  }
133 
134  if (_has_box)
135  writeBox(grp.periodicBox());
136 
137  float *data = new float[_natoms];
138  for (uint i=0; i<_natoms; i++)
139  data[i] = grp[i]->coords().x();
140  writeF77Line((char *)data, _natoms * sizeof(float));
141 
142  for (uint i=0; i<_natoms; i++)
143  data[i] = grp[i]->coords().y();
144  writeF77Line((char *)data, _natoms * sizeof(float));
145 
146  for (uint i=0; i<_natoms; i++)
147  data[i] = grp[i]->coords().z();
148  writeF77Line((char *)data, _natoms * sizeof(float));
149 
150  delete[] data;
151 
152  stream_->flush();
153  ++_current;
154  }
155 
156 
157  void DCDWriter::writeFrames(const std::vector<AtomicGroup>& grps) {
158  std::vector<AtomicGroup>::const_iterator i;
159 
160  for (i= grps.begin(); i != grps.end(); i++)
161  writeFrame(*i);
162  }
163 
164  void DCDWriter::prepareToAppend() {
165 
166  stream_->seekg(0);
167 
168  DCD dcd(*stream_);
169  _natoms = dcd.natoms();
170  _has_box = dcd.hasPeriodicBox();
171  _timestep = dcd.timestep();
172  _current = _nsteps = dcd.nframes();
173  _titles = dcd.titles();
174 
175  stream_->seekp(0, std::ios_base::end);
176  }
177 
178 }
179 
180 
Class for reading DCD files.
Definition: dcd.hpp:64
bool isPeriodic(void) const
Test whether or not periodic boundary conditions are set.
void writeFrame(const AtomicGroup &grp)
Writes a frame to a growing DCD.
Definition: dcdwriter.cpp:109
void writeFrames(const std::vector< AtomicGroup > &grps)
Same as writeFrame(), but writes out the vector of frames...
Definition: dcdwriter.cpp:157
Generic LOOS exception.
Definition: exceptions.hpp:40
Class for handling groups of Atoms (pAtoms, actually)
Definition: AtomicGroup.hpp:87
Namespace for most things not already encapsulated within a class.
Errors while writing to files.
Definition: exceptions.hpp:226
GCoord periodicBox(void) const
Fetch the periodic boundary conditions.