IMP  2.0.0
The Integrative Modeling Platform
Writer.h
Go to the documentation of this file.
1 /**
2  * \file IMP/display/Writer.h
3  * \brief Base class for writing geometry to a file
4  *
5  * Copyright 2007-2013 IMP Inventors. All rights reserved.
6  */
7 
8 #ifndef IMPDISPLAY_WRITER_H
9 #define IMPDISPLAY_WRITER_H
10 
11 #include <IMP/display/display_config.h>
12 #include "declare_Geometry.h"
13 #include "internal/writers.h"
14 #include "GeometryProcessor.h"
15 #include <IMP/base/Pointer.h>
16 #include <IMP/base/InputAdaptor.h>
17 #include <IMP/file.h>
18 #include <IMP/PairContainer.h>
19 #include <IMP/SingletonContainer.h>
20 #include <IMP/RefCounted.h>
21 
22 #include <boost/format.hpp>
23 
24 IMPDISPLAY_BEGIN_NAMESPACE
25 
26 
27 //! Base class for writing geometry to a file.
28 /** A writer object accumulates geometry and then
29  writes a file when the object is destroyed. You must set the name
30  of the file being written to before writing using the
31  IMP::display::Writer::set_file_name() method.
32  */
33 class IMPDISPLAYEXPORT Writer:
35 {
36  int frame_;
37  public:
38  //! Create a writer opening the file with the passed name
39  Writer(std::string name);
40 
41  //! Write the data and close the file
42  virtual ~Writer();
43 
44  /** \name Frames
45  The writer has a concept of the current frame. Depending on
46  the implementation, each frame might be stored in a separate
47  file or they might all be in one file. If using a writer that
48  stores frames in multiple files, you should include a %1% in the
49  filename which will get replaced by the frame number.
50  @{
51  */
52  void set_frame(unsigned int i);
53  int get_frame() const {
54  return frame_;
55  }
56  /** @} */
57 
58 
59  /** @name Geometry Addition methods
60  These methods can be used to add geometry to the model.
61  If you do not want the geometry objects to be destroyed
62  upon addition, make sure you store an IMP::Pointer
63  to them externally.
64 
65  \throws UsageException if it doesn't know
66  how to write that particular sort of geometry.
67  @{
68  */
69  void add_geometry(Geometry* g);
70 
71  void add_geometry(const Geometries &g) {
72  for (unsigned int i=0; i< g.size(); ++i) {
73  IMP_CHECK_OBJECT(g[i]);
75  add_geometry(gp);
76  }
77  }
78  /** @} */
79 
80 protected:
81  //! A hook for implementation classes to use to take actions on file close
82  virtual void do_close()=0;
83  //! A hook for implementation classes to use to take actions on file open
84  virtual void do_open()=0;
85  //! in case you want to take action on a new frame
86  virtual void do_set_frame() {}
87 };
88 
89 
90 /** A base class for writers which write to text files. By default,
91  separate frames are stored in separate files. To change this,
92  override the do_set_frame() method.
93 
94  \note If you inherit from this class, you must use the
95  IMP_TEXT_WRITER() macro and not provide any additional
96  constructors. Sorry, it is necessary in order to ensure
97  that the derived classes handler for opening a file
98  is successfully called, as it can't be directly
99  called from the TextWriter constructor.
100  */
101 class IMPDISPLAYEXPORT TextWriter: public Writer
102 {
103  std::string file_name_;
104  base::TextOutput out_;
105  protected:
106  void open();
107  //! Get the stream for inhereting classes to write to
108  std::ostream& get_stream() {
109  return out_;
110  }
111 
112  void do_set_frame();
113 
114  public:
115  //! Create a writer opening the file with the passed sink
116  /** Frames are not supported with this constructor when using a format
117  such as CMM or Chimera that writes multiple frames to different
118  files.
119  */
121  //! Create a write for a file or files with the passed name or pattern
122  /** The name should contain %1% if you want to write different frames
123  to separate files. Otherwise, it will either write all frames to the
124  same file (Pymol) or overwrite the file with each new frame,
125  Chimera, CMM.
126  */
127  TextWriter(std::string name);
128 
129  //! get the name of the current file being writter
130  std::string get_current_file_name() const {
131  if (file_name_.find("%1%") != std::string::npos) {
132  IMP_USAGE_CHECK(get_frame()>=0, "No frame set");
133  std::ostringstream oss;
134  oss << boost::format(file_name_)%get_frame();
135  return oss.str();
136  } else {
137  return file_name_;
138  }
139  }
140  //! Write the data and close the file
141  virtual ~TextWriter();
142 };
143 
144 
145 /** Create an appropriate writer based on the file suffix. */
146 IMPDISPLAYEXPORT Writer *create_writer(std::string filename);
147 
148 
151 
152 
153 /** An adaptor for functions that should take a writer as an input.
154  It can be implicitly constructed from either a Writer or a string.
155  In the later case it determines what type of writer is needed from
156  the file suffix. */
157 class IMPDISPLAYEXPORT WriterAdaptor: public base::InputAdaptor {
159  public:
160  WriterAdaptor(std::string name): writer_(create_writer(name)){}
161  WriterAdaptor(Writer *w): writer_(w){}
162 #ifndef SWIG
163  Writer* operator->() const {
164  return writer_;
165  }
166  operator Writer*() const {
167  return writer_;
168  }
169 #endif
170  Writer* get_writer() const {
171  return writer_;
172  }
173  IMP_SHOWABLE_INLINE(WriterAdaptor, out << writer_->get_name());
174  ~WriterAdaptor();
175 };
176 
178 
179 IMPDISPLAY_END_NAMESPACE
180 
181 #endif /* IMPDISPLAY_WRITER_H */