563a13fa565c406f0f3b0220fa582e2896851f41
[alexxy/gromacs.git] / src / ngmx / g_xrama.c
1 /*
2  * 
3  *                This source code is part of
4  * 
5  *                 G   R   O   M   A   C   S
6  * 
7  *          GROningen MAchine for Chemical Simulations
8  * 
9  *                        VERSION 3.2.0
10  * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
11  * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
12  * Copyright (c) 2001-2004, The GROMACS development team,
13  * check out http://www.gromacs.org for more information.
14
15  * This program is free software; you can redistribute it and/or
16  * modify it under the terms of the GNU General Public License
17  * as published by the Free Software Foundation; either version 2
18  * of the License, or (at your option) any later version.
19  * 
20  * If you want to redistribute modifications, please consider that
21  * scientific software is very special. Version control is crucial -
22  * bugs must be traceable. We will be happy to consider code for
23  * inclusion in the official distribution, but derived work must not
24  * be called official GROMACS. Details are found in the README & COPYING
25  * files - if they are missing, get the official version at www.gromacs.org.
26  * 
27  * To help us fund GROMACS development, we humbly ask that you cite
28  * the papers on the package - you can find them in the top README file.
29  * 
30  * For more info, check our website at http://www.gromacs.org
31  * 
32  * And Hey:
33  * Gyas ROwers Mature At Cryogenic Speed
34  */
35 #ifdef HAVE_CONFIG_H
36 #include <config.h>
37 #endif
38
39 #include <stdlib.h>
40 #include <math.h>
41 #include <string.h>
42 #include "macros.h"
43 #include "Xstuff.h"
44 #include "copyrite.h"
45 #include "xutil.h"
46 #include "futil.h"
47 #include "x11.h"
48 #include "smalloc.h"
49 #include "statutil.h"
50 #include "rama.bm"
51 #include "nrama.h"
52
53 #define MAXDEG 360
54
55 enum { ebQuit, ebStart, ebStop, ebRewind, ebGly, ebutNR };
56
57 static real scx,scy;
58 #define SX(x) ((int)(((x)+M_PI)*scx))
59 #define SY(y) ((int)((M_PI-(y))*scy))
60
61 enum { esStop, esGo, esNR };
62
63 typedef struct {
64   int       status;
65   gmx_bool      bShowGly;
66   gmx_bool      *bIsGly;
67   t_windata wd;
68   t_windata xrwd;
69   t_xrama   *xr;
70   t_windata but[ebutNR];
71 } t_app;
72
73 static void plot_pp(t_x11 *x11,Window w,t_phipsi *pp,t_dih dih[])
74 {
75   int x0,y0;
76   int th=(XTextHeight(x11->font)+6)/2;
77   
78   x0=SX(dih[pp->iphi].ang);
79   y0=SY(dih[pp->ipsi].ang);
80   XFillRectangle(x11->disp,w,x11->gc,x0-1,y0-1,4,4);
81   /* Draw Label ? */
82   if (pp->bShow) 
83     TextInRect(x11,w,pp->label,x0+6,y0-th,30,2*th,eXLeft,eYCenter);
84 }
85
86 static gmx_bool label_pp(t_x11 *x11,Window w,int npp,t_phipsi pp[],
87                      t_dih dih[],int mx,int my)
88 {
89   int d,md,x0,y0;
90   int i,imin;
91   
92   imin=-1;
93   md=16;
94   for(i=0; (i<npp); i++) {
95     x0=SX(dih[pp[i].iphi].ang);
96     y0=SY(dih[pp[i].ipsi].ang);
97     d=(mx-x0)*(mx-x0)+(my-y0)*(my-y0);
98     if (d < md) {
99       md=d;
100       imin=i;
101     }
102   }
103   if (imin != -1) {
104     pp[imin].bShow=!pp[imin].bShow;
105     return TRUE;
106   }
107   return FALSE;
108 }
109
110 static gmx_bool xrCallBack(struct t_x11 *x11,XEvent *event, Window w, void *data)
111 {
112   t_app   *app;
113   t_xrama *xr;
114   char    buf[256];
115   int     i;
116   
117   (void)XTextHeight(x11->font);
118   app=(t_app *)data;
119   xr=app->xr;
120   scx=app->xrwd.width/(2.0*M_PI);
121   scy=app->xrwd.height/(2.0*M_PI);
122   switch (event->type) {
123   case Expose:
124     XClearWindow(x11->disp,app->xrwd.self);
125     XDrawLine(x11->disp,app->xrwd.self,x11->gc,
126               SX(0),SY(-M_PI)+1,SX(0),SY(M_PI)-1);
127     XDrawLine(x11->disp,app->xrwd.self,x11->gc,
128               SX(-M_PI)+1,SY(0),SX(M_PI)-1,SY(0));
129     TextInRect(x11,app->xrwd.self,"Phi",SX(M_PI)-50,SY(0)+4,46,20,eXRight,eYTop);
130     TextInRect(x11,app->xrwd.self,"Psi",SX(0)+4,4,46,20,eXLeft,eYTop);
131     for(i=0; (i<xr->npp); i++) 
132       if (app->bShowGly || !app->bIsGly[i])
133         plot_pp(x11,app->xrwd.self,&(xr->pp[i]),xr->dih);
134     break;
135   case ButtonPress:
136     if (label_pp(x11,app->xrwd.self,xr->npp,xr->pp,xr->dih,
137                  event->xbutton.x,event->xbutton.y))
138       ExposeWin(x11->disp,app->xrwd.self);
139     break;
140   case ConfigureNotify:
141     app->xrwd.width=event->xconfigure.width;
142     app->xrwd.height=event->xconfigure.height;
143     break;
144   }
145   if (app->status == esGo) {
146     if (!new_data(app->xr)) 
147       app->status=ebStop;
148     else {
149       ExposeWin(x11->disp,app->xrwd.self);
150       sprintf(buf,"Rama: t=%.2f",app->xr->t);
151       XSetStandardProperties(x11->disp,app->wd.self,buf,
152                              "Rama",0,NULL,0,NULL);
153       
154     }
155   }
156   return FALSE;
157 }
158
159 static gmx_bool appCallBack(struct t_x11 *x11,XEvent *event, Window w, void *data)
160 {
161   t_app  *app;
162   int    win;
163
164   app=(t_app *)data;
165   for(win=0; (win<ebutNR); win++)
166     if (app->but[win].self == w)
167       break;
168   if (win==ebutNR)
169     return FALSE;
170
171   switch(event->type) {
172   case Expose:
173     TextInWin(x11,&(app->but[win]),app->but[win].text,eXCenter,eYCenter);
174     break;
175   case ButtonPress:
176     switch (win) {
177     case ebQuit:
178       exit(1);
179     case ebStart:
180       app->status=esGo;
181       ExposeWin(x11->disp,app->xrwd.self);
182       break;
183     case ebStop:
184       app->status=esStop;
185       break;
186     case ebRewind:
187       rewind_trj(app->xr->traj);
188       break;
189     case ebGly:
190       app->bShowGly=!app->bShowGly;
191       ExposeWin(x11->disp,app->xrwd.self);
192       break;
193     default:
194       XBell(x11->disp,50);
195       break;
196     }
197     break;
198   }
199   return FALSE;
200 }
201
202 static void size_app(t_x11 *x11,t_app *app)
203 {
204   int i,dx,th;
205
206   th=XTextHeight(x11->font)+4;
207   dx=app->wd.width/ebutNR;
208   for(i=0; (i<ebutNR); i++) {
209     app->but[i].width=dx-4;
210     app->but[i].height=th+4;
211     XMoveResizeWindow(x11->disp,app->but[i].self,i*dx+2,2,dx-4,th+4);
212   }
213   XMoveResizeWindow(x11->disp,app->xrwd.self,2,th+10,
214                     app->wd.width-6,app->wd.height-th-10-4);
215 }
216
217 static gmx_bool mainCallBack(struct t_x11 *x11,XEvent *event, Window w, void *data)
218 {
219   t_app *app;
220   int   wt,ht;
221   
222   app=(t_app *)data;
223   switch (event->type) {
224   case ConfigureNotify:
225     wt=event->xconfigure.width;
226     ht=event->xconfigure.height;
227     if ((app->wd.width != wt) || (app->wd.height != ht)) {
228       fprintf(stderr,"New wxh = %dx%d\n",wt,ht);
229       app->wd.width=wt;
230       app->wd.height=ht;
231       size_app(x11,app);
232     }
233     break;
234   }
235   return FALSE;
236 }
237
238 static t_xrama *init_xrama(t_x11 *x11,Window Parent,int y0,t_app *app)
239 {
240   t_xrama *xr;
241
242   snew(xr,1);
243   
244   InitWin(&(app->xrwd),2,y0,MAXDEG+1,MAXDEG+1,1,"Ramachandran Movie");
245   app->xrwd.self=XCreateSimpleWindow(x11->disp,Parent,app->xrwd.x,app->xrwd.y,
246                                   app->xrwd.width,app->xrwd.height,
247                                   app->xrwd.bwidth,x11->fg,x11->bg);
248   x11->RegisterCallback(x11,app->xrwd.self,Parent,xrCallBack,app);
249   x11->SetInputMask(x11,app->xrwd.self,ButtonPressMask | ExposureMask |
250                     StructureNotifyMask);
251
252   return xr;
253 }
254
255 static t_app *init_app(t_x11 *x11,int argc,char *argv[])
256 {
257   static const char *but_nm[ebutNR] = { "Quit", "Start", "Stop", "Rewind", "Toggle Gly" };
258   XSizeHints hints;
259   Pixmap     pm;
260   int        th;
261   t_app      *app;
262   t_windata  *wd;
263   int        i,dx;
264
265   snew(app,1);
266   th=XTextHeight(x11->font)+4;
267   InitWin(&(app->wd),0,0,MAXDEG+6,MAXDEG+6+th+6,0,"Ramachandran Movie");
268   dx=app->wd.width/ebutNR;
269   app->wd.self=XCreateSimpleWindow(x11->disp,x11->root,app->wd.x,app->wd.y,
270                                   app->wd.width,app->wd.height,
271                                   app->wd.bwidth,x11->fg,x11->bg);
272   x11->RegisterCallback(x11,app->wd.self,x11->root,mainCallBack,app);
273   x11->SetInputMask(x11,app->wd.self,StructureNotifyMask);
274   hints.flags=0;
275   pm=XCreatePixmapFromBitmapData(x11->disp,x11->root,(char *)rama_bits,
276                                  rama_width,rama_height,WHITE,BLACK,1);
277   XSetStandardProperties(x11->disp,app->wd.self,app->wd.text,
278                          "Rama",pm,argv,argc,&hints);
279   x11->RegisterCallback(x11,app->wd.self,x11->root,appCallBack,app);
280   x11->SetInputMask(x11,app->wd.self,ButtonPressMask | ExposureMask |
281                     StructureNotifyMask);
282
283   app->xr=init_xrama(x11,app->wd.self,th+6,app);
284   for(i=0; (i<ebutNR); i++) {
285     wd=&(app->but[i]);
286     InitWin(wd,i*dx+2,2,dx-4,th,1,but_nm[i]);
287     wd->self=XCreateSimpleWindow(x11->disp,app->wd.self,
288                                  wd->x,wd->y,wd->width,wd->height,
289                                  wd->bwidth,x11->fg,x11->bg);
290     x11->RegisterCallback(x11,wd->self,app->wd.self,appCallBack,app);
291     x11->SetInputMask(x11,wd->self,ButtonPressMask | ExposureMask);
292   }
293   return app;
294 }
295
296 static void mk_gly(t_app *app)
297 {
298   int i;
299   
300   snew(app->bIsGly,app->xr->npp);
301   for(i=0; (i<app->xr->npp); i++) {
302     if (strstr(app->xr->pp[i].label,"GLY") != NULL)
303       app->bIsGly[i]=TRUE;
304   }
305
306
307 int main(int argc,char *argv[])
308 {
309   const char *desc[] = {
310     "[TT]g_xrama[tt] shows a Ramachandran movie, that is, it shows",
311     "the Phi/Psi angles as a function of time in an X-Window.[PAR]"
312     "Static Phi/Psi plots for printing can be made with [TT]g_rama[tt].[PAR]",
313     "Some of the more common X command line options can be used:[BR]",
314     "[TT]-bg[tt], [TT]-fg[tt] change colors, [TT]-font fontname[tt], changes the font."
315   };
316
317   output_env_t oenv;
318   t_x11     *x11;
319   t_topology *ramatop;
320   t_app     *app;
321   t_filenm  fnm[] = {
322     { efTRX, "-f", NULL, ffREAD },
323     { efTPX, NULL, NULL, ffREAD }
324   };
325 #define NFILE asize(fnm)
326
327   CopyRight(stderr,argv[0]);
328   parse_common_args(&argc,argv,PCA_CAN_TIME,NFILE,fnm,0,NULL,
329                     asize(desc),desc,0,NULL,&oenv);
330
331                       
332   if ((x11=GetX11(&argc,argv)) == NULL) {
333     fprintf(stderr,"Can't open display, set your DISPLAY environment variable\n");
334     exit(1);
335   }
336   XSetForeground(x11->disp,x11->gc,x11->fg);
337   app=init_app(x11,argc,argv);
338
339   ramatop = init_rama(oenv,ftp2fn(efTRX,NFILE,fnm),ftp2fn(efTPX,NFILE,fnm),
340                       app->xr,3);
341   mk_gly(app);
342   
343   XMapWindow(x11->disp,app->wd.self);
344   XMapSubwindows(x11->disp,app->wd.self);
345   x11->MainLoop(x11);
346   x11->CleanUp(x11);
347   
348   thanx(stderr);
349   
350   return 0;
351 }
352