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