changed reading hint
[gromacs/adressmacs.git] / src / tools / make_ndx.c
blob9dd1553351f163b98b838824a73456771e59017a
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 2.0
12 * Copyright (c) 1991-1999
13 * BIOSON Research Institute, Dept. of Biophysical Chemistry
14 * University of Groningen, The Netherlands
16 * Please refer to:
17 * GROMACS: A message-passing parallel molecular dynamics implementation
18 * H.J.C. Berendsen, D. van der Spoel and R. van Drunen
19 * Comp. Phys. Comm. 91, 43-56 (1995)
21 * Also check out our WWW page:
22 * http://md.chem.rug.nl/~gmx
23 * or e-mail to:
24 * gromacs@chem.rug.nl
26 * And Hey:
27 * Great Red Oystrich Makes All Chemists Sane
29 static char *SRCID_make_ndx_c = "$Id$";
31 #include <ctype.h>
32 #include "sysstuff.h"
33 #include "strdb.h"
34 #include "futil.h"
35 #include "macros.h"
36 #include "string2.h"
37 #include "statutil.h"
38 #include "confio.h"
39 #include "assert.h"
40 #include "copyrite.h"
41 #include "typedefs.h"
42 #include "rdgroup.h"
43 #include "smalloc.h"
44 #include "vec.h"
45 #include "index.h"
47 #define MAXNAMES 20
49 bool bCase=FALSE;
51 static int or_groups(atom_id nr1,atom_id *at1,atom_id nr2,atom_id *at2,
52 atom_id *nr,atom_id *at)
54 atom_id i1,i2,max=0;
55 bool bNotIncr;
57 *nr=0;
59 bNotIncr=FALSE;
60 for(i1=0; i1<nr1; i1++) {
61 if ((i1>0) && (at1[i1] <= max))
62 bNotIncr=TRUE;
63 max=at1[i1];
65 for(i1=0; i1<nr2; i1++) {
66 if ((i1>0) && (at2[i1] <= max))
67 bNotIncr=TRUE;
68 max=at2[i1];
71 if (bNotIncr)
72 printf("One of your groups is not ascending\n");
73 else {
74 i1=0;
75 i2=0;
76 *nr=0;
77 while ((i1 < nr1) || (i2 < nr2)) {
78 if ((i2 == nr2) || ((i1<nr1) && (at1[i1] < at2[i2]))) {
79 at[*nr]=at1[i1];
80 (*nr)++;
81 i1++;
83 else {
84 if ((i2<nr2) && ((i1==nr1) || (at1[i1] > at2[i2]))) {
85 at[*nr]=at2[i2];
86 (*nr)++;
88 i2++;
92 printf("Merged two groups with OR: %u %u -> %u\n",nr1,nr2,*nr);
95 return *nr;
98 static int and_groups(atom_id nr1,atom_id *at1,atom_id nr2,atom_id *at2,
99 atom_id *nr,atom_id *at)
101 atom_id i1,i2;
103 *nr=0;
104 for (i1=0; i1<nr1; i1++) {
105 for (i2=0; i2<nr2; i2++) {
106 if (at1[i1]==at2[i2]) {
107 at[*nr]=at1[i1];
108 (*nr)++;
113 printf("Merged two groups with AND: %u %u -> %u\n",nr1,nr2,*nr);
115 return *nr;
118 static bool isalnum_star(char c)
120 return (isalnum(c) || (c=='*'));
123 static int parse_names(char **string,int *n_names,char **names)
125 int i;
127 *n_names=0;
128 while ((isalnum_star((*string)[0]) || ((*string)[0]==' '))) {
129 if (isalnum_star((*string)[0])) {
130 if (*n_names >= MAXNAMES)
131 fatal_error(0,"To many names: %d\n",*n_names+1);
132 i=0;
133 while (isalnum_star((*string)[i])) {
134 names[*n_names][i]=(*string)[i];
135 i++;
136 if (i==5) {
137 printf("Name to long: %d characters\n",i);
138 return 0;
141 names[*n_names][i]='\0';
142 if (!bCase)
143 upstring(names[*n_names]);
144 *string += i;
145 (*n_names)++;
147 else
148 (*string)++;
151 return *n_names;
154 static bool parse_int(char **string,int *nr)
156 bool bRet;
158 while ((*string)[0]==' ')
159 (*string)++;
161 bRet=FALSE;
163 if (isdigit((*string)[0])) {
164 *nr=(*string)[0]-'0';
165 (*string)++;
166 while (isdigit((*string)[0])) {
167 *nr = (*nr)*10+(*string)[0]-'0';
168 (*string)++;
170 bRet=TRUE;
172 else
173 *nr=NOTSET;
175 return bRet;
178 static int select_atomnumbers(char **string,t_atoms *atoms,atom_id n1,
179 atom_id *nr,atom_id *index,char *gname)
181 char buf[STRLEN];
182 int i,up;
184 *nr=0;
185 while ((*string)[0]==' ')
186 (*string)++;
187 if ((*string)[0]=='-') {
188 (*string)++;
189 parse_int(string,&up);
190 if ((n1<1) || (n1>atoms->nr) || (up<1) || (up>atoms->nr))
191 printf("Invalid atom range\n");
192 else {
193 for(i=n1-1; i<=up-1; i++) {
194 index[*nr]=i;
195 (*nr)++;
197 printf("Found %u atom%s in range %u-%d\n",*nr,(*nr==1)?"":"s",n1,up);
198 if (n1==up)
199 sprintf(buf,"a_%u",n1);
200 else
201 sprintf(buf,"a_%u-%d",n1,up);
202 strcpy(gname,buf);
205 else {
206 i=n1;
207 sprintf(gname,"a");
208 do {
209 if ((i-1>=0) && (i-1<atoms->nr)) {
210 index[*nr] = i-1;
211 (*nr)++;
212 sprintf(buf,"_%d",i);
213 strcat(gname,buf);
214 } else {
215 printf("Invalid atom number %d\n",i);
216 *nr = 0;
218 } while ((*nr!=0) && (parse_int(string,&i)));
221 return *nr;
224 static int select_residuenumbers(char **string,t_atoms *atoms,atom_id n1,
225 atom_id *nr,atom_id *index,char *gname)
227 char buf[STRLEN];
228 int j,resnr;
229 int i,up;
231 *nr=0;
232 while ((*string)[0]==' ')
233 (*string)++;
234 if ((*string)[0]=='-') {
235 (*string)++;
236 parse_int(string,&up);
238 for(i=0; i<atoms->nr; i++) {
239 resnr=atoms->atom[i].resnr;
240 for(j=n1; (j<=up); j++) {
241 if (resnr==j-1) {
242 index[*nr]=i;
243 (*nr)++;
247 printf("Found %u atom%s with res.nr. in range %u-%d\n",
248 *nr,(*nr==1)?"":"s",n1,up);
249 if (n1==up)
250 sprintf(buf,"r_%u",n1);
251 else
252 sprintf(buf,"r_%u-%d",n1,up);
253 strcpy(gname,buf);
255 else {
256 j=n1;
257 sprintf(gname,"r");
258 do {
259 for(i=0; i<atoms->nr; i++) {
260 if (atoms->atom[i].resnr==j-1) {
261 index[*nr]=i;
262 (*nr)++;
265 sprintf(buf,"_%d",j);
266 strcat(gname,buf);
267 } while (parse_int(string,&j));
270 return *nr;
273 static bool comp_name(char *name,char *search)
275 int n;
277 n=strlen(search)-1;
279 return (((search[n]!='*') &&
280 (bCase ? strcmp(name,search) : strcasecmp(name,search))) ||
281 ((search[n]=='*') &&
282 (bCase ? strncmp(name,search,n) : strncasecmp(name,search,n))));
285 static int select_chainnames(t_atoms *atoms,int n_names,char **names,
286 atom_id *nr,atom_id *index)
288 char name[2];
289 int j;
290 atom_id i;
292 name[1]=0;
293 *nr=0;
294 for(i=0; i<atoms->nr; i++) {
295 name[0]=atoms->atom[i].chain;
296 j=0;
297 while (j<n_names && comp_name(name,names[j]))
298 j++;
299 if (j<n_names) {
300 index[*nr]=i;
301 (*nr)++;
304 printf("Found %u atom%s with chain identifier%s",
305 *nr,(*nr==1)?"":"s",(n_names==1)?"":"s");
306 for(j=0; (j<n_names); j++)
307 printf(" %s",names[j]);
308 printf("\n");
310 return *nr;
313 static int select_atomnames(t_atoms *atoms,int n_names,char **names,
314 atom_id *nr,atom_id *index)
316 char *name;
317 int j;
318 atom_id i;
320 *nr=0;
321 for(i=0; i<atoms->nr; i++) {
322 name=*(atoms->atomname[i]);
323 j=0;
324 while (j<n_names && comp_name(name,names[j]))
325 j++;
326 if (j<n_names) {
327 index[*nr]=i;
328 (*nr)++;
331 printf("Found %u atoms with name%s",*nr,(n_names==1)?"":"s");
332 for(j=0; (j<n_names); j++)
333 printf(" %s",names[j]);
334 printf("\n");
336 return *nr;
339 static int select_residuenames(t_atoms *atoms,int n_names,char **names,
340 atom_id *nr,atom_id *index)
342 char *name;
343 int j;
344 atom_id i;
346 *nr=0;
347 for(i=0; i<atoms->nr; i++) {
348 name=*(atoms->resname[atoms->atom[i].resnr]);
349 j=0;
350 while (j<n_names && comp_name(name,names[j]))
351 j++;
352 if (j<n_names) {
353 index[*nr]=i;
354 (*nr)++;
357 printf("Found %u atoms with residue name%s",*nr,(n_names==1)?"":"s");
358 for(j=0; (j<n_names); j++)
359 printf(" %s",names[j]);
360 printf("\n");
362 return *nr;
365 static void copy2block(int n,atom_id *index,t_block *block)
367 int i,n0;
369 block->nr++;
370 n0=block->nra;
371 block->nra=n0+n;
372 srenew(block->index,block->nr+1);
373 block->index[block->nr]=n0+n;
374 srenew(block->a,n0+n);
375 for(i=0; i<n; i++)
376 block->a[n0+i]=index[i];
379 static void make_gname(int n,char **names,char *gname)
381 int i;
383 strcpy(gname,names[0]);
384 for (i=1; i<n; i++) {
385 strcat(gname,"_");
386 strcat(gname,names[i]);
390 static void copy_group(int g,t_block *block,atom_id *nr,atom_id *index)
392 int i,i0;
394 i0=block->index[g];
395 *nr=block->index[g+1]-i0;
396 for (i=0; i<=*nr; i++)
397 index[i]=block->a[i0+i];
400 static void remove_group(int nr,int nr2,t_block *block,char ***gn)
402 int i,j,shift;
404 if (nr2==NOTSET)
405 nr2=nr;
407 for(j=0; j<=nr2-nr; j++) {
408 if ((nr<0) || (nr>=block->nr))
409 printf("Group %d does not exist\n",nr+j);
410 else {
411 shift=block->index[nr+1]-block->index[nr];
412 for(i=block->index[nr+1]; i<block->nra; i++)
413 block->a[i-shift]=block->a[i];
415 for(i=nr; i<block->nr; i++)
416 block->index[i]=block->index[i+1]-shift;
417 sfree((*gn)[nr]);
418 for(i=nr; i<block->nr-1; i++) {
419 (*gn)[i]=(*gn)[i+1];
421 block->nr--;
422 block->nra=block->index[block->nr];
423 printf("Removed group %d\n",nr+j);
428 static void split_group(t_atoms *atoms,int sel_nr,t_block *block,char ***gn,
429 bool bAtom)
431 char buf[STRLEN],*name;
432 int i,nr;
433 atom_id a,n0,n1,max;
435 if (bAtom)
436 printf("Splitting group %d into residues\n",sel_nr);
437 else
438 printf("Splitting group %d into atoms\n",sel_nr);
440 max=block->nra;
441 n0=block->index[sel_nr];
442 n1=block->index[sel_nr+1];
443 for (i=n0; i<n1; i++) {
444 a=block->a[i];
445 nr=atoms->atom[a].resnr;
446 name=*(atoms->resname[nr]);
447 if (bAtom || (i==n0) || (atoms->atom[block->a[i-1]].resnr!=nr)) {
448 if (i>n0)
449 block->index[block->nr]=block->nra;
450 block->nr++;
451 srenew(block->index,block->nr+1);
452 srenew(*gn,block->nr);
453 if (bAtom)
454 sprintf(buf,"%s_%s_%u",(*gn)[sel_nr],*atoms->atomname[a],a+1);
455 else
456 sprintf(buf,"%s_%s_%d",(*gn)[sel_nr],name,nr+1);
457 (*gn)[block->nr-1]=strdup(buf);
459 if (block->nra == max) {
460 max+=20;
461 srenew(block->a,max);
463 block->a[block->nra]=a;
464 block->nra++;
466 block->index[block->nr]=block->nra;
469 static int split_chain(t_atoms *atoms,rvec *x,
470 int sel_nr,t_block *block,char ***gn)
472 char buf[STRLEN];
473 int j,nchain;
474 atom_id i,a,max,natoms,*start=NULL,*end=NULL,ca_start,ca_end;
475 rvec vec;
477 natoms=atoms->nr;
478 nchain=0;
479 ca_start=0;
481 while (ca_start<natoms) {
482 while((ca_start<natoms) && strcmp(*atoms->atomname[ca_start],"CA"))
483 ca_start++;
484 if (ca_start<natoms) {
485 srenew(start,nchain+1);
486 srenew(end,nchain+1);
487 start[nchain]=ca_start;
488 while ((start[nchain]>0) &&
489 (atoms->atom[start[nchain]-1].resnr==atoms->atom[ca_start].resnr))
490 start[nchain]--;
492 i=ca_start;
493 do {
494 ca_end=i;
495 do {
496 i++;
497 } while ((i<natoms) && strcmp(*atoms->atomname[i],"CA"));
498 if (i<natoms)
499 rvec_sub(x[ca_end],x[i],vec);
500 } while ((i<natoms) && (norm(vec)<0.45));
502 end[nchain]=ca_end;
503 while ((end[nchain]+1<natoms) &&
504 (atoms->atom[end[nchain]+1].resnr==atoms->atom[ca_end].resnr))
505 end[nchain]++;
506 ca_start=end[nchain]+1;
507 nchain++;
510 if (nchain==1)
511 printf("Found 1 chain, will not split\n");
512 else
513 printf("Found %d chains\n",nchain);
514 for (j=0; j<nchain; j++)
515 printf("%d:%6u atoms (%u to %u)\n",
516 j+1,end[j]-start[j]+1,start[j]+1,end[j]+1);
518 if (nchain>1) {
519 for (j=0; j<nchain; j++) {
520 block->nr++;
521 srenew(block->index,block->nr+1);
522 srenew(*gn,block->nr);
523 sprintf(buf,"%s_chain%d",(*gn)[sel_nr],j+1);
524 (*gn)[block->nr-1]=strdup(buf);
525 max=block->nra;
526 for (i=block->index[sel_nr]; i<block->index[sel_nr+1]; i++) {
527 a=block->a[i];
528 if ((a>=start[j]) && (a<=end[j])) {
529 if (block->nra==max) {
530 max+=20;
531 srenew(block->a,max);
533 block->a[block->nra]=a;
534 block->nra++;
537 block->index[block->nr]=block->nra;
538 if (block->index[block->nr-1]==block->index[block->nr])
539 remove_group(block->nr-1,NOTSET,block,gn);
542 sfree(start);
543 sfree(end);
545 return nchain;
548 static bool parse_entry(char **string,t_atoms *atoms,
549 t_block *block,char ***gn,
550 atom_id *nr,atom_id *index,char *gname)
552 static char **names;
553 static int namelen=5;
554 static bool bFirst=TRUE;
555 int j,n_names,sel_nr1;
556 atom_id i,nr1,*index1;
557 bool bRet,bCompl;
559 if (bFirst) {
560 bFirst=FALSE;
561 snew(names,MAXNAMES);
562 for (i=0; i<MAXNAMES; i++)
563 snew(names[i],namelen);
566 bRet=FALSE;
567 sel_nr1=NOTSET;
569 while(*string[0]==' ')
570 (*string)++;
572 if ((*string)[0]=='!') {
573 bCompl=TRUE;
574 (*string)++;
575 while(*string[0]==' ')
576 (*string)++;
577 } else
578 bCompl=FALSE;
580 if (parse_int(string,&sel_nr1)) {
581 if ((sel_nr1>=0) && (sel_nr1<block->nr)) {
582 copy_group(sel_nr1,block,nr,index);
583 strcpy(gname,(*gn)[sel_nr1]);
584 printf("Copied index group %d\n",sel_nr1);
585 bRet=TRUE;
586 } else
587 printf("Group %d does not exist\n",sel_nr1);
589 else if ((*string)[0]=='a') {
590 (*string)++;
591 if (parse_int(string,&sel_nr1)) {
592 bRet=select_atomnumbers(string,atoms,sel_nr1,nr,index,gname);
594 else if (parse_names(string,&n_names,names)) {
595 bRet=select_atomnames(atoms,n_names,names,nr,index);
596 make_gname(n_names,names,gname);
599 else if ((*string)[0]=='r') {
600 (*string)++;
601 if (parse_int(string,&sel_nr1)) {
602 bRet=select_residuenumbers(string,atoms,sel_nr1,nr,index,gname);
604 else if (parse_names(string,&n_names,names)) {
605 bRet=select_residuenames(atoms,n_names,names,nr,index);
606 make_gname(n_names,names,gname);
609 else if (!strncmp(*string,"chain",5)) {
610 (*string)+=5;
611 if (parse_names(string,&n_names,names)) {
612 bRet=select_chainnames(atoms,n_names,names,nr,index);
613 sprintf(gname,"ch%s",names[0]);
614 for (i=1; i<n_names; i++)
615 strcat(gname,names[i]);
618 if (bRet && bCompl) {
619 snew(index1,atoms->nr-*nr);
620 nr1=0;
621 for(i=0; i<atoms->nr; i++) {
622 j=0;
623 while ((j<*nr) && (index[j] != i))
624 j++;
625 if (j==*nr) {
626 if (nr1 >= atoms->nr-*nr) {
627 printf("There are double atoms in your index group\n");
628 break;
630 index1[nr1]=i;
631 nr1++;
634 *nr=nr1;
635 for(i=0; i<nr1; i++)
636 index[i]=index1[i];
637 sfree(index1);
639 for (i=strlen(gname); i>0; i--)
640 gname[i]=gname[i-1];
641 gname[0]='!';
642 printf("Complemented group: %u atoms\n",*nr);
645 return bRet;
648 static void list_residues(t_atoms *atoms)
650 int i,j,start,end,prev_resnr,resnr;
651 bool bDiff;
653 /* Print all the residues, assuming continuous resnr count */
654 start = atoms->atom[0].resnr;
655 prev_resnr = start;
656 for(i=0; i<atoms->nr; i++) {
657 resnr = atoms->atom[i].resnr;
658 if ((resnr != prev_resnr) || (i==atoms->nr-1)) {
659 if ((bDiff=strcmp(*atoms->resname[resnr],*atoms->resname[start])) ||
660 (i==atoms->nr-1)) {
661 if (bDiff)
662 end = prev_resnr;
663 else
664 end = resnr;
665 if (end < start+3)
666 for(j=start; j<=end; j++)
667 printf("%4d %-5s",j+1,*(atoms->resname[j]));
668 else
669 printf(" %4d - %4d %-5s ",start+1,end+1,*(atoms->resname[start]));
670 start = resnr;
673 prev_resnr = resnr;
675 printf("\n");
678 static void edit_index(t_atoms *atoms,rvec *x,t_block *block, char ***gn)
680 static char **atnames;
681 static bool bFirst=TRUE;
682 static int namelen=5;
683 char inp_string[STRLEN],*string,*atom_name;
684 char gname[STRLEN],gname1[STRLEN],gname2[STRLEN];
685 int i,sel_nr,sel_nr2;
686 atom_id nr,nr1,nr2,*index,*index1,*index2;
687 bool bCompl,bAnd,bOr;
689 if (bFirst) {
690 bFirst=FALSE;
691 snew(atnames,MAXNAMES);
692 for (i=0; i<MAXNAMES; i++)
693 snew(atnames[i],namelen);
696 string=NULL;
698 snew(index,atoms->nr);
699 snew(index1,atoms->nr);
700 snew(index2,atoms->nr);
702 do {
703 gname1[0]='\0';
704 printf("\n");
705 for(i=0; (i<block->nr); i++)
706 printf("%3d %-20s: %5u atoms\n",i,(*gn)[i],
707 block->index[i+1]-block->index[i]);
709 printf("\n");
710 printf(" nr : group ! 'name' nr name 'splitch' nr 'l': list residues\n");
711 printf(" 'a': atom & 'del' nr 'splitres' nr 'h': help\n");
712 printf(" 'r': residue | 'keep' nr 'splitat' nr\n");
713 printf(" 'chain' char 'case': %s 'q': save and quit\n",
714 bCase ? "case insensitive" : "case sensitive ");
715 printf("\n> ");
716 fgets(inp_string,STRLEN,stdin);
717 inp_string[strlen(inp_string)-1]=0;
718 printf("\n");
719 string=inp_string;
720 while (string[0]==' ')
721 string++;
723 nr=0;
724 if (string[0] == 'h') {
725 printf(" nr : selects an index group.\n");
726 printf(" 'a' nr1 [nr2 ...] : selects atoms, atom numbering starts at 1.\n");
727 printf(" 'a' nr1 - nr2 : selects atoms in the range from nr1 to nr2.\n");
728 printf(" 'a' name1[*] [name2[*] ...] : selects atoms by name(s), wildcard allowed\n");
729 printf(" at the end of a name.\n");
730 printf(" 'r' : analogous to 'a', but for residues.\n");
731 printf(" 'chain' ch1 [ch2 ...] : selects atoms by chain identifier(s),\n");
732 printf(" not available with a .gro file as input.\n");
733 printf(" ! : takes the complement of a group with respect to all\n");
734 printf(" the atoms in the input file.\n");
735 printf(" & | : AND and OR, can be placed between any of the options\n");
736 printf(" above, the input is processed from left to right.\n");
737 printf(" 'name' nr name : rename group nr to name.\n");
738 printf(" 'del' nr1 [- nr2] : deletes one group or groups in the range from nr1 to nr2.\n");
739 printf(" 'keep' nr : deletes all groups except nr.\n");
740 printf(" 'case' : make all name compares case (in)sensitive.\n");
741 printf(" 'splitch' nr : split group into chains using CA distances.\n");
742 printf(" 'splitres' nr : split group into residues.\n");
743 printf(" 'splitat' nr : split group into atoms.\n");
744 printf(" 'l' : list the residues.\n");
745 printf(" 'h' : show this help.\n");
746 printf(" 'q' : save and quit.\n");
747 printf("\n");
748 printf(" Examples:\n");
749 printf(" > 2 | 4 & r 3-5\n");
750 printf(" will select all atoms from group 2 and 4 which have residue numbers\n 3, 4 or 5\n");
751 printf(" > a C* & !a C CA\n");
752 printf(" will select all atoms starting with 'C' but not the atoms 'C' and 'CA'\n");
753 printf("\npress Enter");
754 getchar();
756 else if (!strncmp(string,"del",3)) {
757 string+=3;
758 if (parse_int(&string,&sel_nr)) {
759 while(string[0]==' ')
760 string++;
761 if (string[0]=='-') {
762 string++;
763 parse_int(&string,&sel_nr2);
764 } else
765 sel_nr2=NOTSET;
766 while(string[0]==' ')
767 string++;
768 if (string[0]=='\0')
769 remove_group(sel_nr,sel_nr2,block,gn);
770 else
771 printf("\nSyntax error: \"%s\"\n",string);
773 } else if (!strncmp(string,"keep",4)) {
774 string+=4;
775 if (parse_int(&string,&sel_nr)) {
776 remove_group(sel_nr+1,block->nr-1,block,gn);
777 remove_group(0,sel_nr-1,block,gn);
779 } else if (!strncmp(string,"name",4)) {
780 string+=4;
781 if (parse_int(&string,&sel_nr)) {
782 if ((sel_nr>=0) && (sel_nr<block->nr)) {
783 sscanf(string,"%s",gname);
784 sfree((*gn)[sel_nr]);
785 (*gn)[sel_nr]=strdup(gname);
788 } else if (!strncmp(string,"case",4)) {
789 bCase=!bCase;
790 } else if (string[0] == 'l')
791 list_residues(atoms);
792 else if (!strncmp(string,"splitch",7)) {
793 string+=7;
794 if (parse_int(&string,&sel_nr))
795 if ((sel_nr>=0) && (sel_nr<block->nr))
796 split_chain(atoms,x,sel_nr,block,gn);
797 } else if (!strncmp(string,"splitres",8)) {
798 string+=8;
799 if (parse_int(&string,&sel_nr))
800 if ((sel_nr>=0) && (sel_nr<block->nr))
801 split_group(atoms,sel_nr,block,gn,FALSE);
802 } else if (!strncmp(string,"splitat",7)) {
803 string+=7;
804 if (parse_int(&string,&sel_nr))
805 if ((sel_nr>=0) && (sel_nr<block->nr))
806 split_group(atoms,sel_nr,block,gn,TRUE);
807 } else if (string[0] != 'q') {
808 nr1=-1;
809 nr2=-1;
810 if (parse_entry(&string,atoms,block,gn,&nr,index,gname)) {
811 do {
812 while (string[0]==' ')
813 string++;
815 bAnd=FALSE;
816 bOr=FALSE;
817 if (string[0]=='&')
818 bAnd=TRUE;
819 else if (string[0]=='|')
820 bOr=TRUE;
822 if (bAnd || bOr) {
823 string++;
824 nr1=nr;
825 for(i=0; i<nr; i++)
826 index1[i]=index[i];
827 strcpy(gname1,gname);
828 if (parse_entry(&string,atoms,block,gn,&nr2,index2,gname2)) {
829 if (bOr) {
830 or_groups(nr1,index1,nr2,index2,&nr,index);
831 sprintf(gname,"%s_%s",gname1,gname2);
833 else {
834 and_groups(nr1,index1,nr2,index2,&nr,index);
835 sprintf(gname,"%s_&_%s",gname1,gname2);
839 } while (bAnd || bOr);
841 while(string[0]==' ')
842 string++;
843 if (string[0])
844 printf("\nSyntax error: \"%s\"\n",string);
845 else if (nr>0) {
846 copy2block(nr,index,block);
847 srenew(*gn,block->nr);
848 (*gn)[block->nr-1]=strdup(gname);
850 else
851 printf("Group is empty\n");
853 } while (string[0]!='q');
855 sfree(index);
856 sfree(index1);
857 sfree(index2);
860 int main(int argc,char *argv[])
862 static char *desc[] = {
863 "Index groups are necessary for almost every gromacs program.",
864 "All these programs can generate default index groups. You ONLY",
865 "have to use make_ndx when you need SPECIAL index groups.",
866 "There is a default index group for the whole system, 9 default",
867 "index groups are generated for proteins, a default index group",
868 "is generated for every other residue name.[PAR]"
869 "When no index file is supplied, also make_ndx will generate the",
870 "default groups.",
871 "With the index editor you can select on atom, residue and chain names",
872 "and numbers, you can use NOT, AND and OR, you can split groups",
873 "into chains, residues or atoms. You can delete and rename groups.[PAR]",
874 "The atom numbering in the editor and the index file starts at 1."
877 char title[STRLEN];
878 t_atoms atoms;
879 rvec *x,*v;
880 matrix box;
881 t_block *block;
882 char **gnames;
883 t_filenm fnm[] = {
884 { efSTX, "-f", NULL, ffREAD },
885 { efNDX, "-n", "in", ffOPTRD },
886 { efNDX, "-o", NULL, ffWRITE }
888 #define NFILE asize(fnm)
890 CopyRight(stdout,argv[0]);
892 parse_common_args(&argc,argv,0,FALSE,NFILE,fnm,0,NULL,asize(desc),
893 desc,0,NULL);
895 get_stx_coordnum(ftp2fn(efSTX,NFILE,fnm),&(atoms.nr));
896 init_t_atoms(&atoms,atoms.nr,TRUE);
897 snew(x,atoms.nr);
898 snew(v,atoms.nr);
899 fprintf(stderr,"\nReading structure file\n");
900 read_stx_conf(ftp2fn(efSTX,NFILE,fnm),title,&atoms,x,v,box);
902 if (opt2bSet("-n",NFILE,fnm))
903 block = init_index(opt2fn("-n",NFILE,fnm),&gnames);
904 else {
905 block = new_block();
906 snew(gnames,1);
907 analyse(&atoms,block,&gnames,FALSE,TRUE);
910 edit_index(&atoms,x,block,&gnames);
912 write_index(opt2fn("-o",NFILE,fnm),block,gnames);
914 thanx(stdout);
916 return 0;