Skip to content

Commit

Permalink
Use long chain labels everywhere internally in structure.c.
Browse files Browse the repository at this point in the history
Add property short_labels to chains struct for backwards compatibility.

Related to #96
  • Loading branch information
mittinatten committed Dec 10, 2023
1 parent 7a6d0fe commit 2b60e2c
Showing 1 changed file with 56 additions and 27 deletions.
83 changes: 56 additions & 27 deletions src/structure.c
Expand Up @@ -27,6 +27,9 @@
#define ATOMS_CHUNK 512
#define RESIDUES_CHUNK 64
#define CHAINS_CHUNK 64
#define CHAIN_LABEL_LENGTH 3

typedef char chain_label_t[CHAIN_LABEL_LENGTH + 1];

struct atom {
char res_name[PDB_ATOM_RES_NAME_STRL + 1];
Expand All @@ -35,7 +38,7 @@ struct atom {
char symbol[PDB_ATOM_SYMBOL_STRL + 1];
char *line;
int res_index;
char chain_label[4];
chain_label_t chain_label;
freesasa_atom_class the_class;
};

Expand Down Expand Up @@ -67,7 +70,8 @@ struct residues {
struct chains {
int n;
int n_alloc;
char *labels; /* all chain labels found (as string) */
chain_label_t *labels;
char* short_labels; /* NULL-terminated string */
int *first_atom; /* first atom of each chain */
};

Expand Down Expand Up @@ -166,7 +170,7 @@ atom_new(const char *residue_name,
const char *residue_number,
const char *atom_name,
const char *symbol,
char chain_label)
chain_label_t chain_label)
{
struct atom *a = malloc(sizeof(struct atom));

Expand All @@ -176,15 +180,14 @@ atom_new(const char *residue_name,
} else {
*a = empty_atom;

a->line = NULL ;
a->chain_label[0] = chain_label;
a->chain_label[1] = '\0';
a->line = NULL;
a->res_index = -1;

strncpy(a->atom_name, atom_name, sizeof(a->atom_name));
strncpy(a->res_name, residue_name, sizeof(a->res_name));
strncpy(a->res_number, residue_number, sizeof(a->res_number));
strncpy(a->symbol, symbol, sizeof(a->symbol));
strncpy(a->chain_label, chain_label, sizeof(chain_label_t));

a->the_class = FREESASA_ATOM_UNKNOWN;
}
Expand All @@ -198,6 +201,7 @@ atom_new_from_line(const char *line,
{
char aname[PDB_ATOM_NAME_STRL + 1], rname[PDB_ATOM_RES_NAME_STRL + 1],
rnumber[PDB_ATOM_RES_NUMBER_STRL + 1], symbol[PDB_ATOM_SYMBOL_STRL + 1];
chain_label_t chain_label;
int flag;
struct atom *a;

Expand All @@ -208,13 +212,15 @@ atom_new_from_line(const char *line,
freesasa_pdb_get_atom_name(aname, line);
freesasa_pdb_get_res_name(rname, line);
freesasa_pdb_get_res_number(rnumber, line);
chain_label[0] = freesasa_pdb_get_chain_label(line);
chain_label[1] = '\0';

flag = freesasa_pdb_get_symbol(symbol, line);
if (flag == FREESASA_FAIL || (symbol[0] == ' ' && symbol[1] == ' ')) {
guess_symbol(symbol, aname);
}

a = atom_new(rname, rnumber, aname, symbol, freesasa_pdb_get_chain_label(line));
a = atom_new(rname, rnumber, aname, symbol, chain_label);

if (a != NULL) {
a->line = strdup(line);
Expand Down Expand Up @@ -301,6 +307,7 @@ chains_init(void)
ch.n_alloc = 0;
ch.first_atom = NULL;
ch.labels = NULL;
ch.short_labels = NULL;

return ch;
}
Expand All @@ -309,7 +316,7 @@ static int
chains_alloc(struct chains *chains)
{
int new_size;
void *fa, *lbl;
void *fa, *lbl, *short_lbl;

assert(chains);
assert(chains->n <= chains->n_alloc);
Expand All @@ -318,6 +325,7 @@ chains_alloc(struct chains *chains)
new_size = chains->n_alloc + CHAINS_CHUNK;
fa = chains->first_atom;
lbl = chains->labels;
short_lbl = chains->short_labels;

chains->first_atom = realloc(chains->first_atom,
sizeof(int) * new_size);
Expand All @@ -326,12 +334,18 @@ chains_alloc(struct chains *chains)
return mem_fail();
}

chains->labels = realloc(chains->labels, new_size + 1);
chains->labels = realloc(chains->labels, sizeof(chain_label_t) * new_size);
if (chains->labels == NULL) {
chains->labels = lbl;
return mem_fail();
}

chains->short_labels = realloc(chains->short_labels, new_size + 1);
if (chains->short_labels == NULL) {
chains->short_labels = short_lbl;
return mem_fail();
}

chains->n_alloc = new_size;
}
++chains->n;
Expand All @@ -344,6 +358,7 @@ chains_dealloc(struct chains *chains)
if (chains) {
free(chains->first_atom);
free(chains->labels);
free(chains->short_labels);
*chains = chains_init();
}
}
Expand Down Expand Up @@ -429,22 +444,30 @@ guess_symbol(char *symbol,
}
return FREESASA_SUCCESS;
}

int structure_has_chain(freesasa_structure *s, chain_label_t chain_label) {
for (int i = 0; i < s->chains.n; ++i) {
if (strncmp(s->chains.labels[i], chain_label, sizeof(chain_label_t)) == 0) {
return 1;
}
}
return 0;
}

static int
structure_add_chain(freesasa_structure *s,
char chain_label,
chain_label_t chain_label,
int i_latest_atom)
{
int n;
if (s->chains.n == 0 || strchr(s->chains.labels, chain_label) == NULL) {
if (s->chains.n == 0 || structure_has_chain(s, chain_label) == 0) {

if (chains_alloc(&s->chains) == FREESASA_FAIL)
return fail_msg("");

n = s->chains.n;
s->chains.labels[n - 1] = chain_label;
s->chains.labels[n] = '\0';

assert(strlen(s->chains.labels) == s->chains.n);
strncpy(s->chains.labels[n - 1], chain_label, sizeof(chain_label_t));
s->chains.short_labels[n - 1] = chain_label[0];

s->chains.first_atom[n - 1] = i_latest_atom;
}
Expand All @@ -466,7 +489,7 @@ structure_add_residue(freesasa_structure *s,
if (!(s->residues.n == 0 ||
(i_latest_atom > 0 &&
(strcmp(a->res_number, s->atoms.atom[i_latest_atom - 1]->res_number) ||
a->chain_label[0] != s->atoms.atom[i_latest_atom - 1]->chain_label[0])))) {
strcmp(a->chain_label, s->atoms.atom[i_latest_atom - 1]->chain_label))))) {
return FREESASA_SUCCESS;
}

Expand Down Expand Up @@ -595,7 +618,7 @@ structure_add_atom(freesasa_structure *structure,
return mem_fail();

/* Check if this is a new chain and if so add it */
if (structure_add_chain(structure, atom->chain_label[0], na - 1) == FREESASA_FAIL)
if (structure_add_chain(structure, atom->chain_label, na - 1) == FREESASA_FAIL)
return mem_fail();

/* Check if this is a new residue, and if so add it */
Expand Down Expand Up @@ -701,7 +724,7 @@ structure_add_atom_wopt_impl(freesasa_structure *structure,
const char *residue_name,
const char *residue_number,
const char *symbol,
char chain_label,
chain_label_t chain_label,
double x, double y, double z,
const freesasa_classifier *classifier,
int options)
Expand Down Expand Up @@ -749,8 +772,10 @@ int freesasa_structure_add_atom_wopt(freesasa_structure *structure,
const freesasa_classifier *classifier,
int options)
{
chain_label_t my_chain_label = { chain_label, '\0'};

return structure_add_atom_wopt_impl(structure, atom_name, residue_name, residue_number, NULL,
chain_label, x, y, z, classifier, options);
my_chain_label, x, y, z, classifier, options);
}
int freesasa_structure_add_atom(freesasa_structure *structure,
const char *atom_name,
Expand All @@ -759,8 +784,10 @@ int freesasa_structure_add_atom(freesasa_structure *structure,
char chain_label,
double x, double y, double z)
{
chain_label_t my_chain_label = { chain_label, '\0'};

return structure_add_atom_wopt_impl(structure, atom_name, residue_name, residue_number, NULL,
chain_label, x, y, z, NULL, 0);
my_chain_label, x, y, z, NULL, 0);
}

int freesasa_structure_add_cif_atom(freesasa_structure *structure,
Expand All @@ -776,8 +803,10 @@ int freesasa_structure_add_cif_atom(freesasa_structure *structure,
snprintf(res_number, sizeof res_number, "%s", atom->auth_seq_id);
}

chain_label_t chain_label = { atom->auth_asym_id, '\0'};

return structure_add_atom_wopt_impl(structure, atom->auth_atom_id, atom->auth_comp_id,
res_number, atom->type_symbol, atom->auth_asym_id,
res_number, atom->type_symbol, chain_label,
atom->Cartn_x, atom->Cartn_y, atom->Cartn_z,
classifier, options);
}
Expand Down Expand Up @@ -908,7 +937,7 @@ freesasa_structure_get_chains(const freesasa_structure *structure,
freesasa_structure *new_s;
struct atom *ai;
int i, res;
char c;
char* c;
const double *v;

assert(structure);
Expand All @@ -925,8 +954,8 @@ freesasa_structure_get_chains(const freesasa_structure *structure,

for (i = 0; i < structure->atoms.n; ++i) {
ai = structure->atoms.atom[i];
c = ai->chain_label[0];
if (strchr(chains, c) != NULL) {
c = ai->chain_label;
if (strchr(chains, c[0]) != NULL) {
v = freesasa_coord_i(structure->xyz, i);
res = structure_add_atom_wopt_impl(new_s, ai->atom_name,
ai->res_name, ai->res_number, ai->symbol,
Expand All @@ -943,7 +972,7 @@ freesasa_structure_get_chains(const freesasa_structure *structure,
if (new_s->atoms.n == 0) {
goto cleanup;
}
if (strlen(new_s->chains.labels) != strlen(chains)) {
if (new_s->chains.n != strlen(chains)) {
fail_msg("structure has chains '%s', but '%s' requested",
structure->chains.labels, chains);
goto cleanup;
Expand All @@ -960,7 +989,7 @@ const char *
freesasa_structure_chain_labels(const freesasa_structure *structure)
{
assert(structure);
return structure->chains.labels;
return structure->chains.short_labels;
}

const coord_t *
Expand Down Expand Up @@ -1133,7 +1162,7 @@ int freesasa_structure_chain_index(const freesasa_structure *structure,
assert(structure);

for (i = 0; i < structure->chains.n; ++i) {
if (structure->chains.labels[i] == chain) return i;
if (structure->chains.labels[i][0] == chain) return i;
}
return fail_msg("chain %c not found", chain);
}
Expand Down

0 comments on commit 2b60e2c

Please sign in to comment.