4 * This source code is part of
8 * GROningen MAchine for Chemical Simulations
11 * Written by David van der Spoel, Erik Lindahl, Berk Hess, and others.
12 * Copyright (c) 1991-2000, University of Groningen, The Netherlands.
13 * Copyright (c) 2001-2004, The GROMACS development team,
14 * check out http://www.gromacs.org for more information.
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.
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.
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.
31 * For more info, check our website at http://www.gromacs.org
34 * GROningen Mixture of Alchemy and Childrens' Stories
56 typedef enum { etOther
, etProt
, etDNA
, erestNR
} eRestp
;
57 static const char *ResTP
[erestNR
] = { "OTHER", "PROTEIN", "DNA" };
59 static const char *Sugars
[] = { "A", "T", "G", "C", "U" };
60 #define NDNA asize(Sugars)
62 static bool yn(bool bASK
)
68 c
=toupper(fgetc(stdin
));
69 } while ((c
!= 'Y') && (c
!= 'N'));
77 t_block
*new_block(void)
87 void write_index(char *outf
, t_block
*b
,char **gnames
)
93 /* fprintf(out,"%5d %5d\n",b->nr,b->nra); */
94 for(i
=0; (i
<b
->nr
); i
++) {
95 fprintf(out
,"[ %s ]\n",gnames
[i
]);
96 for(k
=0,j
=b
->index
[i
]; j
<b
->index
[i
+1]; j
++,k
++) {
97 fprintf(out
,"%4d ",b
->a
[j
]+1);
106 void add_grp(t_block
*b
,char ***gnames
,int nra
,atom_id a
[],const char *name
)
110 srenew(b
->index
,b
->nr
+2);
111 srenew(*gnames
,b
->nr
+1);
112 (*gnames
)[b
->nr
]=strdup(name
);
114 srenew(b
->a
,b
->nra
+nra
);
115 for(i
=0; (i
<nra
); i
++)
118 b
->index
[b
->nr
]=b
->nra
;
121 /* compare index in `a' with group in `b' at `index',
122 when `index'<0 it is relative to end of `b' */
123 static bool grp_cmp(t_block
*b
, int nra
, atom_id a
[], int index
)
128 index
= b
->nr
-1+index
;
130 fatal_error(0,"no such index group %d in t_block (nr=%d)",index
,b
->nr
);
132 if ( nra
!= b
->index
[index
+1] - b
->index
[index
] )
135 if ( a
[i
] != b
->a
[b
->index
[index
]+i
] )
140 static void p_status(int nres
,eRestp restp
[],bool bVerb
)
142 int i
,j
,ntp
[erestNR
];
144 for(i
=0; (i
<erestNR
); i
++)
146 for(j
=0; (j
<nres
); j
++)
150 for(i
=0; (i
<erestNR
); i
++)
151 printf("There are: %5d %10s residues\n",ntp
[i
],ResTP
[i
]);
154 atom_id
*mk_aid(t_atoms
*atoms
,eRestp restp
[],eRestp res
,int *nra
,
156 /* Make an array of atom_ids for all atoms with:
157 * (restp[i] == res) == bTrue
165 for(i
=0; (i
<atoms
->nr
); i
++)
166 if ((restp
[atoms
->atom
[i
].resnr
] == res
) == bTrue
)
172 static void analyse_other(eRestp Restp
[],t_atoms
*atoms
,
173 t_block
*gb
,char ***gn
,bool bASK
,bool bVerb
)
178 atom_id
*other_ndx
,*aid
,*aaid
;
179 int i
,j
,k
,l
,resnr
,naid
,naaid
,natp
,nrestp
=0;
181 for(i
=0; (i
<atoms
->nres
); i
++)
182 if (Restp
[i
] == etOther
)
184 if (i
< atoms
->nres
) {
187 printf("Analysing Other...\n");
188 snew(other_ndx
,atoms
->nr
);
189 for(k
=0; (k
<atoms
->nr
); k
++) {
190 resnr
=atoms
->atom
[k
].resnr
;
191 rname
=*atoms
->resname
[resnr
];
192 if (Restp
[resnr
] == etOther
) {
193 for(l
=0; (l
<nrestp
); l
++)
194 if (strcmp(restp
[l
],rname
) == 0)
197 srenew(restp
,++nrestp
);
198 restp
[nrestp
-1]=strdup(rname
);
202 for(i
=0; (i
<nrestp
); i
++) {
205 for(j
=0; (j
<atoms
->nr
); j
++) {
206 rname
=*atoms
->resname
[atoms
->atom
[j
].resnr
];
207 if (strcmp(restp
[i
],rname
) == 0)
210 add_grp(gb
,gn
,naid
,aid
,restp
[i
]);
212 printf("split %s into atoms (y/n) ? ",restp
[i
]);
216 for(k
=0; (k
<naid
); k
++) {
217 aname
=*atoms
->atomname
[aid
[k
]];
218 for(l
=0; (l
<natp
); l
++)
219 if (strcmp(aname
,attp
[l
]) == 0)
227 for(l
=0; (l
<natp
); l
++) {
230 for(k
=0; (k
<naid
); k
++) {
231 aname
=*atoms
->atomname
[aid
[k
]];
232 if (strcmp(aname
,attp
[l
])==0)
233 aaid
[naaid
++]=aid
[k
];
235 add_grp(gb
,gn
,naaid
,aaid
,attp
[l
]);
249 static void analyse_prot(eRestp restp
[],t_atoms
*atoms
,
250 t_block
*gb
,char ***gn
,bool bASK
,bool bVerb
)
252 /* atomnames to be used in constructing index groups: */
253 const char *pnoh
[] = { "H" };
254 const char *pnodum
[] = { "MN1", "MN2", "MCB1", "MCB2", "MCG1", "MCG2",
255 "MCD1", "MCD2", "MCE1", "MCE2", "MNZ1", "MNZ2" };
256 const char *calpha
[] = { "CA" };
257 const char *bb
[] = { "N","CA","C" };
258 const char *mc
[] = { "N","CA","C","O","O1","O2","OXT" };
259 const char *mcb
[] = { "N","CA","CB","C","O","O1","O2","OT","OXT" };
260 const char *mch
[] = { "N","CA","C","O","O1","O2","OT","OXT",
261 "H1","H2","H3","H" };
262 /* array of arrays of atomnames: */
263 const char **chains
[] = { NULL
,pnoh
,calpha
,bb
,mc
,mcb
,mch
,mch
,mch
,pnodum
};
264 #define NCH asize(chains)
265 /* array of sizes of arrays of atomnames: */
266 const int sizes
[NCH
] = {
267 0, asize(pnoh
), asize(calpha
), asize(bb
),
268 asize(mc
), asize(mcb
), asize(mch
), asize(mch
), asize(mch
), asize(pnodum
)
270 /* descriptive names of index groups */
271 const char *ch_name
[NCH
] = {
272 "Protein", "Protein-H", "C-alpha", "Backbone",
273 "MainChain", "MainChain+Cb", "MainChain+H", "SideChain", "SideChain-H",
276 /* construct index group containing (TRUE) or excluding (FALSE)
278 const bool complement
[NCH
] = {
279 TRUE
, TRUE
, FALSE
, FALSE
, FALSE
, FALSE
, FALSE
, TRUE
, TRUE
, TRUE
281 const int wholename
[NCH
] = { -1, 0,-1,-1,-1,-1,-1,-1, 11,-1 };
282 /* the index in wholename gives the first item in the arrays of
283 * atomtypes that should be tested with 'strncasecmp' in stead of
284 * strcasecmp, or -1 if all items should be tested with strcasecmp
285 * This is comparable to using a '*' wildcard at the end of specific
286 * atom names, but that is more involved to implement...
288 /* only add index group if it differs from the specified one,
289 specify -1 to always add group */
290 const int compareto
[NCH
] = { -1,-1,-1,-1,-1,-1,-1,-1,-1, 0 };
294 int nra
,nnpres
,npres
;
296 char ndx_name
[STRLEN
],*atnm
;
299 printf("Analysing Protein...\n");
302 /* calculate the number of protein residues */
304 for(i
=0; (i
<atoms
->nres
); i
++)
305 if (restp
[i
] == etProt
)
308 /* find matching or complement atoms */
309 for(i
=0; (i
<NCH
); i
++) {
311 for(n
=0; (n
<atoms
->nr
); n
++) {
312 if (restp
[atoms
->atom
[n
].resnr
] == etProt
) {
314 for(j
=0; (j
<sizes
[i
]); j
++) {
315 /* skip digits at beginning of atomname, e.g. 1H */
316 atnm
=*atoms
->atomname
[n
];
317 while (isdigit(atnm
[0]))
319 if ( (wholename
[i
]==-1) || (j
<wholename
[i
]) ) {
320 if (strcasecmp(chains
[i
][j
],atnm
) == 0)
323 if (strncasecmp(chains
[i
][j
],atnm
,strlen(chains
[i
][j
])) == 0)
327 if (match
!= complement
[i
])
331 /* if we want to add this group always or it differs from previous
333 if ( compareto
[i
] == -1 || !grp_cmp(gb
,nra
,aid
,compareto
[i
]-i
) )
334 add_grp(gb
,gn
,nra
,aid
,ch_name
[i
]);
338 for(i
=0; (i
<NCH
); i
++) {
339 printf("Split %12s into %5d residues (y/n) ? ",ch_name
[i
],npres
);
343 for(n
=0;((atoms
->atom
[n
].resnr
<npres
) && (n
<atoms
->nr
));) {
344 resnr
= atoms
->atom
[n
].resnr
;
345 for(;((atoms
->atom
[n
].resnr
==resnr
) && (n
<atoms
->nr
));n
++) {
347 for(j
=0;(j
<sizes
[i
]); j
++)
348 if (strcasecmp(chains
[i
][j
],*atoms
->atomname
[n
]) == 0)
350 if (match
!= complement
[i
])
353 /* copy the residuename to the tail of the groupname */
355 sprintf(ndx_name
,"%s_%s%d",
356 ch_name
[i
],*atoms
->resname
[resnr
],resnr
+1);
357 add_grp(gb
,gn
,nra
,aid
,ndx_name
);
363 printf("Make group with sidechain and C=O swapped (y/n) ? ");
365 /* Make swap sidechain C=O index */
368 for(n
=0;((atoms
->atom
[n
].resnr
<npres
) && (n
<atoms
->nr
));) {
369 resnr
= atoms
->atom
[n
].resnr
;
371 for(;((atoms
->atom
[n
].resnr
==resnr
) && (n
<atoms
->nr
));n
++)
372 if (strcmp("CA",*atoms
->atomname
[n
]) == 0) {
376 } else if (strcmp("C",*atoms
->atomname
[n
]) == 0) {
379 } else if (strcmp("O",*atoms
->atomname
[n
]) == 0) {
382 } else if (strcmp("O1",*atoms
->atomname
[n
]) == 0) {
388 /* copy the residuename to the tail of the groupname */
390 add_grp(gb
,gn
,nra
,aid
,"SwapSC-CO");
398 static void analyse_dna(eRestp restp
[],t_atoms
*atoms
,
399 t_block
*gb
,char ***gn
,bool bASK
,bool bVerb
)
402 printf("Analysing DNA... (not really)\n");
404 printf("eRestp %p; atoms %p; gb %p; gn %p; bASK %s; bASK %s",
405 (void *)restp
, (void *)atoms
, (void *)gb
, (void *)gn
,
406 bool_names
[bASK
], bool_names
[bVerb
]);
409 t_aa_names
*get_aa_names(void)
411 /* Read the database in aminoacids.dat */
416 aan
->n
= get_strings("aminoacids.dat",&(aan
->aa
));
417 /* qsort(aan->aa,aan->n,sizeof(aan->aa[0]),strcmp);*/
422 bool is_protein(t_aa_names
*aan
,char *resnm
)
424 /* gives true if resnm occurs in aminoacids.dat */
427 for(i
=0; (i
<aan
->n
); i
++)
428 if (strcasecmp(aan
->aa
[i
],resnm
) == 0)
434 void done_aa_names(t_aa_names
**aan
)
439 for(i
=0; (i
<(*aan
)->n
); i
++)
440 sfree((*aan
)->aa
[i
]);
446 void analyse(t_atoms
*atoms
,t_block
*gb
,char ***gn
,bool bASK
,bool bVerb
)
456 printf("Analysing residue names:\n");
457 snew(restp
,atoms
->nres
);
458 aid
=mk_aid(atoms
,restp
,etOther
,&nra
,TRUE
);
459 add_grp(gb
,gn
,nra
,aid
,"System");
462 aan
= get_aa_names();
463 for(i
=0; (i
<atoms
->nres
); i
++) {
464 resnm
=*atoms
->resname
[i
];
465 if ((restp
[i
] == etOther
) && is_protein(aan
,resnm
))
467 if (restp
[i
] == etOther
)
468 for(j
=0; (j
<NDNA
); j
++) {
469 if (strcasecmp(Sugars
[j
],resnm
) == 0)
473 p_status(atoms
->nres
,restp
,bVerb
);
477 aid
=mk_aid(atoms
,restp
,etProt
,&nra
,TRUE
);
479 analyse_prot(restp
,atoms
,gb
,gn
,bASK
,bVerb
);
484 aid
=mk_aid(atoms
,restp
,etProt
,&nra
,FALSE
);
485 if ((nra
> 0) && (nra
< atoms
->nr
))
486 add_grp(gb
,gn
,nra
,aid
,"Non-Protein");
490 aid
=mk_aid(atoms
,restp
,etDNA
,&nra
,TRUE
);
492 add_grp(gb
,gn
,nra
,aid
,"DNA");
493 analyse_dna(restp
,atoms
,gb
,gn
,bASK
,bVerb
);
498 analyse_other(restp
,atoms
,gb
,gn
,bASK
,bVerb
);
499 aid
=mk_aid(atoms
,restp
,etOther
,&nra
,TRUE
);
500 if ((nra
> 0) && (nra
< atoms
->nr
))
501 add_grp(gb
,gn
,nra
,aid
,"Other");
506 void check_index(char *gname
,int n
,atom_id index
[],char *traj
,int natoms
)
511 if (index
[i
] >= natoms
)
512 fatal_error(0,"%s atom number (index[%d]=%d) is larger than the number of atoms in %s (%d)",
513 gname
? gname
: "Index",i
+1, index
[i
]+1,
514 traj
? traj
: "the trajectory",natoms
);
517 t_block
*init_index(char *gfile
, char ***grpname
)
523 char line
[STRLEN
],*pt
,str
[STRLEN
];
525 in
=ffopen(gfile
,"r");
527 get_a_line(in
,line
,STRLEN
);
528 if ( line
[0]=='[' ) {
537 if (get_header(line
,str
)) {
539 srenew(b
->index
,b
->nr
+1);
540 srenew(*grpname
,b
->nr
);
543 b
->index
[b
->nr
]=b
->index
[b
->nr
-1];
544 (*grpname
)[b
->nr
-1]=strdup(str
);
547 while ((i
=sscanf(pt
,"%s",str
)) == 1) {
551 srenew(b
->a
,maxentries
);
556 pt
=strstr(pt
,str
)+strlen(str
);
559 } while (get_a_line(in
,line
,STRLEN
));
563 sscanf(line
,"%d%d",&b
->nr
,&b
->nra
);
564 snew(b
->index
,b
->nr
+1);
565 snew(*grpname
,b
->nr
);
568 for (i
=0; (i
<b
->nr
); i
++) {
569 fscanf(in
,"%s%d",str
,&ng
);
570 (*grpname
)[i
]=strdup(str
);
571 b
->index
[i
+1]=b
->index
[i
]+ng
;
572 if (b
->index
[i
+1] > b
->nra
)
573 fatal_error(0,"Something wrong in your indexfile at group %s",str
);
574 for(j
=0; (j
<ng
); j
++) {
576 b
->a
[b
->index
[i
]+j
]=a
;
585 static void minstring(char *str
)
589 for (i
=0; (i
< (int)strlen(str
)); i
++)
594 int find_group(char s
[], int ngrps
, char **grpname
)
603 /* first look for whole name match */
605 for(i
=0; i
<ngrps
; i
++)
606 if (strcasecmp_min(s
,grpname
[i
])==0) {
611 /* second look for first string match */
613 for(i
=0; i
<ngrps
; i
++)
614 if (strncasecmp_min(s
,grpname
[i
],n
)==0) {
619 /* last look for arbitrary substring match */
623 for(i
=0; i
<ngrps
; i
++) {
624 strcpy(string
, grpname
[i
]);
627 if (strstr(s
,string
)!=NULL
) {
635 printf("Error: Multiple groups '%s' selected\n", s
);
641 static int qgroup(int *a
, int ngrps
, char **grpname
)
648 fprintf(stderr
,"Select a group: ");
650 if ( scanf("%s",s
)!=1 )
651 fatal_error(0,"Cannot read from input");
652 trim(s
); /* remove spaces */
653 } while (strlen(s
)==0);
655 if (aa
==0 && strcmp(s
,"0")!=0 ) /* string entered */
656 aa
= find_group(s
, ngrps
, grpname
);
657 bInRange
= aa
>=0 && aa
<ngrps
;
659 printf("Error: No such group '%s'\n", s
);
661 printf("Selected %d: '%s'\n", aa
, grpname
[aa
]);
666 static void rd_groups(t_block
*grps
,char **grpname
,char *gnames
[],
667 int ngrps
,int isize
[],atom_id
*index
[],int grpnr
[])
672 fatal_error(0,"Error: no groups in indexfile");
673 for(i
=0; (i
<grps
->nr
); i
++)
674 fprintf(stderr
,"Group %5d (%12s) has %5d elements\n",i
,grpname
[i
],
675 grps
->index
[i
+1]-grps
->index
[i
]);
676 for(i
=0; (i
<ngrps
); i
++) {
679 gnr1
=qgroup(&grpnr
[i
], grps
->nr
, grpname
);
680 if ((gnr1
<0) || (gnr1
>=grps
->nr
))
681 fprintf(stderr
,"Select between %d and %d.\n",0,grps
->nr
-1);
682 } while ((gnr1
<0) || (gnr1
>=grps
->nr
));
684 fprintf(stderr
,"There is one group in the index\n");
687 gnames
[i
]=strdup(grpname
[gnr1
]);
688 isize
[i
]=grps
->index
[gnr1
+1]-grps
->index
[gnr1
];
689 snew(index
[i
],isize
[i
]);
690 for(j
=0; (j
<isize
[i
]); j
++)
691 index
[i
][j
]=grps
->a
[grps
->index
[gnr1
]+j
];
695 void rd_index(char *statfile
,int ngrps
,int isize
[],
696 atom_id
*index
[],char *grpnames
[])
704 fatal_error(0,"No index file specified");
705 grps
=init_index(statfile
,&gnames
);
706 rd_groups(grps
,gnames
,grpnames
,ngrps
,isize
,index
,grpnr
);
709 void rd_index_nrs(char *statfile
,int ngrps
,int isize
[],
710 atom_id
*index
[],char *grpnames
[],int grpnr
[])
716 fatal_error(0,"No index file specified");
717 grps
=init_index(statfile
,&gnames
);
719 rd_groups(grps
,gnames
,grpnames
,ngrps
,isize
,index
,grpnr
);
722 void get_index(t_atoms
*atoms
, char *fnm
, int ngrps
,
723 int isize
[], atom_id
*index
[],char *grpnames
[])
732 grps
=init_index(fnm
,gnames
);
737 analyse(atoms
,grps
,gnames
,FALSE
,FALSE
);
739 rd_groups(grps
,*gnames
,grpnames
,ngrps
,isize
,index
,grpnr
);