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,2016,2017, 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.
51 #include <unistd.h> // for usleep()
54 #include "gromacs/fileio/tpxio.h"
55 #include "gromacs/math/utilities.h"
56 #include "gromacs/math/vec.h"
57 #include "gromacs/mdtypes/md_enums.h"
58 #include "gromacs/pbcutil/pbc.h"
59 #include "gromacs/topology/atomprop.h"
60 #include "gromacs/topology/ifunc.h"
61 #include "gromacs/utility/coolstuff.h"
62 #include "gromacs/utility/cstringutil.h"
63 #include "gromacs/utility/fatalerror.h"
64 #include "gromacs/utility/futil.h"
65 #include "gromacs/utility/smalloc.h"
66 #include "gromacs/utility/stringutil.h"
71 static void add_object(t_manager
*man
, eObject eO
, int ai
, int aj
)
73 srenew(man
->obj
, ++man
->nobj
);
74 man
->obj
[man
->nobj
-1].eO
= eO
;
75 man
->obj
[man
->nobj
-1].eV
= eVNormal
;
76 man
->obj
[man
->nobj
-1].color
= WHITE
;
77 man
->obj
[man
->nobj
-1].ai
= ai
;
78 man
->obj
[man
->nobj
-1].aj
= aj
;
79 man
->obj
[man
->nobj
-1].z
= 0.0;
82 static void add_bonds(t_manager
*man
, t_functype func
[],
83 t_ilist
*b
, bool bB
[])
85 bool *bH
= man
->bHydro
;
87 t_iatom type
, ai
, aj
, ak
;
91 std::fprintf(stderr
, "Going to make bonds from an ilist with %d entries\n", b
->nr
);
94 for (i
= 0; (i
< b
->nr
); )
99 delta
= interaction_function
[ftype
].nratoms
;
101 if (ftype
== F_SETTLE
)
105 bB
[ai
] = bB
[aj
] = bB
[ak
] = true;
106 add_object(man
, eOHBond
, ai
, aj
);
107 add_object(man
, eOHBond
, ai
, ak
);
109 else if (IS_CHEMBOND(ftype
))
113 std::fprintf(stderr
, "Adding bond from %d to %d\n", ai
, aj
);
115 bB
[ai
] = bB
[aj
] = true;
116 if (!(bH
[ai
] == bH
[aj
]))
118 add_object(man
, eOHBond
, ai
, aj
);
120 else if (!bH
[ai
] && !bH
[aj
])
122 add_object(man
, eOBond
, ai
, aj
);
126 std::fprintf(stderr
, "Type: %5d, delta: %5d\n", type
, delta
);
133 static void add_bpl(t_manager
*man
, t_idef
*idef
, bool bB
[])
137 for (ftype
= 0; ftype
< F_NRE
; ftype
++)
139 if (IS_CHEMBOND(ftype
) || ftype
== F_SETTLE
)
141 add_bonds(man
, idef
->functype
, &idef
->il
[ftype
], bB
);
146 static int which_atom(t_manager
*man
, int x
, int y
)
152 for (i
= 0; (i
< man
->natom
); i
++)
154 if ((std::abs(ix
[i
][XX
]-x
) < DELTA
) && (std::abs(ix
[i
][YY
]-y
) < DELTA
))
165 static void do_label(t_x11
*x11
, t_manager
*man
, int x
, int y
, bool bSet
)
170 if ((ai
= which_atom(man
, x
, y
)) != -1)
174 if (bSet
&& !man
->bLabel
[ai
])
177 man
->bLabel
[ai
] = true;
179 else if (!bSet
&& man
->bLabel
[ai
])
182 man
->bLabel
[ai
] = false;
188 XSetForeground(x11
->disp
, x11
->gc
, col
);
189 XDrawString(x11
->disp
, man
->molw
->wd
.self
, x11
->gc
, x
+2, y
-2, man
->szLab
[ai
],
190 std::strlen(man
->szLab
[ai
]));
191 XSetForeground(x11
->disp
, x11
->gc
, x11
->fg
);
195 static void show_label(t_x11
*x11
, t_manager
*man
, int x
, int y
)
197 do_label(x11
, man
, x
, y
, true);
200 static void hide_label(t_x11
*x11
, t_manager
*man
, int x
, int y
)
202 do_label(x11
, man
, x
, y
, false);
205 void set_file(t_x11
*x11
, t_manager
*man
, const char *trajectory
,
214 read_tpxheader(status
, &sh
, true);
215 snew(man
->ix
, sh
.natoms
);
216 snew(man
->zz
, sh
.natoms
);
217 snew(man
->col
, sh
.natoms
);
218 snew(man
->size
, sh
.natoms
);
219 snew(man
->vdw
, sh
.natoms
);
220 snew(man
->bLabel
, sh
.natoms
);
221 snew(man
->bVis
, sh
.natoms
);
222 for (i
= 0; (i
< sh
.natoms
); i
++)
224 man
->bVis
[i
] = false;
229 snew(man
->szLab
, sh
.natoms
);
230 snew(man
->bHydro
, sh
.natoms
);
232 read_tpx_top(status
, nullptr, man
->box
, &man
->natom
, nullptr, nullptr, &man
->top
);
233 man
->gpbc
= gmx_rmpbc_init(&man
->top
.idef
, -1, man
->natom
);
236 read_first_x(man
->oenv
, &man
->status
, trajectory
, &(man
->time
), &(man
->x
),
238 man
->trajfile
= gmx_strdup(trajectory
);
239 if (man
->natom
> man
->top
.atoms
.nr
)
241 gmx_fatal(FARGS
, "Topology %s (%d atoms) and trajectory %s (%d atoms) "
242 "do not match", status
, man
->top
.atoms
.nr
,
243 trajectory
, man
->natom
);
246 man
->title
.text
= gmx_strdup(gmx::formatString("%s: %s", *man
->top
.name
, gmx::getCoolQuote().c_str()).c_str());
247 man
->view
= init_view(man
->box
);
248 at
= &(man
->top
.atoms
);
249 aps
= gmx_atomprop_init();
250 for (i
= 0; (i
< man
->natom
); i
++)
252 char *aname
= *(at
->atomname
[i
]);
253 t_resinfo
*ri
= &at
->resinfo
[at
->atom
[i
].resind
];
255 man
->col
[i
] = Type2Color(aname
);
256 snew(man
->szLab
[i
], 20);
259 std::sprintf(man
->szLab
[i
], "%s%d%c, %s", *ri
->name
, ri
->nr
, ri
->ic
, aname
);
263 std::sprintf(man
->szLab
[i
], "%s%d, %s", *ri
->name
, ri
->nr
, aname
);
265 man
->bHydro
[i
] = (toupper(aname
[0]) == 'H');
270 else if (!gmx_atomprop_query(aps
, epropVDW
, *ri
->name
, aname
, &(man
->vdw
[i
])))
275 gmx_atomprop_destroy(aps
);
276 add_bpl(man
, &(man
->top
.idef
), bB
);
277 for (i
= 0; (i
< man
->natom
); i
++)
281 add_object(man
, eOSingle
, (int) i
, 0);
286 ExposeWin(x11
->disp
, man
->molw
->wd
.self
);
289 void step_message(t_x11
*x11
, t_manager
*man
)
293 letter
.type
= ClientMessage
;
294 letter
.xclient
.display
= x11
->disp
;
295 letter
.xclient
.window
= man
->wd
.self
;
296 letter
.xclient
.message_type
= 0;
297 letter
.xclient
.format
= 32;
298 letter
.xclient
.data
.l
[0] = IDSTEP
;
299 letter
.xclient
.data
.l
[1] = Button1
;
300 XSendEvent(x11
->disp
, letter
.xclient
.window
, True
, 0, &letter
);
303 static void reset_mols(t_block
*mols
, matrix box
, rvec x
[])
309 for (i
= 0; (i
< mols
->nr
); i
++)
312 m1
= mols
->index
[i
+1];
317 for (j
= m0
; (j
< m1
); j
++)
321 for (m
= 0; (m
< DIM
); m
++)
325 for (m
= 0; (m
< DIM
); m
++)
331 else if (xcm
[m
] >= box
[m
][m
])
336 ix
= icm
[XX
], iy
= icm
[YY
], iz
= icm
[ZZ
];
338 if ((ix
!= 0) || (iy
!= 0) || (iz
!= 0))
340 for (j
= m0
; (j
< m1
); j
++)
350 static bool step_man(t_manager
*man
, int *nat
)
352 static int ncount
= 0;
357 std::fprintf(stderr
, "Not initiated yet!");
360 bEof
= read_next_x(man
->oenv
, man
->status
, &man
->time
, man
->x
, man
->box
);
362 if (ncount
== man
->nSkip
)
364 auto atomsArrayRef
= gmx::arrayRefFromArray(reinterpret_cast<gmx::RVec
*>(man
->x
), man
->natom
);
365 switch (man
->molw
->boxtype
)
368 put_atoms_in_triclinic_unitcell(ecenterDEF
, man
->box
, atomsArrayRef
);
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
= static_cast<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
= static_cast<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 gmx_output_env_t
*oenv
)
648 man
->status
= nullptr;
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, nullptr);
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
);