23f883189f79e38f87f7a52b341b293171884140
[alexxy/gromacs.git] / src / ngmx / manager.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 <sysstuff.h>
40 #include <string.h>
41 #include <smalloc.h>
42 #include <ctype.h>
43 #include <typedefs.h>
44 #include <smalloc.h>
45 #include <tpxio.h>
46 #include <macros.h>
47 #include <maths.h>
48 #include <atomprop.h>
49 #include <names.h>
50 #include "manager.h"
51 #include "futil.h"
52 #include "pbc.h"
53 #include "nmol.h"
54 #include "copyrite.h"
55 #include "gstat.h"
56 #include "vec.h"
57 #include "statutil.h"
58 #include "string2.h"
59
60 static void add_object(t_manager *man,eObject eO,atom_id ai,atom_id aj)
61 {
62   srenew(man->obj,++man->nobj);
63   man->obj[man->nobj-1].eO    = eO;
64   man->obj[man->nobj-1].eV    = eVNormal;
65   man->obj[man->nobj-1].color = WHITE;
66   man->obj[man->nobj-1].ai    = ai;
67   man->obj[man->nobj-1].aj    = aj;
68   man->obj[man->nobj-1].z     = 0.0;
69 }
70
71 static void add_bonds(t_manager *man,t_functype func[],
72                       t_ilist *b,gmx_bool bB[])
73 {
74   gmx_bool    *bH=man->bHydro;
75   t_iatom *ia;
76   t_iatom type,ai,aj,ak;
77   int     i,delta,ftype;
78   
79 #ifdef DEBUG
80   fprintf(stderr,"Going to make bonds from an ilist with %d entries\n",b->nr);
81 #endif
82   ia=b->iatoms;
83   for(i=0; (i<b->nr); ) {
84     type  = ia[0];
85     ai    = ia[1];
86     ftype = func[type];
87     delta = interaction_function[ftype].nratoms;
88     
89     if (ftype == F_SETTLE) {
90       aj = ia[2];
91       ak = ia[3];
92       bB[ai]=bB[aj]=bB[ak]=TRUE;
93       add_object(man,eOHBond,ai,aj);
94       add_object(man,eOHBond,ai,ak);
95     }
96     else if (IS_CHEMBOND(ftype)) {
97       aj=ia[2];
98 #ifdef DEBUG
99       fprintf(stderr,"Adding bond from %d to %d\n",ai,aj);
100 #endif
101       bB[ai]=bB[aj]=TRUE;
102       if (!(bH[ai] == bH[aj])) 
103         add_object(man,eOHBond,ai,aj);
104       else if (!bH[ai] && !bH[aj]) 
105         add_object(man,eOBond,ai,aj);
106     }
107 #ifdef DEBUG
108     fprintf(stderr,"Type: %5d, delta: %5d\n",type,delta);
109 #endif
110     ia += delta+1;
111     i  += delta+1;
112   }
113 }
114
115 static void add_bpl(t_manager *man,t_idef *idef,gmx_bool bB[])
116 {
117   int ftype;
118
119   for(ftype=0; ftype<F_NRE; ftype++)
120     if (IS_CHEMBOND(ftype) || ftype==F_SETTLE)
121       add_bonds(man,idef->functype,&idef->il[ftype],bB);
122 }
123  
124 static atom_id which_atom(t_manager *man,int x, int y)
125 {
126 #define DELTA 5
127   int i;
128   iv2 *ix=man->ix;
129
130   for(i=0; (i<man->natom); i++) {
131     if ((abs(ix[i][XX]-x) < DELTA) && (abs(ix[i][YY]-y) < DELTA)) {
132       if (man->bVis[i]) 
133         return (atom_id) i;
134     }
135   }
136   return NO_ATID;
137 }
138
139 static void do_label(t_x11 *x11,t_manager *man,int x,int y,gmx_bool bSet)
140 {
141   atom_id ai;
142   unsigned long   col;
143
144   if ((ai=which_atom(man,x,y)) != NO_ATID) {
145     x=man->ix[ai][XX];
146     y=man->ix[ai][YY];
147     if (bSet && !man->bLabel[ai]) {
148       col=WHITE;
149       man->bLabel[ai]=TRUE;
150     }
151     else if (!bSet && man->bLabel[ai]) {
152       col=BLUE;
153       man->bLabel[ai]=FALSE;
154     }
155     else
156       return;
157     XSetForeground(x11->disp,x11->gc,col);
158     XDrawString(x11->disp,man->molw->wd.self,x11->gc,x+2,y-2,man->szLab[ai],
159                 strlen(man->szLab[ai]));
160     XSetForeground(x11->disp,x11->gc,x11->fg);
161   }
162 }
163
164 static void show_label(t_x11 *x11,t_manager *man,int x,int y)
165 {
166   do_label(x11,man,x,y,TRUE);
167 }
168
169 static void hide_label(t_x11 *x11,t_manager *man,int x,int y)
170 {
171   do_label(x11,man,x,y,FALSE);
172 }
173
174 void set_file(t_x11 *x11,t_manager *man,const char *trajectory,
175               const char *status)
176 {
177   gmx_atomprop_t aps;
178   char         buf[256],quote[256];
179   t_tpxheader  sh;
180   t_atoms      *at;
181   gmx_bool         *bB;
182   int          i,idum;
183
184   read_tpxheader(status,&sh,TRUE,NULL,NULL);
185   snew(man->ix,sh.natoms);
186   snew(man->zz,sh.natoms);
187   snew(man->col,sh.natoms);
188   snew(man->size,sh.natoms);
189   snew(man->vdw,sh.natoms);
190   snew(man->bLabel,sh.natoms);
191   snew(man->bVis,sh.natoms);
192   for(i=0; (i<sh.natoms); i++)
193     man->bVis[i]=FALSE;
194
195   man->bPbc=FALSE;
196
197   snew(man->szLab,sh.natoms);
198   snew(man->bHydro,sh.natoms);
199   snew(bB,sh.natoms);
200   read_tpx_top(status,NULL,man->box,&man->natom,NULL,NULL,NULL,&man->top);
201   man->gpbc = gmx_rmpbc_init(&man->top.idef,-1,man->natom,man->box);
202   
203   man->natom=
204     read_first_x(man->oenv,&man->status,trajectory,&(man->time),&(man->x),
205                  man->box);
206   man->trajfile=strdup(trajectory);
207   if (man->natom > man->top.atoms.nr)
208     gmx_fatal(FARGS,"Topology %s (%d atoms) and trajectory %s (%d atoms) "
209                 "do not match",status,man->top.atoms.nr,
210                 trajectory,man->natom);
211  
212   cool_quote(quote,255,NULL);
213   sprintf(buf,"%s: %s",*man->top.name,quote);
214   man->title.text = strdup(buf);
215   man->view       = init_view(man->box);
216   at  = &(man->top.atoms);
217   aps = gmx_atomprop_init();
218   for(i=0; (i<man->natom); i++) {
219     char *aname=*(at->atomname[i]);
220     t_resinfo *ri=&at->resinfo[at->atom[i].resind];
221
222     man->col[i]=Type2Color(aname);
223     snew(man->szLab[i],20);
224     if (ri->ic != ' ') {
225       sprintf(man->szLab[i],"%s%d%c, %s",*ri->name,ri->nr,ri->ic,aname);
226     } else {
227       sprintf(man->szLab[i],"%s%d, %s",*ri->name,ri->nr,aname);
228     }
229     man->bHydro[i]=(toupper(aname[0])=='H');
230     if ( man->bHydro[i] )
231       man->vdw[i]=0;
232     else if (!gmx_atomprop_query(aps,epropVDW,*ri->name,aname,&(man->vdw[i])))
233       man->vdw[i] = 0;
234   }
235   gmx_atomprop_destroy(aps);
236   add_bpl(man,&(man->top.idef),bB);
237   for(i=0; (i<man->natom); i++)
238     if (!bB[i]) 
239       add_object(man,eOSingle,(atom_id) i,0);
240   sfree(bB);
241
242   ExposeWin(x11->disp,man->molw->wd.self);
243 }
244
245 void step_message(t_x11 *x11,t_manager *man)
246 {
247   XEvent letter;
248
249   letter.type=ClientMessage;
250   letter.xclient.display=x11->disp;
251   letter.xclient.window=man->wd.self;
252   letter.xclient.message_type=0;
253   letter.xclient.format=32;
254   letter.xclient.data.l[0]=IDSTEP;
255   letter.xclient.data.l[1]=Button1;
256   XSendEvent(x11->disp,letter.xclient.window,True,0,&letter);
257 }
258
259 gmx_bool ReadMonfile(char *fn,int *nbars, int *bars)
260 {
261   FILE *fp;
262   if ((fp = fopen(fn,"r"))==NULL) 
263     return(FALSE);
264   else {
265     for((*nbars)=0; fscanf(fp,"%d",&bars[*nbars])>0; (*nbars)++)
266       ;
267     fclose(fp);
268     return (TRUE);
269   }
270 }
271
272 static void reset_mols(t_block *mols,matrix box,rvec x[])
273 {
274   int  i,m0,m1,j,m;
275   rvec xcm,icm;
276   real ix,iy,iz;
277   
278   for(i=0; (i<mols->nr); i++) {
279     m0=mols->index[i];
280     m1=mols->index[i+1];
281     
282     clear_rvec(xcm);
283     clear_rvec(icm);
284     
285     for(j=m0; (j<m1); j++) {
286       rvec_inc(xcm,x[j]);
287     }
288     for(m=0; (m<DIM); m++)
289       xcm[m]/=(m1-m0);
290     for(m=0; (m<DIM); m++) {
291       if (xcm[m] < 0) 
292         icm[m]=box[m][m];
293       else if (xcm[m] >= box[m][m]) 
294         icm[m]=-box[m][m];
295     }
296     ix=icm[XX],iy=icm[YY],iz=icm[ZZ];
297     
298     if ((ix != 0) || (iy != 0) || (iz != 0)) {
299       for(j=m0; (j<m1); j++) {
300         x[j][XX]+=ix;
301         x[j][YY]+=iy;
302         x[j][ZZ]+=iz;
303       }
304     }
305   }
306 }
307
308 static gmx_bool step_man(t_manager *man,int *nat)
309 {
310   static int  ncount=0;
311   static gmx_bool bWarn = FALSE;
312   gmx_bool        bEof;
313   int         dum;
314   const char *warn;
315
316   if (!man->natom) {
317     fprintf(stderr,"Not initiated yet!");
318     exit(1);
319   }
320   bEof=read_next_x(man->oenv,man->status,&man->time,man->natom,man->x,man->box);
321   *nat=man->natom;
322   if (ncount == man->nSkip) {
323     switch (man->molw->boxtype) {
324     case esbTri:
325       put_atoms_in_triclinic_unitcell(ecenterDEF,man->box,man->natom,man->x);
326       break;
327     case esbTrunc:
328       warn = put_atoms_in_compact_unitcell(man->molw->ePBC,ecenterDEF,man->box,
329                                            man->natom,man->x);
330       if (warn && !bWarn) {
331         fprintf(stderr,"\n%s\n",warn);
332         bWarn = TRUE;
333       }
334       break;
335     case esbRect:
336     case esbNone:
337     default:
338       break;
339     }
340     if (man->bPbc) {
341       gmx_rmpbc(man->gpbc,man->natom,man->box,man->x);
342       reset_mols(&(man->top.mols),man->box,man->x);
343     }
344     ncount=0;
345   }
346   else {
347     if (man->nSkip > 0) {
348       ncount++;
349       return step_man(man,nat);
350     }
351   }
352
353   return bEof;
354 }
355
356 static void HandleClient(t_x11 *x11,t_manager *man,long data[])
357 {
358   int  ID,button,x,y;
359   gmx_bool bPos;
360   real fac;
361
362   ID=data[0];
363   button=data[1];
364   x=data[2];
365   y=data[3];
366   bPos=(button==Button1);
367   switch (ID) {
368   case IDROTX:
369   case IDROTY:
370   case IDROTZ:
371     rotate_3d(man->view,ID-IDROTX,bPos);
372     draw_mol(x11,man);
373     break;
374   case IDZOOM:
375     if (bPos)
376       fac=0.8; /* Reduce distance between eye and origin */
377     else
378       fac=1.25;
379     
380     /*  zoom changed to scale by Berk Hess 3-7-96
381     if (zoom_3d(man->view,fac))
382       draw_mol(x11,man); */
383     man->view->sc_x/=fac;
384     man->view->sc_y/=fac;
385     draw_mol(x11,man);
386     break;
387   case IDTRANSX:
388   case IDTRANSY:
389   case IDTRANSZ:
390     translate_view(man->view,ID-IDTRANSX,bPos);
391     draw_mol(x11,man);
392     break;
393   case IDREWIND:
394     if (man->status) {
395       rewind_trj(man->status);
396       read_next_x(man->oenv,man->status,&(man->time),man->natom,man->x,
397                   man->box);
398       man->bEof=FALSE;
399       draw_mol(x11,man);
400     }
401     break;
402   case IDSTEP: {
403     int      nat;
404
405     nat=0;
406     if (!step_man(man,&nat)) {
407       man->bEof=TRUE;
408       man->bStop=TRUE;
409     }
410     else {
411       if (nat > 0) {
412         draw_mol(x11,man);
413         usleep(man->nWait*1000);
414       }
415     }
416     break;
417   }
418   case IDFF:
419     man->bStop=FALSE;
420     break;
421   case IDSTOP_ANI:
422     man->bStop=TRUE;
423     break;
424   case IDDRAWMOL:
425     draw_mol(x11,man);
426     break;
427   case IDLABEL:
428     switch (button) {
429     case Button1:
430     case Button2:
431       show_label(x11,man,x,y);
432       break;
433     case Button3:
434       hide_label(x11,man,x,y);
435       break;
436     }
437     break;
438   default:
439     break;
440   }
441   if (man->bAnimate && !man->bEof && !man->bStop)
442     step_message(x11,man);
443 }
444
445 static gmx_bool TitleCallBack(t_x11 *x11,XEvent *event, Window w, void *data)
446 {
447   t_windata *wd;
448
449   wd=(t_windata *)data;
450   switch (event->type) {
451   case Expose:
452     if (wd->text && (wd->width > 10)) {
453       XSetForeground(x11->disp,x11->gc,WHITE);
454       TextInWin(x11,wd,wd->text,eXCenter,eYCenter);
455       XDrawLine(x11->disp,wd->self,x11->gc,0,wd->height,
456                 wd->width,wd->height);
457     }
458     break;
459   case ConfigureNotify:
460     wd->width=event->xconfigure.width;
461     wd->height=event->xconfigure.height;
462     break;
463   }
464   return FALSE;
465 }
466
467 static gmx_bool ManCallBack(t_x11 *x11,XEvent *event, Window w, void *data)
468 {
469   t_manager *man;
470   int       width,height;
471
472   man=(t_manager *)data;
473   switch(event->type) {
474   case ConfigureNotify:
475     width=event->xconfigure.width;
476     height=event->xconfigure.height;
477     if ((width!=man->wd.width) || (height!=man->wd.height))
478       move_man(x11,man,width,height);
479     break;
480   case ClientMessage:
481     HandleClient(x11,man,event->xclient.data.l);
482     break;
483   default:
484     break;
485   }
486   return FALSE;
487 }
488
489 void no_labels(t_x11 *x11,t_manager *man)
490 {
491   int i;
492
493   for(i=0; (i<man->natom); i++)
494     man->bLabel[i]=FALSE;
495   draw_mol(x11,man);
496 }
497
498 void move_man(t_x11 *x11,t_manager *man,int width,int height)
499 {
500   int x0,y0,mw,mh,hb;
501   int th;
502   
503 #ifdef DEBUG
504   fprintf(stderr,"Move manager %dx%d\n",width,height);
505 #endif
506   man->wd.width=width;
507   man->wd.height=height;
508
509   /* Move all subwindows, resize only Mol window */
510   x0=width-EWIDTH-AIR-4*BORDER;               /* Starting of ewin etc. */
511   y0=AIR;
512   
513   /* Mol Window */
514   mw=x0-2*AIR-4*BORDER;
515   mh=height-y0-AIR-2*BORDER;
516   XMoveResizeWindow(x11->disp,man->molw->wd.self,AIR,y0,mw,mh);
517
518   /* Title Window */
519   th=XTextHeight(x11->font);
520   XMoveResizeWindow(x11->disp,man->title.self,0,0,mw,th+AIR);
521   
522   /* Legend Window */
523   XMoveResizeWindow(x11->disp,man->legw->wd.self,x0,y0,EWIDTH,LEGHEIGHT);
524   y0+=LEGHEIGHT+AIR+2*BORDER;
525
526   if (y0 > height) 
527     printf("Error: Windows falling out of main window!\n");
528
529   /* Button Box */
530   hb=height-y0-AIR-2*BORDER;
531   XMoveResizeWindow(x11->disp,man->bbox->wd.self,x0,y0,EWIDTH,hb);
532   
533   /* Video Box */
534   x0=(mw-man->vbox->wd.width)/2;
535   y0=(mh-2-AIR-man->vbox->wd.height);
536   XMoveWindow(x11->disp,man->vbox->wd.self,x0,y0);
537 }
538
539 void map_man(t_x11 *x11,t_manager *man)
540 {
541   XMapWindow(x11->disp,man->wd.self);
542   map_mw(x11,man->molw);
543   XMapWindow(x11->disp,man->title.self);
544   map_legw(x11,man->legw);
545   show_but(x11,man->bbox);
546 }
547
548 gmx_bool toggle_animate (t_x11 *x11,t_manager *man)
549
550   if (man->status) {
551     man->bAnimate=!man->bAnimate;
552     man->bStop=TRUE;
553     man->bEof=FALSE;
554     if (man->bAnimate)
555       show_but(x11,man->vbox);
556     else
557       hide_but(x11,man->vbox);
558   }
559   return man->bAnimate;
560 }
561
562 gmx_bool toggle_pbc (t_manager *man)
563 {
564   man->bPbc=!man->bPbc;
565   
566   return man->bPbc;
567 }
568
569
570 t_manager *init_man(t_x11 *x11,Window Parent,
571                     int x,int y,int width,int height,
572                     unsigned long fg,unsigned long bg,
573                     int ePBC,matrix box,
574                     const output_env_t oenv)
575 {
576   t_manager *man;
577
578   snew(man,1);
579   man->status=NULL;
580   man->bPlus=TRUE;
581   man->bSort=TRUE;
582   man->oenv=oenv;
583   InitWin(&(man->wd),x,y,width,height,0,"Manager");
584   man->wd.self=XCreateSimpleWindow(x11->disp,Parent,man->wd.x, man->wd.y, 
585                                    man->wd.width,man->wd.height,
586                                    man->wd.bwidth,fg,bg);
587   x11->RegisterCallback(x11,man->wd.self,Parent,ManCallBack,man);
588   x11->SetInputMask(x11,man->wd.self,StructureNotifyMask | 
589                     ExposureMask | ButtonPressMask);
590
591   /* The order of creating windows is important for the stacking order */
592   /* Mol Window */
593   man->molw=init_mw(x11,man->wd.self,0,0,1,1,WHITE,BLUE,ePBC,box);
594
595   /* Title Window */
596   InitWin(&(man->title),0,0,1,1,0,NULL);
597   man->title.self=XCreateSimpleWindow(x11->disp,man->molw->wd.self,
598                                       man->title.x,man->title.y,
599                                       man->title.width,man->title.height,
600                                       man->title.bwidth,WHITE,BLUE);
601   x11->RegisterCallback(x11,man->title.self,man->molw->wd.self,
602                         TitleCallBack,&(man->title));
603   x11->SetInputMask(x11,man->title.self,ExposureMask | StructureNotifyMask);
604   
605   /* Button box */
606   man->bbox=init_bbox(x11,man->wd.self,man->wd.self,1,WHITE,BLUE);
607   
608   /* Legend Window */
609   man->legw=init_legw(x11,man->wd.self,0,0,EWIDTH,LEGHEIGHT,WHITE,BLUE);
610
611   /* Video Box */
612   man->vbox=init_vbox(x11,man->molw->wd.self,man->wd.self,WHITE,BLUE);
613   
614   return man;
615 }
616
617 void done_man(t_x11 *x11,t_manager *man)
618 {
619   done_bbox(x11,man->vbox);
620   done_bbox(x11,man->bbox);
621   done_mw(x11,man->molw);
622   done_legw(x11,man->legw);
623   x11->UnRegisterCallback(x11,man->title.self);
624   x11->UnRegisterCallback(x11,man->wd.self);
625   sfree(man->x);
626   sfree(man->obj);
627   sfree(man->bHydro);
628   sfree(man->bLabel);
629   sfree(man->szLab);
630   sfree(man->col);
631   sfree(man);
632 }
633
634 void do_filter(t_x11 *x11,t_manager *man,t_filter *filter)
635 {
636   int      i;
637   atom_id  j;
638
639   for(i=0; (i<man->natom); i++)
640     man->bVis[i]=FALSE;
641   for(i=0; (i<filter->grps->nr); i++) {
642     if (filter->bShow[i])
643       for(j=filter->grps->index[i]; (j<filter->grps->index[i+1]); j++)
644         man->bVis[filter->grps->a[j]]=TRUE;
645   }
646
647   ExposeWin(x11->disp,man->wd.self);
648 }