/
Writer.h
162 lines (137 loc) · 5.11 KB
/
Writer.h
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
/**
* \file IMP/display/Writer.h
* \brief Base class for writing geometry to a file
*
* Copyright 2007-2022 IMP Inventors. All rights reserved.
*/
#ifndef IMPDISPLAY_WRITER_H
#define IMPDISPLAY_WRITER_H
#include <IMP/display/display_config.h>
#include "declare_Geometry.h"
#include "internal/writers.h"
#include "GeometryProcessor.h"
#include <IMP/Pointer.h>
#include <IMP/InputAdaptor.h>
#include <boost/format.hpp>
IMPDISPLAY_BEGIN_NAMESPACE
//! Base class for writing geometry to a file.
/** A writer object accumulates geometry and then
writes a file when the object is destroyed. You must set the name
of the file being written to before writing using the
IMP::display::Writer::set_file_name() method.
*/
class IMPDISPLAYEXPORT Writer : public GeometryProcessor,
public IMP::Object {
int frame_;
public:
//! Create a writer opening the file with the passed name
Writer(std::string name);
//! Write the data and close the file
virtual ~Writer();
/** \name Frames
The writer has a concept of the current frame. Depending on
the implementation, each frame might be stored in a separate
file or they might all be in one file. If using a writer that
stores frames in multiple files, you should include a %1% in the
filename which will get replaced by the frame number.
@{
*/
void set_frame(unsigned int i);
int get_frame() const { return frame_; }
/** @} */
/** @name Geometry Addition methods
These methods can be used to add geometry to the model.
If you do not want the geometry objects to be destroyed
upon addition, make sure you store an IMP::Pointer
to them externally.
\throws UsageException if it doesn't know
how to write that particular sort of geometry.
@{
*/
void add_geometry(Geometry* g);
void add_geometry(const Geometries& g) {
for (unsigned int i = 0; i < g.size(); ++i) {
IMP_CHECK_OBJECT(g[i]);
IMP::PointerMember<Geometry> gp(g[i]);
add_geometry(gp);
}
}
/** @} */
protected:
//! A hook for implementation classes to use to take actions on file close
virtual void do_close() = 0;
//! A hook for implementation classes to use to take actions on file open
virtual void do_open() = 0;
//! in case you want to take action on a new frame
virtual void do_set_frame() {}
};
/** A base class for writers which write to text files. By default,
separate frames are stored in separate files. To change this,
override the do_set_frame() method.
\note If you inherit from this class, you must use the
IMP_TEXT_WRITER() macro and not provide any additional
constructors. Sorry, it is necessary in order to ensure
that the derived classes handler for opening a file
is successfully called, as it can't be directly
called from the TextWriter constructor.
*/
class IMPDISPLAYEXPORT TextWriter : public Writer {
std::string file_name_;
TextOutput out_;
protected:
void open();
//! Get the stream for inheriting classes to write to
std::ostream& get_stream() { return out_; }
virtual void do_set_frame() override;
public:
//! Create a writer opening the file with the passed sink
/** Frames are not supported with this constructor when using a format
such as CMM or Chimera that writes multiple frames to different
files.
*/
TextWriter(TextOutput fn);
//! Create a write for a file or files with the passed name or pattern
/** The name should contain %1% if you want to write different frames
to separate files. Otherwise, it will either write all frames to the
same file (Pymol) or overwrite the file with each new frame,
Chimera, CMM.
*/
TextWriter(std::string name);
//! get the name of the current file being written
std::string get_current_file_name() const {
if (file_name_.find("%1%") != std::string::npos) {
IMP_USAGE_CHECK(get_frame() >= 0, "No frame set");
std::ostringstream oss;
oss << boost::format(file_name_) % get_frame();
return oss.str();
} else {
return file_name_;
}
}
//! Write the data and close the file
virtual ~TextWriter();
};
/** Create an appropriate writer based on the file suffix. */
IMPDISPLAYEXPORT Writer* create_writer(std::string filename);
IMP_OBJECTS(Writer, Writers);
IMP_OBJECTS(TextWriter, TextWriters);
/** An adaptor for functions that should take a writer as an input.
It can be implicitly constructed from either a Writer or a string.
In the later case it determines what type of writer is needed from
the file suffix. */
class IMPDISPLAYEXPORT WriterAdaptor : public InputAdaptor {
IMP::PointerMember<Writer> writer_;
public:
WriterAdaptor(std::string name) : writer_(create_writer(name)) {}
WriterAdaptor(Writer* w) : writer_(w) {}
#ifndef SWIG
Writer* operator->() const { return writer_; }
operator Writer*() const { return writer_; }
#endif
Writer* get_writer() const { return writer_; }
IMP_SHOWABLE_INLINE(WriterAdaptor, out << writer_->get_name());
~WriterAdaptor();
};
IMP_VALUES(WriterAdaptor, WriterAdaptors);
IMPDISPLAY_END_NAMESPACE
#endif /* IMPDISPLAY_WRITER_H */