5d553b4b696e46e30a36d09b704c0c87fa47dd20
[alexxy/gromacs.git] / src / ngmx / g_xrama.cpp
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 "xutil.h"
45 #include "futil.h"
46 #include "x11.h"
47 #include "smalloc.h"
48 #include "statutil.h"
49 #include "rama.bm"
50 #include "nrama.h"
51
52 #include "gromacs/commandline/cmdlinemodulemanager.h"
53
54 #define MAXDEG 360
55
56 enum {
57     ebQuit, ebStart, ebStop, ebRewind, ebGly, ebutNR
58 };
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 {
65     esStop, esGo, esNR
66 };
67
68 typedef struct {
69     int            status;
70     gmx_bool       bShowGly;
71     gmx_bool      *bIsGly;
72     t_windata      wd;
73     t_windata      xrwd;
74     t_xrama       *xr;
75     t_windata      but[ebutNR];
76 } t_app;
77
78 static void plot_pp(t_x11 *x11, Window w, t_phipsi *pp, t_dih dih[])
79 {
80     int x0, y0;
81     int th = (XTextHeight(x11->font)+6)/2;
82
83     x0 = SX(dih[pp->iphi].ang);
84     y0 = SY(dih[pp->ipsi].ang);
85     XFillRectangle(x11->disp, w, x11->gc, x0-1, y0-1, 4, 4);
86     /* Draw Label ? */
87     if (pp->bShow)
88     {
89         TextInRect(x11, w, pp->label, x0+6, y0-th, 30, 2*th, eXLeft, eYCenter);
90     }
91 }
92
93 static gmx_bool label_pp(t_x11 *x11, Window w, int npp, t_phipsi pp[],
94                          t_dih dih[], int mx, int my)
95 {
96     int d, md, x0, y0;
97     int i, imin;
98
99     imin = -1;
100     md   = 16;
101     for (i = 0; (i < npp); i++)
102     {
103         x0 = SX(dih[pp[i].iphi].ang);
104         y0 = SY(dih[pp[i].ipsi].ang);
105         d  = (mx-x0)*(mx-x0)+(my-y0)*(my-y0);
106         if (d < md)
107         {
108             md   = d;
109             imin = i;
110         }
111     }
112     if (imin != -1)
113     {
114         pp[imin].bShow = !pp[imin].bShow;
115         return TRUE;
116     }
117     return FALSE;
118 }
119
120 static gmx_bool xrCallBack(struct t_x11 *x11, XEvent *event, Window w, void *data)
121 {
122     t_app   *app;
123     t_xrama *xr;
124     char     buf[256];
125     int      i;
126
127     (void)XTextHeight(x11->font);
128     app = (t_app *)data;
129     xr  = app->xr;
130     scx = app->xrwd.width/(2.0*M_PI);
131     scy = app->xrwd.height/(2.0*M_PI);
132     switch (event->type)
133     {
134         case Expose:
135             XClearWindow(x11->disp, app->xrwd.self);
136             XDrawLine(x11->disp, app->xrwd.self, x11->gc,
137                       SX(0), SY(-M_PI)+1, SX(0), SY(M_PI)-1);
138             XDrawLine(x11->disp, app->xrwd.self, x11->gc,
139                       SX(-M_PI)+1, SY(0), SX(M_PI)-1, SY(0));
140             TextInRect(x11, app->xrwd.self, "Phi", SX(M_PI)-50, SY(0)+4, 46, 20, eXRight, eYTop);
141             TextInRect(x11, app->xrwd.self, "Psi", SX(0)+4, 4, 46, 20, eXLeft, eYTop);
142             for (i = 0; (i < xr->npp); i++)
143             {
144                 if (app->bShowGly || !app->bIsGly[i])
145                 {
146                     plot_pp(x11, app->xrwd.self, &(xr->pp[i]), xr->dih);
147                 }
148             }
149             break;
150         case ButtonPress:
151             if (label_pp(x11, app->xrwd.self, xr->npp, xr->pp, xr->dih,
152                          event->xbutton.x, event->xbutton.y))
153             {
154                 ExposeWin(x11->disp, app->xrwd.self);
155             }
156             break;
157         case ConfigureNotify:
158             app->xrwd.width  = event->xconfigure.width;
159             app->xrwd.height = event->xconfigure.height;
160             break;
161     }
162     if (app->status == esGo)
163     {
164         if (!new_data(app->xr))
165         {
166             app->status = ebStop;
167         }
168         else
169         {
170             ExposeWin(x11->disp, app->xrwd.self);
171             sprintf(buf, "Rama: t=%.2f", app->xr->t);
172             XSetStandardProperties(x11->disp, app->wd.self, buf,
173                                    "Rama", 0, NULL, 0, NULL);
174
175         }
176     }
177     return FALSE;
178 }
179
180 static gmx_bool appCallBack(struct t_x11 *x11, XEvent *event, Window w, void *data)
181 {
182     t_app  *app;
183     int     win;
184
185     app = (t_app *)data;
186     for (win = 0; (win < ebutNR); win++)
187     {
188         if (app->but[win].self == w)
189         {
190             break;
191         }
192     }
193     if (win == ebutNR)
194     {
195         return FALSE;
196     }
197
198     switch (event->type)
199     {
200         case Expose:
201             TextInWin(x11, &(app->but[win]), app->but[win].text, eXCenter, eYCenter);
202             break;
203         case ButtonPress:
204             switch (win)
205             {
206                 case ebQuit:
207                     exit(1);
208                 case ebStart:
209                     app->status = esGo;
210                     ExposeWin(x11->disp, app->xrwd.self);
211                     break;
212                 case ebStop:
213                     app->status = esStop;
214                     break;
215                 case ebRewind:
216                     rewind_trj(app->xr->traj);
217                     break;
218                 case ebGly:
219                     app->bShowGly = !app->bShowGly;
220                     ExposeWin(x11->disp, app->xrwd.self);
221                     break;
222                 default:
223                     XBell(x11->disp, 50);
224                     break;
225             }
226             break;
227     }
228     return FALSE;
229 }
230
231 static void size_app(t_x11 *x11, t_app *app)
232 {
233     int i, dx, th;
234
235     th = XTextHeight(x11->font)+4;
236     dx = app->wd.width/ebutNR;
237     for (i = 0; (i < ebutNR); i++)
238     {
239         app->but[i].width  = dx-4;
240         app->but[i].height = th+4;
241         XMoveResizeWindow(x11->disp, app->but[i].self, i*dx+2, 2, dx-4, th+4);
242     }
243     XMoveResizeWindow(x11->disp, app->xrwd.self, 2, th+10,
244                       app->wd.width-6, app->wd.height-th-10-4);
245 }
246
247 static gmx_bool mainCallBack(struct t_x11 *x11, XEvent *event, Window w, void *data)
248 {
249     t_app *app;
250     int    wt, ht;
251
252     app = (t_app *)data;
253     switch (event->type)
254     {
255         case ConfigureNotify:
256             wt = event->xconfigure.width;
257             ht = event->xconfigure.height;
258             if ((app->wd.width != wt) || (app->wd.height != ht))
259             {
260                 fprintf(stderr, "New wxh = %dx%d\n", wt, ht);
261                 app->wd.width  = wt;
262                 app->wd.height = ht;
263                 size_app(x11, app);
264             }
265             break;
266     }
267     return FALSE;
268 }
269
270 static t_xrama *init_xrama(t_x11 *x11, Window Parent, int y0, t_app *app)
271 {
272     t_xrama *xr;
273
274     snew(xr, 1);
275
276     InitWin(&(app->xrwd), 2, y0, MAXDEG+1, MAXDEG+1, 1, "Ramachandran Movie");
277     app->xrwd.self = XCreateSimpleWindow(x11->disp, Parent, app->xrwd.x, app->xrwd.y,
278                                          app->xrwd.width, app->xrwd.height,
279                                          app->xrwd.bwidth, x11->fg, x11->bg);
280     x11->RegisterCallback(x11, app->xrwd.self, Parent, xrCallBack, app);
281     x11->SetInputMask(x11, app->xrwd.self, ButtonPressMask | ExposureMask |
282                       StructureNotifyMask);
283
284     return xr;
285 }
286
287 static t_app *init_app(t_x11 *x11, int argc, char *argv[])
288 {
289     static const char *but_nm[ebutNR] = { "Quit", "Start", "Stop", "Rewind", "Toggle Gly" };
290     XSizeHints         hints;
291     Pixmap             pm;
292     int                th;
293     t_app             *app;
294     t_windata         *wd;
295     int                i, dx;
296
297     snew(app, 1);
298     th = XTextHeight(x11->font)+4;
299     InitWin(&(app->wd), 0, 0, MAXDEG+6, MAXDEG+6+th+6, 0, "Ramachandran Movie");
300     dx           = app->wd.width/ebutNR;
301     app->wd.self = XCreateSimpleWindow(x11->disp, x11->root, app->wd.x, app->wd.y,
302                                        app->wd.width, app->wd.height,
303                                        app->wd.bwidth, x11->fg, x11->bg);
304     x11->RegisterCallback(x11, app->wd.self, x11->root, mainCallBack, app);
305     x11->SetInputMask(x11, app->wd.self, StructureNotifyMask);
306     hints.flags = 0;
307     pm          = XCreatePixmapFromBitmapData(x11->disp, x11->root, (char *)rama_bits,
308                                               rama_width, rama_height, WHITE, BLACK, 1);
309     XSetStandardProperties(x11->disp, app->wd.self, app->wd.text,
310                            "Rama", pm, argv, argc, &hints);
311     x11->RegisterCallback(x11, app->wd.self, x11->root, appCallBack, app);
312     x11->SetInputMask(x11, app->wd.self, ButtonPressMask | ExposureMask |
313                       StructureNotifyMask);
314
315     app->xr = init_xrama(x11, app->wd.self, th+6, app);
316     for (i = 0; (i < ebutNR); i++)
317     {
318         wd = &(app->but[i]);
319         InitWin(wd, i*dx+2, 2, dx-4, th, 1, but_nm[i]);
320         wd->self = XCreateSimpleWindow(x11->disp, app->wd.self,
321                                        wd->x, wd->y, wd->width, wd->height,
322                                        wd->bwidth, x11->fg, x11->bg);
323         x11->RegisterCallback(x11, wd->self, app->wd.self, appCallBack, app);
324         x11->SetInputMask(x11, wd->self, ButtonPressMask | ExposureMask);
325     }
326     return app;
327 }
328
329 static void mk_gly(t_app *app)
330 {
331     int i;
332
333     snew(app->bIsGly, app->xr->npp);
334     for (i = 0; (i < app->xr->npp); i++)
335     {
336         if (strstr(app->xr->pp[i].label, "GLY") != NULL)
337         {
338             app->bIsGly[i] = TRUE;
339         }
340     }
341 }
342
343 int gmx_xrama(int argc, char *argv[])
344 {
345     const char  *desc[] = {
346         "[TT]g_xrama[tt] shows a Ramachandran movie, that is, it shows",
347         "the Phi/Psi angles as a function of time in an X-Window.[PAR]"
348         "Static Phi/Psi plots for printing can be made with [TT]g_rama[tt].[PAR]",
349         "Some of the more common X command line options can be used:[BR]",
350         "[TT]-bg[tt], [TT]-fg[tt] change colors, [TT]-font fontname[tt], changes the font."
351     };
352
353     output_env_t oenv;
354     t_x11       *x11;
355     t_app       *app;
356     t_filenm     fnm[] = {
357         { efTRX, "-f", NULL, ffREAD },
358         { efTPX, NULL, NULL, ffREAD }
359     };
360 #define NFILE asize(fnm)
361
362     if (!parse_common_args(&argc, argv, PCA_CAN_TIME, NFILE, fnm,
363                            0, NULL, asize(desc), desc, 0, NULL, &oenv))
364     {
365         return 0;
366     }
367
368
369     if ((x11 = GetX11(&argc, argv)) == NULL)
370     {
371         fprintf(stderr, "Can't open display, set your DISPLAY environment variable\n");
372         exit(1);
373     }
374     XSetForeground(x11->disp, x11->gc, x11->fg);
375     app = init_app(x11, argc, argv);
376
377     init_rama(oenv, ftp2fn(efTRX, NFILE, fnm), ftp2fn(efTPX, NFILE, fnm),
378               app->xr, 3);
379     mk_gly(app);
380
381     XMapWindow(x11->disp, app->wd.self);
382     XMapSubwindows(x11->disp, app->wd.self);
383     x11->MainLoop(x11);
384     x11->CleanUp(x11);
385
386     return 0;
387 }
388
389 int main(int argc, char *argv[])
390 {
391     return gmx::CommandLineModuleManager::runAsMainCMain(argc, argv, &gmx_xrama);
392 }