static void edit_index(int natoms, t_atoms *atoms, rvec *x, t_blocka *block, char ***gn, gmx_bool bVerbose) { static char **atnames, *ostring; static gmx_bool bFirst = TRUE; char inp_string[STRLEN], *string; char gname[STRLEN], gname1[STRLEN], gname2[STRLEN]; int i, i0, i1, sel_nr, sel_nr2, newgroup; atom_id nr, nr1, nr2, *index, *index1, *index2; gmx_bool bAnd, bOr, bPrintOnce; if (bFirst) { bFirst = FALSE; snew(atnames, MAXNAMES); for (i = 0; i < MAXNAMES; i++) { snew(atnames[i], NAME_LEN+1); } } string = NULL; snew(index, natoms); snew(index1, natoms); snew(index2, natoms); newgroup = NOTSET; bPrintOnce = TRUE; do { gname1[0] = '\0'; if (bVerbose || bPrintOnce || newgroup != NOTSET) { printf("\n"); if (bVerbose || bPrintOnce || newgroup == NOTSET) { i0 = 0; i1 = block->nr; } else { i0 = newgroup; i1 = newgroup+1; } for (i = i0; i < i1; i++) { printf("%3d %-20s: %5d atoms\n", i, (*gn)[i], block->index[i+1]-block->index[i]); } newgroup = NOTSET; } if (bVerbose || bPrintOnce) { printf("\n"); printf(" nr : group ! 'name' nr name 'splitch' nr Enter: list groups\n"); printf(" 'a': atom & 'del' nr 'splitres' nr 'l': list residues\n"); printf(" 't': atom type | 'keep' nr 'splitat' nr 'h': help\n"); printf(" 'r': residue 'res' nr 'chain' char\n"); printf(" \"name\": group 'case': case %s 'q': save and quit\n", bCase ? "insensitive" : "sensitive "); printf(" 'ri': residue index\n"); bPrintOnce = FALSE; } printf("\n"); printf("> "); if (NULL == fgets(inp_string, STRLEN, stdin)) { gmx_fatal(FARGS, "Error reading user input"); } inp_string[strlen(inp_string)-1] = 0; printf("\n"); string = inp_string; while (string[0] == ' ') { string++; } ostring = string; nr = 0; if (string[0] == 'h') { printf(" nr : selects an index group by number or quoted string.\n"); printf(" The string is first matched against the whole group name,\n"); printf(" then against the beginning and finally against an\n"); printf(" arbitrary substring. A multiple match is an error.\n"); printf(" 'a' nr1 [nr2 ...] : selects atoms, atom numbering starts at 1.\n"); printf(" 'a' nr1 - nr2 : selects atoms in the range from nr1 to nr2.\n"); printf(" 'a' name1[*] [name2[*] ...] : selects atoms by name(s), '?' matches any char,\n"); printf(" wildcard '*' allowed at the end of a name.\n"); printf(" 't' type1[*] [type2[*] ...] : as 'a', but for type, run input file required.\n"); printf(" 'r' nr1[ic1] [nr2[ic2] ...] : selects residues by number and insertion code.\n"); printf(" 'r' nr1 - nr2 : selects residues in the range from nr1 to nr2.\n"); printf(" 'r' name1[*] [name2[*] ...] : as 'a', but for residue names.\n"); printf(" 'ri' nr1 - nr2 : selects residue indices, 1-indexed, (as opposed to numbers) in the range from nr1 to nr2.\n"); printf(" 'chain' ch1 [ch2 ...] : selects atoms by chain identifier(s),\n"); printf(" not available with a .gro file as input.\n"); printf(" ! : takes the complement of a group with respect to all\n"); printf(" the atoms in the input file.\n"); printf(" & | : AND and OR, can be placed between any of the options\n"); printf(" above, the input is processed from left to right.\n"); printf(" 'name' nr name : rename group nr to name.\n"); printf(" 'del' nr1 [- nr2] : deletes one group or groups in the range from nr1 to nr2.\n"); printf(" 'keep' nr : deletes all groups except nr.\n"); printf(" 'case' : make all name compares case (in)sensitive.\n"); printf(" 'splitch' nr : split group into chains using CA distances.\n"); printf(" 'splitres' nr : split group into residues.\n"); printf(" 'splitat' nr : split group into atoms.\n"); printf(" 'res' nr : interpret numbers in group as residue numbers\n"); printf(" Enter : list the currently defined groups and commands\n"); printf(" 'l' : list the residues.\n"); printf(" 'h' : show this help.\n"); printf(" 'q' : save and quit.\n"); printf("\n"); printf(" Examples:\n"); printf(" > 2 | 4 & r 3-5\n"); printf(" selects all atoms from group 2 and 4 that have residue numbers 3, 4 or 5\n"); printf(" > a C* & !a C CA\n"); printf(" selects all atoms starting with 'C' but not the atoms 'C' and 'CA'\n"); printf(" > \"protein\" & ! \"backb\"\n"); printf(" selects all atoms that are in group 'protein' and not in group 'backbone'\n"); if (bVerbose) { printf("\npress Enter "); getchar(); } } else if (strncmp(string, "del", 3) == 0) { string += 3; if (parse_int(&string, &sel_nr)) { while (string[0] == ' ') { string++; } if (string[0] == '-') { string++; parse_int(&string, &sel_nr2); } else { sel_nr2 = NOTSET; } while (string[0] == ' ') { string++; } if (string[0] == '\0') { remove_group(sel_nr, sel_nr2, block, gn); } else { printf("\nSyntax error: \"%s\"\n", string); } } } else if (strncmp(string, "keep", 4) == 0) { string += 4; if (parse_int(&string, &sel_nr)) { remove_group(sel_nr+1, block->nr-1, block, gn); remove_group(0, sel_nr-1, block, gn); } } else if (strncmp(string, "name", 4) == 0) { string += 4; if (parse_int(&string, &sel_nr)) { if ((sel_nr >= 0) && (sel_nr < block->nr)) { sscanf(string, "%s", gname); sfree((*gn)[sel_nr]); (*gn)[sel_nr] = gmx_strdup(gname); } } } else if (strncmp(string, "case", 4) == 0) { bCase = !bCase; printf("Switched to case %s\n", bCase ? "sensitive" : "insensitive"); } else if (string[0] == 'v') { bVerbose = !bVerbose; printf("Turned verbose %s\n", bVerbose ? "on" : "off"); } else if (string[0] == 'l') { if (check_have_atoms(atoms, ostring) ) { list_residues(atoms); } } else if (strncmp(string, "splitch", 7) == 0) { string += 7; if (check_have_atoms(atoms, ostring) && parse_int(&string, &sel_nr) && (sel_nr >= 0) && (sel_nr < block->nr)) { split_chain(atoms, x, sel_nr, block, gn); } } else if (strncmp(string, "splitres", 8) == 0) { string += 8; if (check_have_atoms(atoms, ostring) && parse_int(&string, &sel_nr) && (sel_nr >= 0) && (sel_nr < block->nr)) { split_group(atoms, sel_nr, block, gn, FALSE); } } else if (strncmp(string, "splitat", 7) == 0) { string += 7; if (check_have_atoms(atoms, ostring) && parse_int(&string, &sel_nr) && (sel_nr >= 0) && (sel_nr < block->nr)) { split_group(atoms, sel_nr, block, gn, TRUE); } } else if (string[0] == '\0') { bPrintOnce = TRUE; } else if (string[0] != 'q') { nr1 = -1; nr2 = -1; if (parse_entry(&string, natoms, atoms, block, gn, &nr, index, gname)) { do { while (string[0] == ' ') { string++; } bAnd = FALSE; bOr = FALSE; if (string[0] == '&') { bAnd = TRUE; } else if (string[0] == '|') { bOr = TRUE; } if (bAnd || bOr) { string++; nr1 = nr; for (i = 0; i < nr; i++) { index1[i] = index[i]; } strcpy(gname1, gname); if (parse_entry(&string, natoms, atoms, block, gn, &nr2, index2, gname2)) { if (bOr) { or_groups(nr1, index1, nr2, index2, &nr, index); sprintf(gname, "%s_%s", gname1, gname2); } else { and_groups(nr1, index1, nr2, index2, &nr, index); sprintf(gname, "%s_&_%s", gname1, gname2); } } } } while (bAnd || bOr); } while (string[0] == ' ') { string++; } if (string[0]) { printf("\nSyntax error: \"%s\"\n", string); } else if (nr > 0) { copy2block(nr, index, block); srenew(*gn, block->nr); newgroup = block->nr-1; (*gn)[newgroup] = gmx_strdup(gname); } else { printf("Group is empty\n"); } } } while (string[0] != 'q'); sfree(index); sfree(index1); sfree(index2); }
static bool parse_entry(char **string,int natoms,t_atoms *atoms, t_blocka *block,char ***gn, atom_id *nr,atom_id *index,char *gname) { static char **names, *ostring; static bool bFirst=TRUE; int j,n_names,sel_nr1; atom_id i,nr1,*index1; bool bRet,bCompl; if (bFirst) { bFirst=FALSE; snew(names,MAXNAMES); for (i=0; i<MAXNAMES; i++) snew(names[i],NAME_LEN+1); } bRet=FALSE; sel_nr1=NOTSET; while(*string[0]==' ') (*string)++; if ((*string)[0]=='!') { bCompl=TRUE; (*string)++; while(*string[0]==' ') (*string)++; } else bCompl=FALSE; ostring = *string; if (parse_int(string,&sel_nr1) || parse_string(string,&sel_nr1,block->nr,*gn)) { if ((sel_nr1>=0) && (sel_nr1<block->nr)) { copy_group(sel_nr1,block,nr,index); strcpy(gname,(*gn)[sel_nr1]); printf("Copied index group %d '%s'\n",sel_nr1,(*gn)[sel_nr1]); bRet=TRUE; } else printf("Group %d does not exist\n",sel_nr1); } else if ((*string)[0]=='a') { (*string)++; if (check_have_atoms(atoms, ostring)) { if (parse_int(string,&sel_nr1)) { bRet=select_atomnumbers(string,atoms,sel_nr1,nr,index,gname); } else if (parse_names(string,&n_names,names)) { bRet=select_atomnames(atoms,n_names,names,nr,index,FALSE); make_gname(n_names,names,gname); } } } else if ((*string)[0]=='t') { (*string)++; if (check_have_atoms(atoms, ostring) && parse_names(string,&n_names,names)) { if (atoms->atomtype == NULL) printf("Need a run input file to select atom types\n"); else { bRet=select_atomnames(atoms,n_names,names,nr,index,TRUE); make_gname(n_names,names,gname); } } } else if (strncmp(*string,"res",3)==0) { (*string)+=3; if ( check_have_atoms(atoms, ostring) && parse_int(string,&sel_nr1) && (sel_nr1>=0) && (sel_nr1<block->nr) ) { bRet=atoms_from_residuenumbers(atoms, sel_nr1,block,nr,index,(*gn)[sel_nr1]); sprintf(gname,"atom_%s",(*gn)[sel_nr1]); } } else if ((*string)[0]=='r') { (*string)++; if (check_have_atoms(atoms, ostring)) { if (parse_int(string,&sel_nr1)) { bRet=select_residuenumbers(string,atoms,sel_nr1,nr,index,gname); } else if (parse_names(string,&n_names,names)) { bRet=select_residuenames(atoms,n_names,names,nr,index); make_gname(n_names,names,gname); } } } else if (strncmp(*string,"chain",5)==0) { (*string)+=5; if (check_have_atoms(atoms, ostring) && parse_names(string,&n_names,names)) { bRet=select_chainnames(atoms,n_names,names,nr,index); sprintf(gname,"ch%s",names[0]); for (i=1; i<n_names; i++) strcat(gname,names[i]); } } if (bRet && bCompl) { snew(index1,natoms-*nr); nr1=0; for(i=0; i<natoms; i++) { j=0; while ((j<*nr) && (index[j] != i)) j++; if (j==*nr) { if (nr1 >= natoms-*nr) { printf("There are double atoms in your index group\n"); break; } index1[nr1]=i; nr1++; } } *nr=nr1; for(i=0; i<nr1; i++) index[i]=index1[i]; sfree(index1); for (i=strlen(gname)+1; i>0; i--) gname[i]=gname[i-1]; gname[0]='!'; printf("Complemented group: %u atoms\n",*nr); } return bRet; }