Tagged files with gromacs 3.0 header and added some license info
[alexxy/gromacs.git] / src / ngmx / manager.c
1 /*
2  * $Id$
3  * 
4  *                This source code is part of
5  * 
6  *                 G   R   O   M   A   C   S
7  * 
8  *          GROningen MAchine for Chemical Simulations
9  * 
10  *                        VERSION 3.0
11  * 
12  * Copyright (c) 1991-2001
13  * BIOSON Research Institute, Dept. of Biophysical Chemistry
14  * University of Groningen, The Netherlands
15  * 
16  * This program is free software; you can redistribute it and/or
17  * modify it under the terms of the GNU General Public License
18  * as published by the Free Software Foundation; either version 2
19  * of the License, or (at your option) any later version.
20  * 
21  * If you want to redistribute modifications, please consider that
22  * scientific software is very special. Version control is crucial -
23  * bugs must be traceable. We will be happy to consider code for
24  * inclusion in the official distribution, but derived work must not
25  * be called official GROMACS. Details are found in the README & COPYING
26  * files - if they are missing, get the official version at www.gromacs.org.
27  * 
28  * To help us fund GROMACS development, we humbly ask that you cite
29  * the papers on the package - you can find them in the top README file.
30  * 
31  * Do check out http://www.gromacs.org , or mail us at gromacs@gromacs.org .
32  * 
33  * And Hey:
34  * Giving Russians Opium May Alter Current Situation
35  */
36 static char *SRCID_manager_c = "$Id$";
37 #include <sysstuff.h>
38 #include <string.h>
39 #include <smalloc.h>
40 #include <ctype.h>
41 #include <typedefs.h>
42 #include <smalloc.h>
43 #include <tpxio.h>
44 #include <macros.h>
45 #include <maths.h>
46 #include <atomprop.h>
47 #include <names.h>
48 #include "manager.h"
49 #include "futil.h"
50 #include "pbc.h"
51 #include "nmol.h"
52 #include "copyrite.h"
53 #include "gstat.h"
54 #include "vec.h"
55 #include "statutil.h"
56 #include "string2.h"
57
58 static void add_object(t_manager *man,eObject eO,atom_id ai,atom_id aj)
59 {
60   srenew(man->obj,++man->nobj);
61   man->obj[man->nobj-1].eO    = eO;
62   man->obj[man->nobj-1].eV    = eVNormal;
63   man->obj[man->nobj-1].color = WHITE;
64   man->obj[man->nobj-1].ai    = ai;
65   man->obj[man->nobj-1].aj    = aj;
66   man->obj[man->nobj-1].z     = 0.0;
67 }
68
69 static void add_bonds(t_manager *man,t_functype func[],
70                       t_ilist *b,bool bB[])
71 {
72   bool    *bH=man->bHydro;
73   t_iatom *ia;
74   t_iatom type,ai,aj,ak;
75   int     i,delta,ftype;
76   
77 #ifdef DEBUG
78   fprintf(stderr,"Going to make bonds from an ilist with %d entries\n",b->nr);
79 #endif
80   ia=b->iatoms;
81   for(i=0; (i<b->nr); ) {
82     type  = ia[0];
83     ai    = ia[1];
84     ftype = func[type];
85     delta = interaction_function[ftype].nratoms;
86     
87     if (ftype == F_SETTLE) {
88       aj=ai+1;
89       ak=ai+2;
90       bB[ai]=bB[aj]=bB[ak]=TRUE;
91       add_object(man,eOHBond,ai,aj);
92       add_object(man,eOHBond,ai,ak);
93     }
94     else if ( interaction_function[ftype].flags & IF_CONNECT ) {
95       aj=ia[2];
96 #ifdef DEBUG
97       fprintf(stderr,"Adding bond from %d to %d\n",ai,aj);
98 #endif
99       bB[ai]=bB[aj]=TRUE;
100       if (!(bH[ai] == bH[aj])) 
101         add_object(man,eOHBond,ai,aj);
102       else if (!bH[ai] && !bH[aj]) 
103         add_object(man,eOBond,ai,aj);
104     }
105 #ifdef DEBUG
106     fprintf(stderr,"Type: %5d, delta: %5d\n",type,delta);
107 #endif
108     ia += delta+1;
109     i  += delta+1;
110   }
111 }
112
113 static void add_bpl(t_manager *man,t_idef *idef,bool bB[])
114 {
115   add_bonds(man,idef->functype,&idef->il[F_BONDS],bB);
116   add_bonds(man,idef->functype,&idef->il[F_G96BONDS],bB);
117   add_bonds(man,idef->functype,&idef->il[F_MORSE],bB);
118   add_bonds(man,idef->functype,&idef->il[F_CUBICBONDS],bB);
119   add_bonds(man,idef->functype,&idef->il[F_CONNBONDS],bB);
120   add_bonds(man,idef->functype,&idef->il[F_SHAKE],bB);
121   add_bonds(man,idef->functype,&idef->il[F_SETTLE],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,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,char *trajectory,char *status)
175 {
176   char         buf[256];
177   t_tpxheader  sh;
178   t_atoms      *at;
179   bool         *bB;
180   int          i,idum;
181   real         rdum;
182
183   read_tpxheader(status,&sh);
184   snew(man->ix,sh.natoms);
185   snew(man->zz,sh.natoms);
186   snew(man->col,sh.natoms);
187   snew(man->size,sh.natoms);
188   snew(man->vdw,sh.natoms);
189   snew(man->bLabel,sh.natoms);
190   snew(man->bVis,sh.natoms);
191   for(i=0; (i<sh.natoms); i++)
192     man->bVis[i]=FALSE;
193
194   man->bPbc=FALSE;
195
196   snew(man->szLab,sh.natoms);
197   snew(man->bHydro,sh.natoms);
198   snew(bB,sh.natoms);
199   read_tpx(status,&(man->step),&(man->time),&rdum,NULL,man->box,
200            &man->natom,NULL,NULL,NULL,&man->top);
201   
202   man->natom=
203     read_first_x(&man->status,trajectory,&(man->time),&(man->x),man->box);
204   man->trajfile=strdup(trajectory);
205   if (man->natom > man->top.atoms.nr)
206     fatal_error(0,"Topology %s (%d atoms) and trajectory %s (%d atoms) "
207                 "do not match",status,man->top.atoms.nr,
208                 trajectory,man->natom);
209   
210   sprintf(buf,"%s: %s",*man->top.name,cool_quote());
211   man->title.text = strdup(buf);
212   man->view       = init_view(man->box);
213   at=&(man->top.atoms);
214   for(i=0; (i<man->natom); i++) {
215     char *aname=*(at->atomname[i]);
216     int  resnr=at->atom[i].resnr;
217
218     man->col[i]=Type2Color(aname);
219     snew(man->szLab[i],20);
220     sprintf(man->szLab[i],"%s%d, %s",*(at->resname[resnr]),resnr+1,aname);
221     man->bHydro[i]=(toupper(aname[0])=='H');
222     if ( man->bHydro[i] )
223       man->vdw[i]=0;
224     else
225       man->vdw[i]=get_vdw(*(at->resname[resnr]),aname,0);
226   }
227   add_bpl(man,&(man->top.idef),bB);
228   for(i=0; (i<man->natom); i++)
229     if (!bB[i]) 
230       add_object(man,eOSingle,(atom_id) i,0);
231   sfree(bB);
232
233   ExposeWin(x11->disp,man->molw->wd.self);
234 }
235
236 void step_message(t_x11 *x11,t_manager *man)
237 {
238   XEvent letter;
239
240   letter.type=ClientMessage;
241   letter.xclient.display=x11->disp;
242   letter.xclient.window=man->wd.self;
243   letter.xclient.message_type=0;
244   letter.xclient.format=32;
245   letter.xclient.data.l[0]=IDSTEP;
246   letter.xclient.data.l[1]=Button1;
247   XSendEvent(x11->disp,letter.xclient.window,True,0,&letter);
248 }
249
250 bool ReadMonfile(char *fn,int *nbars, int *bars)
251 {
252   FILE *fp;
253   if ((fp = fopen(fn,"r"))==NULL) 
254     return(FALSE);
255   else {
256     for((*nbars)=0; fscanf(fp,"%d",&bars[*nbars])>0; (*nbars)++)
257       ;
258     fclose(fp);
259     return (TRUE);
260   }
261 }
262
263 static void reset_mols(t_block *mols,matrix box,rvec x[])
264 {
265   int  i,aj,m0,m1,j,m;
266   rvec xcm,icm;
267   real ix,iy,iz;
268   
269   for(i=0; (i<mols->nr); i++) {
270     m0=mols->index[i];
271     m1=mols->index[i+1];
272     
273     clear_rvec(xcm);
274     clear_rvec(icm);
275     
276     for(j=m0; (j<m1); j++) {
277       aj=mols->a[j];
278       rvec_inc(xcm,x[aj]);
279     }
280     for(m=0; (m<DIM); m++)
281       xcm[m]/=(m1-m0);
282     for(m=0; (m<DIM); m++) {
283       if (xcm[m] < 0) 
284         icm[m]=box[m][m];
285       else if (xcm[m] >= box[m][m]) 
286         icm[m]=-box[m][m];
287     }
288     ix=icm[XX],iy=icm[YY],iz=icm[ZZ];
289     
290     if ((ix != 0) || (iy != 0) || (iz != 0)) {
291       for(j=m0; (j<m1); j++) {
292         aj=mols->a[j];
293         x[aj][XX]+=ix;
294         x[aj][YY]+=iy;
295         x[aj][ZZ]+=iz;
296       }
297     }
298   }
299 }
300
301 static bool step_man(t_manager *man,int *nat)
302 {
303   static int  ncount=0;
304   bool        bEof;
305   real        rdum;
306   int         dum;
307
308   if (!man->natom) {
309     fprintf(stderr,"Not initiated yet!");
310     exit(1);
311   }
312   bEof=read_next_x(man->status,&man->time,man->natom,man->x,man->box);
313   *nat=man->natom;
314   if (ncount == man->nSkip) {
315     switch (man->molw->boxtype) {
316     case esbTri:
317       put_atoms_in_triclinic_unitcell(man->box,man->natom,man->x);
318       break;
319     case esbTrunc:
320       put_atoms_in_compact_unitcell(man->box,man->natom,man->x);
321       break;
322     case esbRect:
323     case esbNone:
324     default:
325       break;
326     }
327     if (man->bPbc) {
328       rm_pbc(&(man->top.idef),man->natom,man->box,man->x,man->x);
329       reset_mols(&(man->top.blocks[ebMOLS]),man->box,man->x);
330     }
331     ncount=0;
332   }
333   else {
334     if (man->nSkip > 0) {
335       ncount++;
336       return step_man(man,nat);
337     }
338   }
339
340   return bEof;
341 }
342
343 static void HandleClient(t_x11 *x11,t_manager *man,long data[])
344 {
345   int  ID,button,x,y;
346   bool bPos;
347   real fac;
348
349   ID=data[0];
350   button=data[1];
351   x=data[2];
352   y=data[3];
353   bPos=(button==Button1);
354   switch (ID) {
355   case IDROTX:
356   case IDROTY:
357   case IDROTZ:
358     rotate_3d(man->view,ID-IDROTX,bPos);
359     draw_mol(x11,man);
360     break;
361   case IDZOOM:
362     if (bPos)
363       fac=0.8; /* Reduce distance between eye and origin */
364     else
365       fac=1.25;
366     
367     /*  zoom changed to scale by Berk Hess 3-7-96
368     if (zoom_3d(man->view,fac))
369       draw_mol(x11,man); */
370     man->view->sc_x/=fac;
371     man->view->sc_y/=fac;
372     draw_mol(x11,man);
373     break;
374   case IDTRANSX:
375   case IDTRANSY:
376   case IDTRANSZ:
377     translate_view(man->view,ID-IDTRANSX,bPos);
378     draw_mol(x11,man);
379     break;
380   case IDREWIND:
381     if (man->status != -1) {
382       rewind_trj(man->status);
383       read_next_x(man->status,&(man->time),man->natom,man->x,man->box);
384       man->bEof=FALSE;
385       draw_mol(x11,man);
386     }
387     break;
388   case IDSTEP: {
389     int      nat;
390
391     nat=0;
392     if (!step_man(man,&nat)) {
393       man->bEof=TRUE;
394       man->bStop=TRUE;
395     }
396     else {
397       if (nat > 0) {
398         draw_mol(x11,man);
399         usleep(man->nWait*1000);
400       }
401     }
402     break;
403   }
404   case IDFF:
405     man->bStop=FALSE;
406     break;
407   case IDSTOP_ANI:
408     man->bStop=TRUE;
409     break;
410   case IDDRAWMOL:
411     draw_mol(x11,man);
412     break;
413   case IDLABEL:
414     switch (button) {
415     case Button1:
416     case Button2:
417       show_label(x11,man,x,y);
418       break;
419     case Button3:
420       hide_label(x11,man,x,y);
421       break;
422     }
423     break;
424   default:
425     break;
426   }
427   if (man->bAnimate && !man->bEof && !man->bStop)
428     step_message(x11,man);
429 }
430
431 static bool TitleCallBack(t_x11 *x11,XEvent *event, Window w, void *data)
432 {
433   t_windata *wd;
434
435   wd=(t_windata *)data;
436   switch (event->type) {
437   case Expose:
438     if (wd->text && (wd->width > 10)) {
439       XSetForeground(x11->disp,x11->gc,WHITE);
440       TextInWin(x11,wd,wd->text,eXCenter,eYCenter);
441       XDrawLine(x11->disp,wd->self,x11->gc,0,wd->height,
442                 wd->width,wd->height);
443     }
444     break;
445   case ConfigureNotify:
446     wd->width=event->xconfigure.width;
447     wd->height=event->xconfigure.height;
448     break;
449   }
450   return FALSE;
451 }
452
453 static bool ManCallBack(t_x11 *x11,XEvent *event, Window w, void *data)
454 {
455   t_manager *man;
456   int       width,height;
457
458   man=(t_manager *)data;
459   switch(event->type) {
460   case ConfigureNotify:
461     width=event->xconfigure.width;
462     height=event->xconfigure.height;
463     if ((width!=man->wd.width) || (height!=man->wd.height))
464       move_man(x11,man,width,height);
465     break;
466   case ClientMessage:
467     HandleClient(x11,man,event->xclient.data.l);
468     break;
469   default:
470     break;
471   }
472   return FALSE;
473 }
474
475 void no_labels(t_x11 *x11,t_manager *man)
476 {
477   int i;
478
479   for(i=0; (i<man->natom); i++)
480     man->bLabel[i]=FALSE;
481   draw_mol(x11,man);
482 }
483
484 void move_man(t_x11 *x11,t_manager *man,int width,int height)
485 {
486   int x0,y0,mw,mh,hb;
487   int th;
488   
489 #ifdef DEBUG
490   fprintf(stderr,"Move manager %dx%d\n",width,height);
491 #endif
492   man->wd.width=width;
493   man->wd.height=height;
494
495   /* Move all subwindows, resize only Mol window */
496   x0=width-EWIDTH-AIR-4*BORDER;               /* Starting of ewin etc. */
497   y0=AIR;
498   
499   /* Mol Window */
500   mw=x0-2*AIR-4*BORDER;
501   mh=height-y0-AIR-2*BORDER;
502   XMoveResizeWindow(x11->disp,man->molw->wd.self,AIR,y0,mw,mh);
503
504   /* Title Window */
505   th=XTextHeight(x11->font);
506   XMoveResizeWindow(x11->disp,man->title.self,0,0,mw,th+AIR);
507   
508   /* Legend Window */
509   XMoveResizeWindow(x11->disp,man->legw->wd.self,x0,y0,EWIDTH,LEGHEIGHT);
510   y0+=LEGHEIGHT+AIR+2*BORDER;
511
512   if (y0 > height) 
513     printf("Error: Windows falling out of main window!\n");
514
515   /* Button Box */
516   hb=height-y0-AIR-2*BORDER;
517   XMoveResizeWindow(x11->disp,man->bbox->wd.self,x0,y0,EWIDTH,hb);
518   
519   /* Video Box */
520   x0=(mw-man->vbox->wd.width)/2;
521   y0=(mh-2-AIR-man->vbox->wd.height);
522   XMoveWindow(x11->disp,man->vbox->wd.self,x0,y0);
523 }
524
525 void map_man(t_x11 *x11,t_manager *man)
526 {
527   XMapWindow(x11->disp,man->wd.self);
528   map_mw(x11,man->molw);
529   XMapWindow(x11->disp,man->title.self);
530   map_legw(x11,man->legw);
531   show_but(x11,man->bbox);
532 }
533
534 bool toggle_animate (t_x11 *x11,t_manager *man)
535
536   if (man->status != -1) {
537     man->bAnimate=!man->bAnimate;
538     man->bStop=TRUE;
539     man->bEof=FALSE;
540     if (man->bAnimate)
541       show_but(x11,man->vbox);
542     else
543       hide_but(x11,man->vbox);
544   }
545   return man->bAnimate;
546 }
547
548 bool toggle_pbc (t_manager *man)
549 {
550   man->bPbc=!man->bPbc;
551   
552   return man->bPbc;
553 }
554
555
556 t_manager *init_man(t_x11 *x11,Window Parent,
557                     int x,int y,int width,int height,
558                     unsigned long fg,unsigned long bg,
559                     matrix box)
560 {
561   t_manager *man;
562
563   snew(man,1);
564   man->status=-1;
565   man->bPlus=TRUE;
566   man->bSort=TRUE;
567   InitWin(&(man->wd),x,y,width,height,0,"Manager");
568   man->wd.self=XCreateSimpleWindow(x11->disp,Parent,man->wd.x, man->wd.y, 
569                                    man->wd.width,man->wd.height,
570                                    man->wd.bwidth,fg,bg);
571   x11->RegisterCallback(x11,man->wd.self,Parent,ManCallBack,man);
572   x11->SetInputMask(x11,man->wd.self,StructureNotifyMask | 
573                     ExposureMask | ButtonPressMask);
574
575   /* The order of creating windows is important for the stacking order */
576   /* Mol Window */
577   man->molw=init_mw(x11,man->wd.self,0,0,1,1,WHITE,BLUE,box);
578
579   /* Title Window */
580   InitWin(&(man->title),0,0,1,1,0,NULL);
581   man->title.self=XCreateSimpleWindow(x11->disp,man->molw->wd.self,
582                                       man->title.x,man->title.y,
583                                       man->title.width,man->title.height,
584                                       man->title.bwidth,WHITE,BLUE);
585   x11->RegisterCallback(x11,man->title.self,man->molw->wd.self,
586                         TitleCallBack,&(man->title));
587   x11->SetInputMask(x11,man->title.self,ExposureMask | StructureNotifyMask);
588   
589   /* Button box */
590   man->bbox=init_bbox(x11,man->wd.self,man->wd.self,1,WHITE,BLUE);
591   
592   /* Legend Window */
593   man->legw=init_legw(x11,man->wd.self,0,0,EWIDTH,LEGHEIGHT,WHITE,BLUE);
594
595   /* Video Box */
596   man->vbox=init_vbox(x11,man->molw->wd.self,man->wd.self,WHITE,BLUE);
597   
598   return man;
599 }
600
601 void done_man(t_x11 *x11,t_manager *man)
602 {
603   done_bbox(x11,man->vbox);
604   done_bbox(x11,man->bbox);
605   done_mw(x11,man->molw);
606   done_legw(x11,man->legw);
607   x11->UnRegisterCallback(x11,man->title.self);
608   x11->UnRegisterCallback(x11,man->wd.self);
609   sfree(man->x);
610   sfree(man->obj);
611   sfree(man->bHydro);
612   sfree(man->bLabel);
613   sfree(man->szLab);
614   sfree(man->col);
615   sfree(man);
616 }
617
618 void do_filter(t_x11 *x11,t_manager *man,t_filter *filter)
619 {
620   int      i;
621   atom_id  j;
622
623   for(i=0; (i<man->natom); i++)
624     man->bVis[i]=FALSE;
625   for(i=0; (i<filter->grps->nr); i++) {
626     if (filter->bShow[i])
627       for(j=filter->grps->index[i]; (j<filter->grps->index[i+1]); j++)
628         man->bVis[filter->grps->a[j]]=TRUE;
629   }
630
631   ExposeWin(x11->disp,man->wd.self);
632 }