3 * This source code is part of
7 * GROningen MAchine for Chemical Simulations
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.
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.
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.
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.
30 * For more info, check our website at http://www.gromacs.org
33 * GROningen Mixture of Alchemy and Childrens' Stories
61 const char gmx_residuetype_undefined[] = "Other";
63 struct gmx_residuetype
72 static gmx_bool gmx_ask_yesno(gmx_bool bASK)
80 c = toupper(fgetc(stdin));
82 while ((c != 'Y') && (c != 'N'));
92 t_blocka *new_blocka(void)
97 snew(block->index, 1);
102 void write_index(const char *outf, t_blocka *b, char **gnames)
107 out = gmx_fio_fopen(outf, "w");
108 /* fprintf(out,"%5d %5d\n",b->nr,b->nra); */
109 for (i = 0; (i < b->nr); i++)
111 fprintf(out, "[ %s ]\n", gnames[i]);
112 for (k = 0, j = b->index[i]; j < b->index[i+1]; j++, k++)
114 fprintf(out, "%4d ", b->a[j]+1);
125 void add_grp(t_blocka *b, char ***gnames, int nra, atom_id a[], const char *name)
129 srenew(b->index, b->nr+2);
130 srenew(*gnames, b->nr+1);
131 (*gnames)[b->nr] = strdup(name);
133 srenew(b->a, b->nra+nra);
134 for (i = 0; (i < nra); i++)
136 b->a[b->nra++] = a[i];
139 b->index[b->nr] = b->nra;
142 /* compare index in `a' with group in `b' at `index',
143 when `index'<0 it is relative to end of `b' */
144 static gmx_bool grp_cmp(t_blocka *b, int nra, atom_id a[], int index)
150 index = b->nr-1+index;
154 gmx_fatal(FARGS, "no such index group %d in t_blocka (nr=%d)", index, b->nr);
157 if (nra != b->index[index+1] - b->index[index])
161 for (i = 0; i < nra; i++)
163 if (a[i] != b->a[b->index[index]+i])
172 p_status(const char **restype, int nres, const char **typenames, int ntypes)
179 snew(counter, ntypes);
180 for (i = 0; i < ntypes; i++)
184 for (i = 0; i < nres; i++)
187 for (j = 0; j < ntypes; j++)
189 if (!gmx_strcasecmp(restype[i], typenames[j]))
196 for (i = 0; (i < ntypes); i++)
200 printf("There are: %5d %10s residues\n", counter[i], typenames[i]);
209 mk_aid(t_atoms *atoms, const char ** restype, const char * typestring, int *nra, gmx_bool bMatch)
210 /* Make an array of atom_ids for all atoms with residuetypes matching typestring, or the opposite if bMatch is false */
218 for (i = 0; (i < atoms->nr); i++)
220 res = !gmx_strcasecmp(restype[atoms->atom[i].resind], typestring);
240 static void analyse_other(const char ** restype, t_atoms *atoms,
241 t_blocka *gb, char ***gn, gmx_bool bASK, gmx_bool bVerb)
243 restp_t *restp = NULL;
246 atom_id *other_ndx, *aid, *aaid;
247 int i, j, k, l, resind, naid, naaid, natp, nrestp = 0;
249 for (i = 0; (i < atoms->nres); i++)
251 if (gmx_strcasecmp(restype[i], "Protein") && gmx_strcasecmp(restype[i], "DNA") && gmx_strcasecmp(restype[i], "RNA") && gmx_strcasecmp(restype[i], "Water"))
261 printf("Analysing residues not classified as Protein/DNA/RNA/Water and splitting into groups...\n");
263 snew(other_ndx, atoms->nr);
264 for (k = 0; (k < atoms->nr); k++)
266 resind = atoms->atom[k].resind;
267 rname = *atoms->resinfo[resind].name;
268 if (gmx_strcasecmp(restype[resind], "Protein") && gmx_strcasecmp(restype[resind], "DNA") &&
269 gmx_strcasecmp(restype[resind], "RNA") && gmx_strcasecmp(restype[resind], "Water"))
272 for (l = 0; (l < nrestp); l++)
274 if (strcmp(restp[l].rname, rname) == 0)
281 srenew(restp, nrestp+1);
282 restp[nrestp].rname = strdup(rname);
283 restp[nrestp].bNeg = FALSE;
284 restp[nrestp].gname = strdup(rname);
290 for (i = 0; (i < nrestp); i++)
292 snew(aid, atoms->nr);
294 for (j = 0; (j < atoms->nr); j++)
296 rname = *atoms->resinfo[atoms->atom[j].resind].name;
297 if ((strcmp(restp[i].rname, rname) == 0 && !restp[i].bNeg) ||
298 (strcmp(restp[i].rname, rname) != 0 && restp[i].bNeg))
303 add_grp(gb, gn, naid, aid, restp[i].gname);
306 printf("split %s into atoms (y/n) ? ", restp[i].gname);
308 if (gmx_ask_yesno(bASK))
311 for (k = 0; (k < naid); k++)
313 aname = *atoms->atomname[aid[k]];
314 for (l = 0; (l < natp); l++)
316 if (strcmp(aname, attp[l]) == 0)
323 srenew(attp, ++natp);
324 attp[natp-1] = aname;
329 for (l = 0; (l < natp); l++)
333 for (k = 0; (k < naid); k++)
335 aname = *atoms->atomname[aid[k]];
336 if (strcmp(aname, attp[l]) == 0)
338 aaid[naaid++] = aid[k];
341 add_grp(gb, gn, naaid, aaid, attp[l]);
355 /*! /brief Instances of this struct contain the data necessary to
356 * construct a single (protein) index group in
358 typedef struct gmx_help_make_index_group
360 /** The set of atom names that will be used to form this index group */
361 const char **defining_atomnames;
362 /** Size of the defining_atomnames array */
363 const int num_defining_atomnames;
364 /** Name of this index group */
365 const char *group_name;
366 /** Whether the above atom names name the atoms in the group, or
367 those not in the group */
368 gmx_bool bTakeComplement;
369 /** The index in wholename gives the first item in the arrays of
370 atomnames that should be tested with 'gmx_strncasecmp' in stead of
371 gmx_strcasecmp, or -1 if all items should be tested with strcasecmp
372 This is comparable to using a '*' wildcard at the end of specific
373 atom names, but that is more involved to implement...
376 /** Only create this index group if it differs from the one specified in compareto,
377 where -1 means to always create this group. */
379 } t_gmx_help_make_index_group;
381 static void analyse_prot(const char ** restype, t_atoms *atoms,
382 t_blocka *gb, char ***gn, gmx_bool bASK, gmx_bool bVerb)
384 /* lists of atomnames to be used in constructing index groups: */
385 static const char *pnoh[] = { "H", "HN" };
386 static const char *pnodum[] = {
387 "MN1", "MN2", "MCB1", "MCB2", "MCG1", "MCG2",
388 "MCD1", "MCD2", "MCE1", "MCE2", "MNZ1", "MNZ2"
390 static const char *calpha[] = { "CA" };
391 static const char *bb[] = { "N", "CA", "C" };
392 static const char *mc[] = { "N", "CA", "C", "O", "O1", "O2", "OC1", "OC2", "OT", "OXT" };
393 static const char *mcb[] = { "N", "CA", "CB", "C", "O", "O1", "O2", "OC1", "OC2", "OT", "OXT" };
394 static const char *mch[] = {
395 "N", "CA", "C", "O", "O1", "O2", "OC1", "OC2", "OT", "OXT",
396 "H1", "H2", "H3", "H", "HN"
399 static const t_gmx_help_make_index_group constructing_data[] =
400 {{ NULL, 0, "Protein", TRUE, -1, -1},
401 { pnoh, asize(pnoh), "Protein-H", TRUE, 0, -1},
402 { calpha, asize(calpha), "C-alpha", FALSE, -1, -1},
403 { bb, asize(bb), "Backbone", FALSE, -1, -1},
404 { mc, asize(mc), "MainChain", FALSE, -1, -1},
405 { mcb, asize(mcb), "MainChain+Cb", FALSE, -1, -1},
406 { mch, asize(mch), "MainChain+H", FALSE, -1, -1},
407 { mch, asize(mch), "SideChain", TRUE, -1, -1},
408 { mch, asize(mch), "SideChain-H", TRUE, 11, -1},
409 { pnodum, asize(pnodum), "Prot-Masses", TRUE, -1, 0}, };
410 const int num_index_groups = asize(constructing_data);
414 int nra, nnpres, npres;
416 char ndx_name[STRLEN], *atnm;
421 printf("Analysing Protein...\n");
423 snew(aid, atoms->nr);
425 /* calculate the number of protein residues */
427 for (i = 0; (i < atoms->nres); i++)
429 if (0 == gmx_strcasecmp(restype[i], "Protein"))
434 /* find matching or complement atoms */
435 for (i = 0; (i < (int)num_index_groups); i++)
438 for (n = 0; (n < atoms->nr); n++)
440 if (0 == gmx_strcasecmp(restype[atoms->atom[n].resind], "Protein"))
443 for (j = 0; (j < constructing_data[i].num_defining_atomnames); j++)
445 /* skip digits at beginning of atomname, e.g. 1H */
446 atnm = *atoms->atomname[n];
447 while (isdigit(atnm[0]))
451 if ( (constructing_data[i].wholename == -1) || (j < constructing_data[i].wholename) )
453 if (0 == gmx_strcasecmp(constructing_data[i].defining_atomnames[j], atnm))
460 if (0 == gmx_strncasecmp(constructing_data[i].defining_atomnames[j], atnm, strlen(constructing_data[i].defining_atomnames[j])))
466 if (constructing_data[i].bTakeComplement != match)
472 /* if we want to add this group always or it differs from previous
474 if (-1 == constructing_data[i].compareto || !grp_cmp(gb, nra, aid, constructing_data[i].compareto-i) )
476 add_grp(gb, gn, nra, aid, constructing_data[i].group_name);
482 for (i = 0; (i < (int)num_index_groups); i++)
484 printf("Split %12s into %5d residues (y/n) ? ", constructing_data[i].group_name, npres);
485 if (gmx_ask_yesno(bASK))
489 for (n = 0; ((atoms->atom[n].resind < npres) && (n < atoms->nr)); )
491 resind = atoms->atom[n].resind;
492 for (; ((atoms->atom[n].resind == resind) && (n < atoms->nr)); n++)
495 for (j = 0; (j < constructing_data[i].num_defining_atomnames); j++)
497 if (0 == gmx_strcasecmp(constructing_data[i].defining_atomnames[j], *atoms->atomname[n]))
502 if (constructing_data[i].bTakeComplement != match)
507 /* copy the residuename to the tail of the groupname */
511 ri = &atoms->resinfo[resind];
512 sprintf(ndx_name, "%s_%s%d%c",
513 constructing_data[i].group_name, *ri->name, ri->nr, ri->ic == ' ' ? '\0' : ri->ic);
514 add_grp(gb, gn, nra, aid, ndx_name);
520 printf("Make group with sidechain and C=O swapped (y/n) ? ");
521 if (gmx_ask_yesno(bASK))
523 /* Make swap sidechain C=O index */
526 for (n = 0; ((atoms->atom[n].resind < npres) && (n < atoms->nr)); )
528 resind = atoms->atom[n].resind;
530 for (; ((atoms->atom[n].resind == resind) && (n < atoms->nr)); n++)
532 if (strcmp("CA", *atoms->atomname[n]) == 0)
538 else if (strcmp("C", *atoms->atomname[n]) == 0)
542 gmx_incons("Atom naming problem");
546 else if (strcmp("O", *atoms->atomname[n]) == 0)
550 gmx_incons("Atom naming problem");
554 else if (strcmp("O1", *atoms->atomname[n]) == 0)
558 gmx_incons("Atom naming problem");
568 /* copy the residuename to the tail of the groupname */
571 add_grp(gb, gn, nra, aid, "SwapSC-CO");
582 /* Return 0 if the name was found, otherwise -1.
583 * p_restype is set to a pointer to the type name, or 'Other' if we did not find it.
586 gmx_residuetype_get_type(gmx_residuetype_t rt, const char * resname, const char ** p_restype)
591 for (i = 0; i < rt->n && rc; i++)
593 rc = gmx_strcasecmp(rt->resname[i], resname);
596 *p_restype = (rc == 0) ? rt->restype[i-1] : gmx_residuetype_undefined;
602 gmx_residuetype_add(gmx_residuetype_t rt, const char *newresname, const char *newrestype)
606 const char * p_oldtype;
608 found = !gmx_residuetype_get_type(rt, newresname, &p_oldtype);
610 if (found && gmx_strcasecmp(p_oldtype, newrestype))
612 fprintf(stderr, "Warning: Residue '%s' already present with type '%s' in database, ignoring new type '%s'.",
613 newresname, p_oldtype, newrestype);
618 srenew(rt->resname, rt->n+1);
619 srenew(rt->restype, rt->n+1);
620 rt->resname[rt->n] = strdup(newresname);
621 rt->restype[rt->n] = strdup(newrestype);
630 gmx_residuetype_init(gmx_residuetype_t *prt)
634 char resname[STRLEN], restype[STRLEN], dum[STRLEN];
637 struct gmx_residuetype *rt;
646 db = libopen("residuetypes.dat");
648 while (get_a_line(db, line, STRLEN))
654 if (sscanf(line, "%s %s %s", resname, restype, dum) != 2)
656 gmx_fatal(FARGS, "Incorrect number of columns (2 expected) for line in residuetypes.dat");
658 gmx_residuetype_add(rt, resname, restype);
670 gmx_residuetype_destroy(gmx_residuetype_t rt)
674 for (i = 0; i < rt->n; i++)
676 sfree(rt->resname[i]);
677 sfree(rt->restype[i]);
687 gmx_residuetype_get_alltypes(gmx_residuetype_t rt,
688 const char *** p_typenames,
693 const char ** my_typename;
699 for (i = 0; i < rt->n; i++)
703 for (j = 0; j < n && !found; j++)
705 found = !gmx_strcasecmp(p, my_typename[j]);
710 srenew(my_typename, n+1);
716 *p_typenames = my_typename;
724 gmx_residuetype_is_protein(gmx_residuetype_t rt, const char *resnm)
729 if (gmx_residuetype_get_type(rt, resnm, &p_type) == 0 &&
730 gmx_strcasecmp(p_type, "Protein") == 0)
742 gmx_residuetype_is_dna(gmx_residuetype_t rt, const char *resnm)
747 if (gmx_residuetype_get_type(rt, resnm, &p_type) == 0 &&
748 gmx_strcasecmp(p_type, "DNA") == 0)
760 gmx_residuetype_is_rna(gmx_residuetype_t rt, const char *resnm)
765 if (gmx_residuetype_get_type(rt, resnm, &p_type) == 0 &&
766 gmx_strcasecmp(p_type, "RNA") == 0)
777 /* Return the size of the arrays */
779 gmx_residuetype_get_size(gmx_residuetype_t rt)
784 /* Search for a residuetype with name resnm within the
785 * gmx_residuetype database. Return the index if found,
789 gmx_residuetype_get_index(gmx_residuetype_t rt, const char *resnm)
794 for (i = 0; i < rt->n && rc; i++)
796 rc = gmx_strcasecmp(rt->resname[i], resnm);
799 return (0 == rc) ? i-1 : -1;
802 /* Return the name of the residuetype with the given index, or
803 * NULL if not found. */
805 gmx_residuetype_get_name(gmx_residuetype_t rt, int index)
807 if (index >= 0 && index < rt->n)
809 return rt->resname[index];
819 void analyse(t_atoms *atoms, t_blocka *gb, char ***gn, gmx_bool bASK, gmx_bool bVerb)
821 gmx_residuetype_t rt = NULL;
824 const char ** restype;
830 const char ** p_typename;
837 printf("Analysing residue names:\n");
839 /* Create system group, every single atom */
840 snew(aid, atoms->nr);
841 for (i = 0; i < atoms->nr; i++)
845 add_grp(gb, gn, atoms->nr, aid, "System");
848 /* For every residue, get a pointer to the residue type name */
849 gmx_residuetype_init(&rt);
852 snew(restype, atoms->nres);
855 for (i = 0; i < atoms->nres; i++)
857 resnm = *atoms->resinfo[i].name;
858 gmx_residuetype_get_type(rt, resnm, &(restype[i]));
860 /* Note that this does not lead to a N*N loop, but N*K, where
861 * K is the number of residue _types_, which is small and independent of N.
864 for (k = 0; k < ntypes && !found; k++)
866 found = !strcmp(restype[i], p_typename[k]);
870 srenew(p_typename, ntypes+1);
871 p_typename[ntypes++] = strdup(restype[i]);
877 p_status(restype, atoms->nres, p_typename, ntypes);
880 for (k = 0; k < ntypes; k++)
882 aid = mk_aid(atoms, restype, p_typename[k], &nra, TRUE);
884 /* Check for special types to do fancy stuff with */
886 if (!gmx_strcasecmp(p_typename[k], "Protein") && nra > 0)
890 analyse_prot(restype, atoms, gb, gn, bASK, bVerb);
892 /* Create a Non-Protein group */
893 aid = mk_aid(atoms, restype, "Protein", &nra, FALSE);
894 if ((nra > 0) && (nra < atoms->nr))
896 add_grp(gb, gn, nra, aid, "non-Protein");
900 else if (!gmx_strcasecmp(p_typename[k], "Water") && nra > 0)
902 add_grp(gb, gn, nra, aid, p_typename[k]);
903 /* Add this group as 'SOL' too, for backward compatibility with older gromacs versions */
904 add_grp(gb, gn, nra, aid, "SOL");
908 /* Solvent, create a negated group too */
909 aid = mk_aid(atoms, restype, "Water", &nra, FALSE);
910 if ((nra > 0) && (nra < atoms->nr))
912 add_grp(gb, gn, nra, aid, "non-Water");
919 add_grp(gb, gn, nra, aid, p_typename[k]);
921 analyse_other(restype, atoms, gb, gn, bASK, bVerb);
927 gmx_residuetype_destroy(rt);
929 /* Create a merged water_and_ions group */
935 for (i = 0; i < gb->nr; i++)
937 if (!gmx_strcasecmp((*gn)[i], "Water"))
940 nwater = gb->index[i+1]-gb->index[i];
942 else if (!gmx_strcasecmp((*gn)[i], "Ion"))
945 nion = gb->index[i+1]-gb->index[i];
949 if (nwater > 0 && nion > 0)
951 srenew(gb->index, gb->nr+2);
952 srenew(*gn, gb->nr+1);
953 (*gn)[gb->nr] = strdup("Water_and_ions");
954 srenew(gb->a, gb->nra+nwater+nion);
957 for (i = gb->index[iwater]; i < gb->index[iwater+1]; i++)
959 gb->a[gb->nra++] = gb->a[i];
964 for (i = gb->index[iion]; i < gb->index[iion+1]; i++)
966 gb->a[gb->nra++] = gb->a[i];
970 gb->index[gb->nr] = gb->nra;
975 void check_index(char *gname, int n, atom_id index[], char *traj, int natoms)
979 for (i = 0; i < n; i++)
981 if (index[i] >= natoms)
983 gmx_fatal(FARGS, "%s atom number (index[%d]=%d) is larger than the number of atoms in %s (%d)",
984 gname ? gname : "Index", i+1, index[i]+1,
985 traj ? traj : "the trajectory", natoms);
987 else if (index[i] < 0)
989 gmx_fatal(FARGS, "%s atom number (index[%d]=%d) is less than zero",
990 gname ? gname : "Index", i+1, index[i]+1);
995 t_blocka *init_index(const char *gfile, char ***grpname)
1000 int i, j, ng, nread;
1001 char line[STRLEN], *pt, str[STRLEN];
1003 in = gmx_fio_fopen(gfile, "r");
1005 get_a_line(in, line, STRLEN);
1017 if (get_header(line, str))
1020 srenew(b->index, b->nr+1);
1021 srenew(*grpname, b->nr);
1026 b->index[b->nr] = b->index[b->nr-1];
1027 (*grpname)[b->nr-1] = strdup(str);
1033 gmx_fatal(FARGS, "The first header of your indexfile is invalid");
1036 while (sscanf(pt, "%s", str) == 1)
1038 i = b->index[b->nr];
1039 if (i >= maxentries)
1042 srenew(b->a, maxentries);
1044 b->a[i] = strtol(str, NULL, 10)-1;
1047 pt = strstr(pt, str)+strlen(str);
1051 while (get_a_line(in, line, STRLEN));
1056 sscanf(line, "%d%d", &b->nr, &b->nra);
1057 snew(b->index, b->nr+1);
1058 snew(*grpname, b->nr);
1061 for (i = 0; (i < b->nr); i++)
1063 nread = fscanf(in, "%s%d", str, &ng);
1064 (*grpname)[i] = strdup(str);
1065 b->index[i+1] = b->index[i]+ng;
1066 if (b->index[i+1] > b->nra)
1068 gmx_fatal(FARGS, "Something wrong in your indexfile at group %s", str);
1070 for (j = 0; (j < ng); j++)
1072 nread = fscanf(in, "%d", &a);
1073 b->a[b->index[i]+j] = a;
1079 for (i = 0; (i < b->nr); i++)
1081 for (j = b->index[i]; (j < b->index[i+1]); j++)
1085 fprintf(stderr, "\nWARNING: negative index %d in group %s\n\n",
1086 b->a[j], (*grpname)[i]);
1094 static void minstring(char *str)
1098 for (i = 0; (i < (int)strlen(str)); i++)
1107 int find_group(char s[], int ngrps, char **grpname)
1110 char string[STRLEN];
1116 /* first look for whole name match */
1119 for (i = 0; i < ngrps; i++)
1121 if (gmx_strcasecmp_min(s, grpname[i]) == 0)
1131 /* second look for first string match */
1134 for (i = 0; i < ngrps; i++)
1136 if (gmx_strncasecmp_min(s, grpname[i], n) == 0)
1146 /* last look for arbitrary substring match */
1151 for (i = 0; i < ngrps; i++)
1153 strcpy(string, grpname[i]);
1156 if (strstr(string, s) != NULL)
1168 printf("Error: Multiple groups '%s' selected\n", s);
1174 static int qgroup(int *a, int ngrps, char **grpname)
1183 fprintf(stderr, "Select a group: ");
1186 if (scanf("%s", s) != 1)
1188 gmx_fatal(FARGS, "Cannot read from input");
1190 trim(s); /* remove spaces */
1192 while (strlen(s) == 0);
1193 aa = strtol(s, &end, 10);
1194 if (aa == 0 && end[0] != '\0') /* string entered */
1196 aa = find_group(s, ngrps, grpname);
1198 bInRange = (aa >= 0 && aa < ngrps);
1201 printf("Error: No such group '%s'\n", s);
1205 printf("Selected %d: '%s'\n", aa, grpname[aa]);
1210 static void rd_groups(t_blocka *grps, char **grpname, char *gnames[],
1211 int ngrps, int isize[], atom_id *index[], int grpnr[])
1217 gmx_fatal(FARGS, "Error: no groups in indexfile");
1219 for (i = 0; (i < grps->nr); i++)
1221 fprintf(stderr, "Group %5d (%15s) has %5d elements\n", i, grpname[i],
1222 grps->index[i+1]-grps->index[i]);
1224 for (i = 0; (i < ngrps); i++)
1230 gnr1 = qgroup(&grpnr[i], grps->nr, grpname);
1231 if ((gnr1 < 0) || (gnr1 >= grps->nr))
1233 fprintf(stderr, "Select between %d and %d.\n", 0, grps->nr-1);
1236 while ((gnr1 < 0) || (gnr1 >= grps->nr));
1240 fprintf(stderr, "There is one group in the index\n");
1243 gnames[i] = strdup(grpname[gnr1]);
1244 isize[i] = grps->index[gnr1+1]-grps->index[gnr1];
1245 snew(index[i], isize[i]);
1246 for (j = 0; (j < isize[i]); j++)
1248 index[i][j] = grps->a[grps->index[gnr1]+j];
1253 void rd_index(const char *statfile, int ngrps, int isize[],
1254 atom_id *index[], char *grpnames[])
1263 gmx_fatal(FARGS, "No index file specified");
1265 grps = init_index(statfile, &gnames);
1266 rd_groups(grps, gnames, grpnames, ngrps, isize, index, grpnr);
1269 void rd_index_nrs(char *statfile, int ngrps, int isize[],
1270 atom_id *index[], char *grpnames[], int grpnr[])
1277 gmx_fatal(FARGS, "No index file specified");
1279 grps = init_index(statfile, &gnames);
1281 rd_groups(grps, gnames, grpnames, ngrps, isize, index, grpnr);
1284 void get_index(t_atoms *atoms, const char *fnm, int ngrps,
1285 int isize[], atom_id *index[], char *grpnames[])
1288 t_blocka *grps = NULL;
1295 grps = init_index(fnm, gnames);
1300 snew(grps->index, 1);
1301 analyse(atoms, grps, gnames, FALSE, FALSE);
1305 gmx_incons("You need to supply a valid atoms structure or a valid index file name");
1308 rd_groups(grps, *gnames, grpnames, ngrps, isize, index, grpnr);
1311 t_cluster_ndx *cluster_index(FILE *fplog, const char *ndx)
1317 c->clust = init_index(ndx, &c->grpname);
1319 for (i = 0; (i < c->clust->nra); i++)
1321 c->maxframe = max(c->maxframe, c->clust->a[i]);
1323 fprintf(fplog ? fplog : stdout,
1324 "There are %d clusters containing %d structures, highest framenr is %d\n",
1325 c->clust->nr, c->clust->nra, c->maxframe);
1328 pr_blocka(debug, 0, "clust", c->clust, TRUE);
1329 for (i = 0; (i < c->clust->nra); i++)
1331 if ((c->clust->a[i] < 0) || (c->clust->a[i] > c->maxframe))
1333 gmx_fatal(FARGS, "Range check error for c->clust->a[%d] = %d\n"
1334 "should be within 0 and %d", i, c->clust->a[i], c->maxframe+1);
1338 c->inv_clust = make_invblocka(c->clust, c->maxframe);