2 * This file is part of the GROMACS molecular simulation package.
4 * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
5 * Copyright (c) 2001-2004, The GROMACS development team.
6 * Copyright (c) 2013,2014,2015, by the GROMACS development team, led by
7 * Mark Abraham, David van der Spoel, Berk Hess, and Erik Lindahl,
8 * and including many others, as listed in the AUTHORS file in the
9 * top-level source directory and at http://www.gromacs.org.
11 * GROMACS is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU Lesser General Public License
13 * as published by the Free Software Foundation; either version 2.1
14 * of the License, or (at your option) any later version.
16 * GROMACS is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 * Lesser General Public License for more details.
21 * You should have received a copy of the GNU Lesser General Public
22 * License along with GROMACS; if not, see
23 * http://www.gnu.org/licenses, or write to the Free Software Foundation,
24 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
26 * If you want to redistribute modifications to GROMACS, please
27 * consider that scientific software is very special. Version
28 * control is crucial - bugs must be traceable. We will be happy to
29 * consider code for inclusion in the official distribution, but
30 * derived work must not be called official GROMACS. Details are found
31 * in the README & COPYING files - if they are missing, get the
32 * official version at http://www.gromacs.org.
34 * To help us fund GROMACS development, we humbly ask that you cite
35 * the research papers on the package. Check out http://www.gromacs.org.
49 #include <unistd.h> // for usleep()
52 #include "gromacs/fileio/tpxio.h"
53 #include "gromacs/legacyheaders/copyrite.h"
54 #include "gromacs/legacyheaders/names.h"
55 #include "gromacs/legacyheaders/typedefs.h"
56 #include "gromacs/legacyheaders/types/ifunc.h"
57 #include "gromacs/math/utilities.h"
58 #include "gromacs/math/vec.h"
59 #include "gromacs/pbcutil/pbc.h"
60 #include "gromacs/topology/atomprop.h"
61 #include "gromacs/utility/cstringutil.h"
62 #include "gromacs/utility/fatalerror.h"
63 #include "gromacs/utility/futil.h"
64 #include "gromacs/utility/smalloc.h"
69 static void add_object(t_manager
*man
, eObject eO
, atom_id ai
, atom_id aj
)
71 srenew(man
->obj
, ++man
->nobj
);
72 man
->obj
[man
->nobj
-1].eO
= eO
;
73 man
->obj
[man
->nobj
-1].eV
= eVNormal
;
74 man
->obj
[man
->nobj
-1].color
= WHITE
;
75 man
->obj
[man
->nobj
-1].ai
= ai
;
76 man
->obj
[man
->nobj
-1].aj
= aj
;
77 man
->obj
[man
->nobj
-1].z
= 0.0;
80 static void add_bonds(t_manager
*man
, t_functype func
[],
81 t_ilist
*b
, bool bB
[])
83 bool *bH
= man
->bHydro
;
85 t_iatom type
, ai
, aj
, ak
;
89 std::fprintf(stderr
, "Going to make bonds from an ilist with %d entries\n", b
->nr
);
92 for (i
= 0; (i
< b
->nr
); )
97 delta
= interaction_function
[ftype
].nratoms
;
99 if (ftype
== F_SETTLE
)
103 bB
[ai
] = bB
[aj
] = bB
[ak
] = true;
104 add_object(man
, eOHBond
, ai
, aj
);
105 add_object(man
, eOHBond
, ai
, ak
);
107 else if (IS_CHEMBOND(ftype
))
111 std::fprintf(stderr
, "Adding bond from %d to %d\n", ai
, aj
);
113 bB
[ai
] = bB
[aj
] = true;
114 if (!(bH
[ai
] == bH
[aj
]))
116 add_object(man
, eOHBond
, ai
, aj
);
118 else if (!bH
[ai
] && !bH
[aj
])
120 add_object(man
, eOBond
, ai
, aj
);
124 std::fprintf(stderr
, "Type: %5d, delta: %5d\n", type
, delta
);
131 static void add_bpl(t_manager
*man
, t_idef
*idef
, bool bB
[])
135 for (ftype
= 0; ftype
< F_NRE
; ftype
++)
137 if (IS_CHEMBOND(ftype
) || ftype
== F_SETTLE
)
139 add_bonds(man
, idef
->functype
, &idef
->il
[ftype
], bB
);
144 static atom_id
which_atom(t_manager
*man
, int x
, int y
)
150 for (i
= 0; (i
< man
->natom
); i
++)
152 if ((std::abs(ix
[i
][XX
]-x
) < DELTA
) && (std::abs(ix
[i
][YY
]-y
) < DELTA
))
163 static void do_label(t_x11
*x11
, t_manager
*man
, int x
, int y
, bool bSet
)
168 if ((ai
= which_atom(man
, x
, y
)) != NO_ATID
)
172 if (bSet
&& !man
->bLabel
[ai
])
175 man
->bLabel
[ai
] = true;
177 else if (!bSet
&& man
->bLabel
[ai
])
180 man
->bLabel
[ai
] = false;
186 XSetForeground(x11
->disp
, x11
->gc
, col
);
187 XDrawString(x11
->disp
, man
->molw
->wd
.self
, x11
->gc
, x
+2, y
-2, man
->szLab
[ai
],
188 std::strlen(man
->szLab
[ai
]));
189 XSetForeground(x11
->disp
, x11
->gc
, x11
->fg
);
193 static void show_label(t_x11
*x11
, t_manager
*man
, int x
, int y
)
195 do_label(x11
, man
, x
, y
, true);
198 static void hide_label(t_x11
*x11
, t_manager
*man
, int x
, int y
)
200 do_label(x11
, man
, x
, y
, false);
203 void set_file(t_x11
*x11
, t_manager
*man
, const char *trajectory
,
207 char buf
[256], quote
[256];
213 read_tpxheader(status
, &sh
, true, NULL
, NULL
);
214 snew(man
->ix
, sh
.natoms
);
215 snew(man
->zz
, sh
.natoms
);
216 snew(man
->col
, sh
.natoms
);
217 snew(man
->size
, sh
.natoms
);
218 snew(man
->vdw
, sh
.natoms
);
219 snew(man
->bLabel
, sh
.natoms
);
220 snew(man
->bVis
, sh
.natoms
);
221 for (i
= 0; (i
< sh
.natoms
); i
++)
223 man
->bVis
[i
] = false;
228 snew(man
->szLab
, sh
.natoms
);
229 snew(man
->bHydro
, sh
.natoms
);
231 read_tpx_top(status
, NULL
, man
->box
, &man
->natom
, NULL
, NULL
, &man
->top
);
232 man
->gpbc
= gmx_rmpbc_init(&man
->top
.idef
, -1, man
->natom
);
235 read_first_x(man
->oenv
, &man
->status
, trajectory
, &(man
->time
), &(man
->x
),
237 man
->trajfile
= gmx_strdup(trajectory
);
238 if (man
->natom
> man
->top
.atoms
.nr
)
240 gmx_fatal(FARGS
, "Topology %s (%d atoms) and trajectory %s (%d atoms) "
241 "do not match", status
, man
->top
.atoms
.nr
,
242 trajectory
, man
->natom
);
245 cool_quote(quote
, 255, NULL
);
246 std::sprintf(buf
, "%s: %s", *man
->top
.name
, quote
);
247 man
->title
.text
= gmx_strdup(buf
);
248 man
->view
= init_view(man
->box
);
249 at
= &(man
->top
.atoms
);
250 aps
= gmx_atomprop_init();
251 for (i
= 0; (i
< man
->natom
); i
++)
253 char *aname
= *(at
->atomname
[i
]);
254 t_resinfo
*ri
= &at
->resinfo
[at
->atom
[i
].resind
];
256 man
->col
[i
] = Type2Color(aname
);
257 snew(man
->szLab
[i
], 20);
260 std::sprintf(man
->szLab
[i
], "%s%d%c, %s", *ri
->name
, ri
->nr
, ri
->ic
, aname
);
264 std::sprintf(man
->szLab
[i
], "%s%d, %s", *ri
->name
, ri
->nr
, aname
);
266 man
->bHydro
[i
] = (toupper(aname
[0]) == 'H');
271 else if (!gmx_atomprop_query(aps
, epropVDW
, *ri
->name
, aname
, &(man
->vdw
[i
])))
276 gmx_atomprop_destroy(aps
);
277 add_bpl(man
, &(man
->top
.idef
), bB
);
278 for (i
= 0; (i
< man
->natom
); i
++)
282 add_object(man
, eOSingle
, (atom_id
) i
, 0);
287 ExposeWin(x11
->disp
, man
->molw
->wd
.self
);
290 void step_message(t_x11
*x11
, t_manager
*man
)
294 letter
.type
= ClientMessage
;
295 letter
.xclient
.display
= x11
->disp
;
296 letter
.xclient
.window
= man
->wd
.self
;
297 letter
.xclient
.message_type
= 0;
298 letter
.xclient
.format
= 32;
299 letter
.xclient
.data
.l
[0] = IDSTEP
;
300 letter
.xclient
.data
.l
[1] = Button1
;
301 XSendEvent(x11
->disp
, letter
.xclient
.window
, True
, 0, &letter
);
304 static void reset_mols(t_block
*mols
, matrix box
, rvec x
[])
310 for (i
= 0; (i
< mols
->nr
); i
++)
313 m1
= mols
->index
[i
+1];
318 for (j
= m0
; (j
< m1
); j
++)
322 for (m
= 0; (m
< DIM
); m
++)
326 for (m
= 0; (m
< DIM
); m
++)
332 else if (xcm
[m
] >= box
[m
][m
])
337 ix
= icm
[XX
], iy
= icm
[YY
], iz
= icm
[ZZ
];
339 if ((ix
!= 0) || (iy
!= 0) || (iz
!= 0))
341 for (j
= m0
; (j
< m1
); j
++)
351 static bool step_man(t_manager
*man
, int *nat
)
353 static int ncount
= 0;
358 std::fprintf(stderr
, "Not initiated yet!");
361 bEof
= read_next_x(man
->oenv
, man
->status
, &man
->time
, man
->x
, man
->box
);
363 if (ncount
== man
->nSkip
)
365 switch (man
->molw
->boxtype
)
368 put_atoms_in_triclinic_unitcell(ecenterDEF
, man
->box
, man
->natom
, man
->x
);
371 put_atoms_in_compact_unitcell(man
->molw
->ePBC
, ecenterDEF
, man
->box
,
381 gmx_rmpbc(man
->gpbc
, man
->natom
, man
->box
, man
->x
);
382 reset_mols(&(man
->top
.mols
), man
->box
, man
->x
);
391 return step_man(man
, nat
);
398 static void HandleClient(t_x11
*x11
, t_manager
*man
, long data
[])
400 int ID
, button
, x
, y
;
408 bPos
= (button
== Button1
);
414 rotate_3d(man
->view
, ID
-IDROTX
, bPos
);
420 fac
= 0.8; /* Reduce distance between eye and origin */
427 /* zoom changed to scale by Berk Hess 3-7-96
428 if (zoom_3d(man->view,fac))
429 draw_mol(x11,man); */
430 man
->view
->sc_x
/= fac
;
431 man
->view
->sc_y
/= fac
;
437 translate_view(man
->view
, ID
-IDTRANSX
, bPos
);
443 rewind_trj(man
->status
);
444 read_next_x(man
->oenv
, man
->status
, &(man
->time
), man
->x
,
455 if (!step_man(man
, &nat
))
465 usleep(man
->nWait
*1000);
484 show_label(x11
, man
, x
, y
);
487 hide_label(x11
, man
, x
, y
);
494 if (man
->bAnimate
&& !man
->bEof
&& !man
->bStop
)
496 step_message(x11
, man
);
500 static bool TitleCallBack(t_x11
*x11
, XEvent
*event
, Window
/*w*/, void *data
)
504 wd
= (t_windata
*)data
;
508 if (wd
->text
&& (wd
->width
> 10))
510 XSetForeground(x11
->disp
, x11
->gc
, WHITE
);
511 TextInWin(x11
, wd
, wd
->text
, eXCenter
, eYCenter
);
512 XDrawLine(x11
->disp
, wd
->self
, x11
->gc
, 0, wd
->height
,
513 wd
->width
, wd
->height
);
516 case ConfigureNotify
:
517 wd
->width
= event
->xconfigure
.width
;
518 wd
->height
= event
->xconfigure
.height
;
524 static bool ManCallBack(t_x11
*x11
, XEvent
*event
, Window
/*w*/, void *data
)
529 man
= (t_manager
*)data
;
532 case ConfigureNotify
:
533 width
= event
->xconfigure
.width
;
534 height
= event
->xconfigure
.height
;
535 if ((width
!= man
->wd
.width
) || (height
!= man
->wd
.height
))
537 move_man(x11
, man
, width
, height
);
541 HandleClient(x11
, man
, event
->xclient
.data
.l
);
549 void no_labels(t_x11
*x11
, t_manager
*man
)
553 for (i
= 0; (i
< man
->natom
); i
++)
555 man
->bLabel
[i
] = false;
560 void move_man(t_x11
*x11
, t_manager
*man
, int width
, int height
)
562 int x0
, y0
, mw
, mh
, hb
;
566 std::fprintf(stderr
, "Move manager %dx%d\n", width
, height
);
568 man
->wd
.width
= width
;
569 man
->wd
.height
= height
;
571 /* Move all subwindows, resize only Mol window */
572 x0
= width
-EWIDTH
-AIR
-4*BORDER
; /* Starting of ewin etc. */
576 mw
= x0
-2*AIR
-4*BORDER
;
577 mh
= height
-y0
-AIR
-2*BORDER
;
578 XMoveResizeWindow(x11
->disp
, man
->molw
->wd
.self
, AIR
, y0
, mw
, mh
);
581 th
= XTextHeight(x11
->font
);
582 XMoveResizeWindow(x11
->disp
, man
->title
.self
, 0, 0, mw
, th
+AIR
);
585 XMoveResizeWindow(x11
->disp
, man
->legw
->wd
.self
, x0
, y0
, EWIDTH
, LEGHEIGHT
);
586 y0
+= LEGHEIGHT
+AIR
+2*BORDER
;
590 std::printf("Error: Windows falling out of main window!\n");
594 hb
= height
-y0
-AIR
-2*BORDER
;
595 XMoveResizeWindow(x11
->disp
, man
->bbox
->wd
.self
, x0
, y0
, EWIDTH
, hb
);
598 x0
= (mw
-man
->vbox
->wd
.width
)/2;
599 y0
= (mh
-2-AIR
-man
->vbox
->wd
.height
);
600 XMoveWindow(x11
->disp
, man
->vbox
->wd
.self
, x0
, y0
);
603 void map_man(t_x11
*x11
, t_manager
*man
)
605 XMapWindow(x11
->disp
, man
->wd
.self
);
606 map_mw(x11
, man
->molw
);
607 XMapWindow(x11
->disp
, man
->title
.self
);
608 map_legw(x11
, man
->legw
);
609 show_but(x11
, man
->bbox
);
612 bool toggle_animate (t_x11
*x11
, t_manager
*man
)
616 man
->bAnimate
= !man
->bAnimate
;
621 show_but(x11
, man
->vbox
);
625 hide_but(x11
, man
->vbox
);
628 return man
->bAnimate
;
631 bool toggle_pbc (t_manager
*man
)
633 man
->bPbc
= !man
->bPbc
;
639 t_manager
*init_man(t_x11
*x11
, Window Parent
,
640 int x
, int y
, int width
, int height
,
641 unsigned long fg
, unsigned long bg
,
642 int ePBC
, matrix box
,
643 const output_env_t oenv
)
652 InitWin(&(man
->wd
), x
, y
, width
, height
, 0, "Manager");
653 man
->wd
.self
= XCreateSimpleWindow(x11
->disp
, Parent
, man
->wd
.x
, man
->wd
.y
,
654 man
->wd
.width
, man
->wd
.height
,
655 man
->wd
.bwidth
, fg
, bg
);
656 x11
->RegisterCallback(x11
, man
->wd
.self
, Parent
, ManCallBack
, man
);
657 x11
->SetInputMask(x11
, man
->wd
.self
, StructureNotifyMask
|
658 ExposureMask
| ButtonPressMask
);
660 /* The order of creating windows is important for the stacking order */
662 man
->molw
= init_mw(x11
, man
->wd
.self
, 0, 0, 1, 1, WHITE
, BLUE
, ePBC
, box
);
665 InitWin(&(man
->title
), 0, 0, 1, 1, 0, NULL
);
666 man
->title
.self
= XCreateSimpleWindow(x11
->disp
, man
->molw
->wd
.self
,
667 man
->title
.x
, man
->title
.y
,
668 man
->title
.width
, man
->title
.height
,
669 man
->title
.bwidth
, WHITE
, BLUE
);
670 x11
->RegisterCallback(x11
, man
->title
.self
, man
->molw
->wd
.self
,
671 TitleCallBack
, &(man
->title
));
672 x11
->SetInputMask(x11
, man
->title
.self
, ExposureMask
| StructureNotifyMask
);
675 man
->bbox
= init_bbox(x11
, man
->wd
.self
, man
->wd
.self
, 1, WHITE
, BLUE
);
678 man
->legw
= init_legw(x11
, man
->wd
.self
, 0, 0, EWIDTH
, LEGHEIGHT
, WHITE
, BLUE
);
681 man
->vbox
= init_vbox(x11
, man
->molw
->wd
.self
, man
->wd
.self
, WHITE
, BLUE
);
686 void done_man(t_x11
*x11
, t_manager
*man
)
688 done_bbox(x11
, man
->vbox
);
689 done_bbox(x11
, man
->bbox
);
690 done_mw(x11
, man
->molw
);
691 done_legw(x11
, man
->legw
);
692 x11
->UnRegisterCallback(x11
, man
->title
.self
);
693 x11
->UnRegisterCallback(x11
, man
->wd
.self
);
703 void do_filter(t_x11
*x11
, t_manager
*man
, t_filter
*filter
)
708 for (i
= 0; (i
< man
->natom
); i
++)
710 man
->bVis
[i
] = false;
712 for (i
= 0; (i
< filter
->grps
->nr
); i
++)
714 if (filter
->bShow
[i
])
716 for (j
= filter
->grps
->index
[i
]; (j
< filter
->grps
->index
[i
+1]); j
++)
718 man
->bVis
[filter
->grps
->a
[j
]] = true;
723 ExposeWin(x11
->disp
, man
->wd
.self
);