9 #include <spdlog/spdlog.h> 28 #include <xdrfile_trr.h> 29 #include <xdrfile_xtc.h> 37 using XDRFILE_unique =
38 std::unique_ptr<XDRFILE, XdrFileDeleter>;
46 std::unique_ptr<std::ostream> openCompressedOutputStream(
const std::string& filename,
47 bool throw_on_error =
false);
56 template <
typename TKey,
typename TValue>
57 void writeKeyValuePairs(std::ostream& stream,
const std::map<TKey, TValue>& data,
58 const std::string& sep =
" ",
const std::string& end =
"\n")
61 for (
const auto& [key, value] : data) {
62 stream << key << sep << value << end;
74 template <
typename TKey,
typename TValue>
75 void writeKeyValuePairs(
const std::string& filename,
const std::map<TKey, TValue>& data)
78 std::ofstream file(filename);
79 writeKeyValuePairs(file, data);
91 virtual void loadHeader(std::istream& stream) = 0;
92 virtual void loadFooter(std::istream& stream);
93 virtual Particle loadParticle(std::istream& stream) = 0;
94 void checkLoadedParticles()
const;
97 static size_t getNumberOfAtoms(
const std::string& line);
98 void getNextLine(std::istream& stream, std::string& destination,
99 const std::string& comment_identifiers);
100 size_t expected_number_of_particles = 0;
102 void handleChargeMismatch(
Particle& particle,
103 int atom_index)
const;
104 static void handleRadiusMismatch(
const Particle& particle,
double radius,
109 Point box_length = Point::Zero();
110 std::vector<std::string> comments;
111 bool prefer_charges_from_file =
118 bool box_dimension_support =
false;
119 bool particle_charge_support =
false;
120 bool particle_radius_support =
false;
132 void loadHeader(std::istream& stream)
override;
133 Particle loadParticle(std::istream& stream)
override;
134 double bond_length = 0.0;
135 Point new_particle_position = Point::Zero();
139 const Point& initial_particle_position =
Point(0, 0, 0));
140 void setBondLength(
double bond_length);
141 std::string loadSequence(std::istream& stream);
142 static char getFastaLetter(std::istream& stream);
148 void loadHeader(std::istream& stream)
override;
149 Particle loadParticle(std::istream& stream)
override;
158 void loadHeader(std::istream& stream)
override;
159 Particle loadParticle(std::istream& stream)
override;
182 void loadHeader(std::istream& stream)
override;
183 Particle loadParticle(std::istream& stream)
override;
189 void loadHeader(std::istream& stream)
override;
190 Particle loadParticle(std::istream& stream)
override;
196 void loadBoxInformation(
197 std::istream& stream);
198 void loadHeader(std::istream& stream)
override;
199 Particle loadParticle(std::istream& stream)
override;
211 virtual void saveHeader(std::ostream& stream,
212 int number_of_particles)
const = 0;
214 saveFooter(std::ostream& stream)
const;
215 virtual void saveParticle(std::ostream& stream,
217 void saveGroup(std::ostream& stream,
const Group& group);
219 template <
class ParticleIter>
220 void saveParticles(std::ostream& stream, ParticleIter begin, ParticleIter end)
224 std::for_each(begin, end, [&](
const auto& particle) {
225 saveParticle(stream, particle);
231 static const std::string generated_by_faunus_comment;
232 bool particle_is_active =
true;
233 std::string group_name;
234 std::size_t particle_index = 0;
235 std::size_t group_index = 0;
236 Point box_dimensions = Point::Zero();
239 template <std::forward_iterator ParticleIter>
240 void save(std::ostream& stream, ParticleIter begin, ParticleIter end,
const Point& box_length)
242 if (
auto number_of_particles = std::distance(begin, end); number_of_particles > 0) {
243 box_dimensions = box_length;
244 saveHeader(stream, number_of_particles);
245 saveParticles(stream, begin, end);
250 void save(std::ostream& stream,
const RequireGroups auto& groups,
const Point& box_length)
254 box_dimensions = box_length;
256 auto group_sizes = groups | std::views::transform(&Group::capacity);
257 const auto number_of_particles =
258 std::accumulate(group_sizes.begin(), group_sizes.end(), 0u);
259 saveHeader(stream, number_of_particles);
261 std::ranges::for_each(groups, [&](
const auto& group) { saveGroup(stream, group); });
265 template <
class... Args>
void save(
const std::string& filename,
const Args&... args)
267 if (std::ofstream stream(filename); stream) {
268 faunus_logger->debug(
"writing to {}", filename);
269 save(stream, args...);
272 throw std::runtime_error(
"writeKeyValuePairs error: "s + filename);
282 void saveHeader(std::ostream& stream,
int number_of_particles)
const override;
283 void saveParticle(std::ostream& stream,
const Particle& particle)
override;
289 void saveHeader(std::ostream& stream,
int number_of_particles)
const override;
290 void saveParticle(std::ostream& stream,
const Particle& particle)
override;
300 void saveHeader(std::ostream& stream,
int number_of_particles)
const override;
301 void saveParticle(std::ostream& stream,
const Particle& particle)
override;
307 void saveHeader(std::ostream& stream,
int number_of_particles)
const override;
308 void saveFooter(std::ostream& stream)
const override;
309 void saveParticle(std::ostream& stream,
const Particle& particle)
override;
318 Style style = Style::PQR_LEGACY;
319 explicit PQRWriter(Style style = Style::PQR_LEGACY);
325 void saveHeader(std::ostream& stream,
int number_of_particles)
const override;
326 void saveFooter(std::ostream& stream)
const override;
327 void saveParticle(std::ostream& stream,
const Particle& particle)
override;
330 namespace PQRTrajectoryReader {
331 bool readAtomRecord(
const std::string& record,
Particle& particle,
333 void loadTrajectory(
const std::string& filename,
334 std::vector<ParticleVector>& destination);
359 float xtc_time = 0.0;
360 int number_of_atoms = 0;
361 float precision = 1000.0;
384 template <RequirePo
intIterator begin_iterator,
class end_iterator>
386 end_iterator coordinates_end)
388 initNumberOfAtoms(std::distance(coordinates_begin, coordinates_end));
389 importFrame(step, time, box, coordinates_begin, coordinates_end);
418 template <RequirePo
intIterator begin_iterator,
class end_iterator>
420 begin_iterator coordinates_begin, end_iterator coordinates_end)
422 importTimestamp(step, time);
424 importCoordinates(coordinates_begin, coordinates_end, 0.5 * box);
445 template <RequirePo
intIterator begin_iterator, RequirePo
intIterator end_iterator>
447 end_iterator coordinates_end)
const 449 exportTimestamp(step, time);
451 exportCoordinates(coordinates_begin, coordinates_end, 0.5 * box);
455 using XTCFloat = float;
457 Eigen::Matrix<XTCFloat, 3, 3, Eigen::RowMajor>;
459 Eigen::Matrix<XTCFloat, 3, 1>;
465 void importTimestamp(
int step,
float time);
470 void importBox(
const Point& box);
477 void importCoordinates(
const PointVector& coordinates,
const Point& offset);
488 template <RequirePo
intIterator begin_iterator,
typename end_iterator>
492 std::ranges::for_each(begin, end, [&](
const auto& position) {
493 if (i >= number_of_atoms) {
494 throw std::runtime_error(
"too many particles for XTC frame");
496 const XTCVector xtc_pos = ((position + offset) / 1.0_nm).template cast<XTCFloat>();
497 std::copy(xtc_pos.data(), xtc_pos.data() + DIM, xtc_coordinates.get()[i++]);
499 if (i != number_of_atoms) {
500 throw std::runtime_error(
"too few particles for XTC frame");
509 void exportTimestamp(
int& step,
float& time)
const;
514 void exportBox(
Point& box)
const;
522 void exportCoordinates(
PointVector& coordinates,
const Point& offset)
const;
533 template <RequirePo
intIterator begin_iterator,
typename end_iterator>
538 for (
auto coordinates_it = begin; coordinates_it != end; ++coordinates_it) {
539 if (i >= number_of_atoms) {
540 throw std::runtime_error(
"number of particles in the loaded XTC frame too low");
542 XTCVector xtc_atom_coordinates(xtc_coordinates.get()[i++]);
543 *coordinates_it =
Point(xtc_atom_coordinates.cast<
double>() * 1.0_nm) - offset;
545 if (i < number_of_atoms) {
546 throw std::runtime_error(
"number of particles in the loaded XTC frame too high");
554 void initNumberOfAtoms(
int);
568 float timestamp = 0.0;
597 int return_code = XdrFile::exdrOK;
598 XdrFile::XDRFILE_unique xdrfile;
599 std::unique_ptr<XTCTrajectoryFrame> xtc_frame;
607 explicit XTCReader(
const std::string& filename);
613 int getNumberOfCoordinates();
634 template <RequirePo
intIterator begin_iterator,
typename end_iterator>
635 bool read(
int& step,
float& time,
Point& box, begin_iterator coordinates_begin,
636 end_iterator coordinates_end)
639 xtc_frame->exportFrame(step, time, box, coordinates_begin, coordinates_end);
663 int return_code = XdrFile::exdrOK;
664 XdrFile::XDRFILE_unique xdrfile;
665 std::unique_ptr<XTCTrajectoryFrame> xtc_frame;
666 int step_counter = 0;
668 float time_delta = 1.0_ps;
675 explicit XTCWriter(
const std::string& filename);
698 template <RequirePo
intIterator begin_iterator,
typename end_iterator>
699 void writeNext(
const Point& box, begin_iterator coordinates_begin, end_iterator coordinates_end)
702 auto number_of_atoms = std::ranges::distance(coordinates_begin, coordinates_end);
703 faunus_logger->trace(
"preparing xtc output for {} particles", number_of_atoms);
704 xtc_frame = std::make_unique<XTCTrajectoryFrame>(number_of_atoms);
706 xtc_frame->importFrame(step_counter, static_cast<float>(step_counter) * time_delta, box,
707 coordinates_begin, coordinates_end);
723 void writeFrameAt(
int step,
float time);
726 std::vector<AtomData::index_type>
736 const Point& origin = {0, 0, 0});
Eigen::Vector3d Point
3D vector used for positions, velocities, forces etc.
Definition: coordinates.h:7
Simple data structure to store a trajectory frame in native Faunus format.
Definition: io.h:563
XTCTrajectoryFrame(int step, float time, const Point &box, begin_iterator coordinates_begin, end_iterator coordinates_end)
Creates an XTC trajectory frame from scalar parameters and input iterator and converts data according...
Definition: io.h:385
std::vector< Point > PointVector
Vector of 3D vectors.
Definition: core.h:24
Base class to writeKeyValuePairs simple structure files such as XYZ, AAM, PQR etc.
Definition: io.h:208
void importFrame(const int step, const float time, const Point &box, begin_iterator coordinates_begin, end_iterator coordinates_end)
Imports data from scalar parameters and an input iterator over coordinates.
Definition: io.h:419
Modified XYZ format that also saves spherocylinder direction and patch (ported from Faunus v1) ...
Definition: io.h:297
XYZ file loader.
Definition: io.h:179
ParticleVector loadStructure(std::string_view filename, bool prefer_charges_from_file)
Load structure file into particle vector.
Definition: io.cpp:413
std::vector< Particle > ParticleVector
Storage type for collections of particles.
Definition: particle.h:253
std::string filename
name of the trajectory file, mainly for error reporting
Definition: io.h:603
void importCoordinates(begin_iterator begin, end_iterator end, const Point &offset) const
Imports and converts atomic coordinates.
Definition: io.h:489
Reads FASTA file and generate one particle per amino acid.
Definition: io.h:129
void operator()(XdrFile::XDRFILE *xdrfile)
Custom deleter for XDRFILE pointer that closes file.
Definition: io.cpp:1252
bool read(int &step, float &time, Point &box, begin_iterator coordinates_begin, end_iterator coordinates_end)
Reads the next frame in the trajectory.
Definition: io.h:635
std::unique_ptr< XdrFile::rvec[]> xtc_coordinates
C-style array of particle coordinates.
Definition: io.h:357
Particle class for storing positions, id, and other properties.
Definition: particle.h:220
Cell list class templates.
Definition: actions.cpp:11
End of Group class.
Definition: group.h:177
std::string addGrowingSuffix(const std::string &)
Add growing suffix filename until non-existing name is found.
void exportCoordinates(begin_iterator begin, end_iterator end, const Point &offset) const
Exports and converts atomic coordinates.
Definition: io.h:534
concept RequireGroups
Concept for a range of groups.
Definition: group.h:387
void writeNext(const Point &box, begin_iterator coordinates_begin, end_iterator coordinates_end)
Writes a next frame into the file using own automatic counter for step and timestamp.
Definition: io.h:699
std::vector< AtomData::index_type > fastaToAtomIds(std::string_view fasta_sequence)
Convert FASTA sequence to atom id sequence.
Definition: io.cpp:455
const std::string filename
name of the trajectory file, mainly for error reporting
Definition: io.h:671
Point box
simulation box
Definition: io.h:565
ParticleVector fastaToParticles(std::string_view fasta_sequence, double bond_length, const Point &origin)
Create particle vector from FASTA sequence with equally spaced atoms.
Definition: io.cpp:373
Base data structure for native XTC format as used in Gromacs and supported by the C library...
Definition: io.h:354
void exportFrame(int &step, float &time, Point &box, begin_iterator coordinates_begin, end_iterator coordinates_end) const
Exports data to scalar paramers and output iterator over atomic coordinates.
Definition: io.h:446
Base class to load simple structure files such as XYZ, AAM, PQR etc.
Definition: io.h:88
PointVector coordinates
coordinates of particles
Definition: io.h:566
Writes frames into an XTC file (GROMACS compressed trajectory file format).
Definition: io.h:661
Reads frames from an XTC file (GROMACS compressed trajectory file format).
Definition: io.h:595
XdrFile::matrix xtc_box
box tensor; only diagonal elements are used
Definition: io.h:356
std::unique_ptr< StructureFileWriter > createStructureFileWriter(const std::string &suffix)
Create structure writer.
Definition: io.cpp:388