-
Notifications
You must be signed in to change notification settings - Fork 48
/
Trajectory.cpp
162 lines (138 loc) · 4.34 KB
/
Trajectory.cpp
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
// Chemfiles, a modern library for chemistry file reading and writing
// Copyright (C) 2015-2016 Guillaume Fraux and contributors
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/
#include "chemfiles/Trajectory.hpp"
#include "chemfiles/File.hpp"
#include "chemfiles/Format.hpp"
#include "chemfiles/Error.hpp"
#include "chemfiles/FormatFactory.hpp"
using namespace chemfiles;
//! Get the extension part of a filename. Filename is assumed to be valid here.
static std::string extension(const std::string& filename) {
auto idx = filename.rfind('.');
if (idx != std::string::npos) {
return filename.substr(idx);
} else {
return "";
}
}
static File::Mode char_to_file_mode(char mode) {
switch (mode) {
case 'r':
case 'R':
return File::READ;
case 'a':
case 'A':
return File::APPEND;
case 'w':
case 'W':
return File::WRITE;
default:
throw FileError(
"Got an unknown file mode '" + std::to_string(mode) + "'"
);
}
}
Trajectory::Trajectory(const std::string& path, char mode, const std::string& format)
: path_(path), mode_(mode), step_(0), nsteps_(0), format_(nullptr), custom_topology_(), custom_cell_() {
format_creator_t format_creator;
if (format == "") {
// try to guess the format by extension
auto ext = extension(path);
format_creator = FormatFactory::get().by_extension(ext);
} else {
format_creator = FormatFactory::get().format(format);
}
auto filemode = char_to_file_mode(mode);
format_ = format_creator(path, filemode);
if (mode == 'r' || mode == 'a') {
nsteps_ = format_->nsteps();
}
}
Trajectory::~Trajectory() = default;
Trajectory::Trajectory(Trajectory&&) = default;
Trajectory& Trajectory::operator=(Trajectory&&) = default;
Frame Trajectory::read() {
if (step_ >= nsteps_) {
throw FileError(
"Can not read file '" + path_ + "' past end."
);
}
if (!(mode_ == File::READ || mode_ == File::APPEND)) {
throw FileError(
"File '" + path_ + "' was not openened in read or append mode."
);
}
Frame frame;
format_->read(frame);
step_++;
// Set the frame topology and/or cell if needed
if (custom_topology_) {
frame.set_topology(*custom_topology_);
}
if (custom_cell_) {
frame.set_cell(*custom_cell_);
}
return frame;
}
Frame Trajectory::read_step(const size_t step) {
if (step >= nsteps_) {
throw FileError(
"Can not read file '" + path_ + "' at step " +
std::to_string(step) + ". Max step is " + std::to_string(nsteps_) + "."
);
}
if (!(mode_ == File::READ || mode_ == File::APPEND)) {
throw FileError(
"File '" + path_ + "' was not openened in read or append mode."
);
}
Frame frame;
step_ = step;
format_->read_step(step_, frame);
// Set the frame topology and/or cell if needed
if (custom_topology_) {
frame.set_topology(*custom_topology_);
}
if (custom_cell_) {
frame.set_cell(*custom_cell_);
}
return frame;
}
void Trajectory::write(const Frame& frame) {
if (!(mode_ == File::WRITE || mode_ == File::APPEND)) {
throw FileError(
"File '" + path_ + "' was not openened in write or append mode."
);
}
// Maybe that is not the better way to do this, performance-wise. I'll have
// to benchmark this part.
Frame frame_copy = frame.clone();
if (custom_topology_) {
frame_copy.set_topology(*custom_topology_);
}
if (custom_cell_) {
frame_copy.set_cell(*custom_cell_);
}
format_->write(frame_copy);
step_++;
nsteps_++;
}
void Trajectory::set_topology(const Topology& top) {
custom_topology_ = top;
}
void Trajectory::set_topology(const std::string& filename, const std::string& format) {
Trajectory topolgy_file(filename, 'r', format);
assert(topolgy_file.nsteps() > 0);
auto frame = topolgy_file.read_step(0);
set_topology(frame.topology());
}
void Trajectory::set_cell(const UnitCell& new_cell) {
custom_cell_ = new_cell;
}
bool Trajectory::done() const {
return step_ >= nsteps_;
}