static struct chain * merge_chains(struct chain *a, int nr_a, struct chain *b, int nr_b, enum field field) { struct chain *chain; struct chain *final; struct chain **next = &final; int i; if (!a) return b; if (!b) return a; for (i = 0, chain = a; chain; i++, chain = next_ptr(chain, field)) ; if (i != nr_a) die("WTF %d %d", i, nr_a); chain = split_chain(a, nr_a, field); a = merge_chains(chain, nr_a / 2, a, (nr_a + 1) / 2, field); chain = split_chain(b, nr_b, field); b = merge_chains(chain, nr_b / 2, b, (nr_b + 1) / 2, field); while (a && b) { if (a->count > b->count) { *next = a; if (field == NEXT_PTR) next = &a->next; else next = &a->sibling; a = *next; *next = NULL; } else { *next = b; if (field == NEXT_PTR) next = &b->next; else next = &b->sibling; b = *next; *next = NULL; } } if (a) *next = a; else *next = b; return final; }
static void sort_chains(void) { struct chain *chain; chain = split_chain(chains, nr_chains, NEXT_PTR); /* The original always has more or equal to the split */ chains = merge_chains(chain, nr_chains / 2, chains, (nr_chains + 1) / 2, NEXT_PTR); for (chain = chains; chain; chain = chain->next) sort_chain_parents(chain); }
static void sort_chain_parents(struct chain *chain) { struct chain *parent; parent = split_chain(chain->parents, chain->nr_parents, SIB_PTR); chain->parents = merge_chains(parent, chain->nr_parents / 2, chain->parents, (chain->nr_parents + 1) / 2, SIB_PTR); for (chain = chain->parents; chain; chain = chain->sibling) sort_chain_parents(chain); }
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] = 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] = strdup(gname); } else { printf("Group is empty\n"); } } } while (string[0] != 'q'); sfree(index); sfree(index1); sfree(index2); }