Rosetta 3.5
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
PyMolMover.cc
Go to the documentation of this file.
1 // -*- mode:c++;tab-width:2;indent-tabs-mode:t;show-trailing-whitespace:t;rm-trailing-spaces:t -*-
2 // vi: set ts=2 noet:
3 //
4 // (c) Copyright Rosetta Commons Member Institutions.
5 // (c) This file is part of the Rosetta software suite and is made available under license.
6 // (c) The Rosetta software is developed by the contributing members of the Rosetta Commons.
7 // (c) For more information, see http://www.rosettacommons.org. Questions about this can be
8 // (c) addressed to University of Washington UW TechTransfer, email: license@u.washington.edu.
9 
10 /// @file protocols/moves/PyMolMover.cc
11 /// @brief Send infromation to PyMol
12 /// @author Sergey Lyskov
13 
14 #ifndef INCLUDED_protocols_moves_PyMolMover_CC
15 #define INCLUDED_protocols_moves_PyMolMover_CC
16 
18 
20 
21 //#ifndef WIN_PYROSETTA // CL compiler got horribly confused if our numeric header got included after <winsock2.h>
22 
23 // AUTO-REMOVED #include <numeric/random/random.hh>
24 
25 #include <core/pose/Pose.hh>
26 #include <core/pose/PDBInfo.hh>
27 // AUTO-REMOVED #include <core/io/pdb/pose_io.hh>
28 
29 #include <core/scoring/Energies.hh>
30 
31 // AUTO-REMOVED #include <utility/io/zipstream.hpp>
32 
33 #include <basic/Tracer.hh>
34 
35 
36 #include <time.h>
37 
38 #include <utility/vector1.hh>
39 #include <utility/io/zipstream.ipp>
40 
41 #include <utility/PyAssert.hh>
42 
43 //Auto Headers
44 #include <numeric/random/uniform.hh>
45 //#endif
46 
47 //#include <cstdlib.h>
48 
49 /*#if !defined(WINDOWS) && !defined(WIN32)
50  #include <sys/time.h>
51 #endif
52 */
53 
54 #ifndef _WIN32
55  #include "pthread.h"
56 #endif
57 
58 
59 namespace protocols {
60 namespace moves {
61 
62 static basic::Tracer TR("protocols.moves.PyMolMover");
63 
64 //static numeric::random::RandomGenerator RG(9636236);
65 
66 /// We using independent RG which is not connected to RNG system because we do not want PyMOL to interfere with other Rosetta systems.
67 /// I.e creating and using PyMOL mover should not change any trajectories of the running program even in production mode.
68 numeric::random::uniform_RG_OP getRG()
69 {
70  static numeric::random::uniform_RG_OP RG = 0;
71 
72  if( RG == 0 ) {
73  //RG = new numeric::random::mt19937_RG;
74  RG = new numeric::random::standard_RG;
75  RG->setSeed( time(NULL) );
76  }
77 
78  return RG;
79 }
80 
81 
83 {
84 #ifndef __native_client__
85  /*
86  #ifdef __APPLE__
87  max_packet_size_ = 8192-512-2; // ← MacOS X kernel can send only small packets even locally.
88  #else
89  max_packet_size_ = 64512; // 1024*63
90  #endif */
91 
92  max_packet_size_ = 8192-512-2; // Choosing max pocket size seems to be less obvious when we have cross OS link, we have to pick less common denominator
93 
94  //#ifndef WIN_PYROSETTA
95  // generating random uuid by hands
96  for(unsigned int i=0; i<sizeof(uuid_.shorts_)/sizeof(uuid_.shorts_[0]); i++) uuid_.shorts_[i] = (unsigned short) getRG()->getRandom()*65536; //RG.random_range(0, 65536);
97 
98  memset(&socket_addr_, '\0', sizeof(sockaddr_in));
99 
100  socket_addr_.sin_family = AF_INET; // host byte order
101  socket_addr_.sin_port = htons(65000); // short, network byte order
102  socket_addr_.sin_addr.s_addr = inet_addr("127.0.0.1");
103 
104  socket_h_ = socket(AF_INET, SOCK_DGRAM, 0);
105  //#endif
106 #endif
107 }
108 
110 {
111  //#ifndef WIN_PYROSETTA
112  #ifdef WIN32
113  closesocket(socket_h_);
114  #else
115  close(socket_h_);
116  #endif
117  //#endif
118 }
119 
121 {
122  int count = 1;
123  if( msg.size() > max_packet_size_ ) { count = msg.size()/max_packet_size_ + 1; }
124 
125  for(int i=0; i<count; i++) {
126  unsigned int last = (i+1)*max_packet_size_;
127  if( last>msg.size() ) last = msg.size();
128  sendRAWMessage(sentCount_, i, count, &msg[i*max_packet_size_], &msg[last] );
129  if(count > 1) {
130  #ifdef _WIN32
131  Sleep(10); // Sleep function takes milliseconds.
132  #else
133  timespec ts; ts.tv_sec=0; ts.tv_nsec=1000000; //time to sleep in nanoseconds, we want to take a nap for ~0.001sec
134  nanosleep(&ts, NULL);
135  #endif
136  }
137  }
138 
139  sentCount_++;
140 }
141 
142 void UDPSocketClient::sendRAWMessage(int globalPacketID, int packetI, int packetCount, char * msg_begin, char *msg_end)
143 {
144  #ifndef __native_client__
145  std::string buf(msg_end - msg_begin + sizeof(uuid_.bytes_) + sizeof(short)*3, 0);
146  int i = 0;
147 
148  memcpy(&buf[i], uuid_.bytes_, sizeof(uuid_.bytes_)); i+= sizeof(uuid_.bytes_);
149  memcpy(&buf[i], &globalPacketID, 2); i+=2;
150  memcpy(&buf[i], &packetI, 2); i+=2;
151  memcpy(&buf[i], &packetCount, 2); i+=2;
152  memcpy(&buf[i], msg_begin, msg_end-msg_begin); i+=msg_end-msg_begin;
153  //#ifndef WIN_PYROSETTA
154  sendto(socket_h_, &buf[0], buf.size(), 0 , (struct sockaddr *)&socket_addr_, sizeof(struct sockaddr_in));
155  //#endif
156  #endif
157 }
158 
159 
160 
161 /* -------------------------------------------------------------------------------------------------
162  PyMolMover Class
163  ---------------------------------------------------------------------------------------------- */
164 
166 
168 {
169  return "PyMOL_Mover";
170 }
171 
173 {
174  if( name_.size() ) return name_;
175  else {
177  if( info ) {
178  std::string n = info->name();
179  for(unsigned int i=0; i<n.size(); i++)
180  if( n[i] == '/' ) n[i] = '_';
181  return n;
182  }
183  else return "pose";
184  }
185 }
186 
187 
189 {
190  // First let's check if enough time have passes since last time we send info...
191  //double t = clock() / CLOCKS_PER_SEC;
192  double t = time(NULL);
193  //TR << "t=" << t << " cl="<< clock() << std::endl;
194  if( t - last_packet_sent_time_ < update_interval_ ) return false;
196  return true;
197 }
198 
199 
200 void PyMolMover::apply( Pose const & pose)
201 {
202  TR.Trace << "PyMolMover::apply( Pose const & pose)..." << std::endl;
203 
204  if( !is_it_time() ) return;
205  TR.Trace << "PyMOL_Mover::apply It is time!" << std::endl;
206 
208 
209  TR.Trace << "PyMOL_Mover::apply name:" << name << std::endl;
210 
211  // Creating message...
212  std::ostringstream os;
213  pose.dump_pdb(os);
214 
215  // Compressing message
216  std::ostringstream zmsg;
217  zlib_stream::zip_ostream zipper(zmsg, true);
218  zipper << os.str();
219  zipper.zflush_finalize();
220 
221  //std::string message = "PDB X" + name + zmsg.str();
222  std::string message = "PDB.gzipXX" + name + zmsg.str();
223  message[8] = keep_history_;
224  message[9] = name.size();
225 
226  //TR << "Sending message: " << message << std::endl << "Size:" << message.size() << std::endl;
227  //TR << "Sending message, Size:" << message.size() << std::endl;
228 
229  link_.sendMessage(message);
230 
232 }
233 
234 void PyMolMover::apply( Pose & pose)
235 {
236  Pose const & p(pose);
237  apply(p);
238 }
239 
240 void PyMolMover::print(std::string const & message)
241 {
242  if( !is_it_time() ) return;
243 
244  std::string msg = std::string("Text ") + char(keep_history_) + char(0) /* Place holder for name size = 0 */ + message;
245 
246  link_.sendMessage(msg);
247 }
248 
249 void PyMolMover::send_RAW_Energies(Pose const &pose, std::string energyType, utility::vector1<int> const & energies)
250 {
251  if( !is_it_time() ) return;
252 
253  std::string msg(7*energies.size(), ' ');
255  for(unsigned int i=1; i<=energies.size(); i++) {
256  char chain = ' ';
257  int res = i;
258  if(info) {
259  chain = info->chain(i);
260  res = info->number(i);
261  }
262  char buf[256];
263  sprintf(buf, "%c%4d%02x", chain, res, energies[i]);
264  for(int k=0; k<7; k++) msg[(i-1)*7+k] = buf[k];
265  }
266  //TR << msg << std::endl;
267 
268  // Compressing message
269  std::ostringstream zmsg;
270  zlib_stream::zip_ostream zipper(zmsg, true);
271  zipper << msg;
272  zipper.zflush_finalize();
273 
275  std::string sname = energyType;
276 
277  std::string message = std::string("Ene.gzip") + char(keep_history_) \
278  + char(name.size()) + name \
279  + char(sname.size()) + sname + zmsg.str();
280 
281  //TR << "Sending message: " << message << std::endl << "Size:" << message.size() << std::endl;
282  //TR << "Sending message, Size:" << message.size() << std::endl;
283 
284  link_.sendMessage(message);
285 }
286 
288 {
289  if( !is_it_time() ) return;
290 
291  if( pose.energies().energies_updated() ) {
292 
294  core::Real min=1e100, max=1e-100;
295  for(unsigned int i=1; i<=e.size(); i++) {
296  if( score_type == core::scoring::total_score ) e[i] = pose.energies().residue_total_energy(i);
297  else e[i] = pose.energies().residue_total_energies(i)[score_type];
298 
299  if( min > e[i] ) min = e[i];
300  if( max < e[i] ) max = e[i];
301  }
302  // We not using send_RAW_Energies for efficiency reasons...
303  std::string msg(7*e.size(), ' ');
305  for(unsigned int i=1; i<=e.size(); i++) {
306  char chain = ' ';
307  int res = i;
308  if(info) {
309  chain = info->chain(i);
310  res = info->number(i);
311  }
312  char buf[256];
313  e[i] = (e[i]-min)*255. / (max-min+1e-100);
314  sprintf(buf, "%c%4d%02x", chain, res, int(e[i]));
315  for(int k=0; k<7; k++) msg[(i-1)*7+k] = buf[k];
316  }
317  //TR << msg << std::endl;
318 
319  // Compressing message
320  std::ostringstream zmsg;
321  zlib_stream::zip_ostream zipper(zmsg, true);
322  zipper << msg;
323  zipper.zflush_finalize();
324 
327 
328  std::string message = std::string("Ene.gzip") + char(keep_history_) \
329  + char(name.size()) + name \
330  + char(sname.size()) + sname + zmsg.str();
331 
332  //TR << "Sending message: " << message << std::endl << "Size:" << message.size() << std::endl;
333  //TR << "Sending message, Size:" << message.size() << std::endl;
334 
335  link_.sendMessage(message);
336  }
337 }
338 
339 /// Send specified energy to PyMOL.
340 void PyMolMover::send_energy(Pose const &pose, std::string const & stype)
341 {
343 }
344 
345 
346 void PyMolMover::send_colors(Pose const &pose, std::map<int, int> const & colors, X11Colors default_color)
347 {
348  utility::vector1<int> energies( pose.total_residue(), default_color); // energies = [ X11Colors[default_color][0] ] * pose.total_residue()
349 
350  for(std::map<int, int>:: const_iterator i = colors.begin(); i!=colors.end(); ++i) {
351  PyAssert( (*i).first >=1 && (*i).first <= pose.total_residue(), "PyMolMover::send_colors residue index is out of range!");
352  PyAssert( (*i).second >= XC_first_color && (*i).second <= XC_last_color, "PyMolMover::send_colors color index is out of range!");
353 
354  energies[ (*i).first ] = (*i).second; // for r in colors: energies[r-1] = X11Colors[ colors[r] ][0]
355  }
356  send_RAW_Energies(pose, "X11Colors", energies); //self._send_RAW_Energies(pose, 'X11Colors', energies, autoscale=False)
357 }
358 
359 
360 
362 {
364 }
365 
367 {
369 }
370 
371 
372 PyMolObserverOP AddPyMolObserver(core::pose::Pose &p, bool keep_history, core::Real update_interval)
373 {
374  //Add options
376  o->pymol().keep_history(keep_history);
377  o->pymol().update_interval(update_interval);
379  return o;
380 }
381 
382 
383 } // moves
384 } // protocols
385 
386 #endif // INCLUDED_protocols_moves_PyMolMover_CC
387 
388 /*
389 #if (defined min) && (defined WIN32) // Workaround for MSVC and windows.h include which used #define min
390  #undef min
391 #endif
392 
393 #if (defined max) && (defined WIN32) // Workaround for MSVC and windows.h include which used #define max
394  #undef max
395 #endif
396 
397 */