|
|
|
|
|
|
|
|
|
|
|
|
|
#if HAVE_CONFIG_H |
|
# include <config.h> |
|
#endif |
|
#include <stdlib.h> |
|
#include <string.h> |
|
#include <assert.h> |
|
|
|
#include "freesasa_internal.h" |
|
|
|
#ifdef PACKAGE_VERSION |
|
const char *freesasa_version = PACKAGE_VERSION; |
|
#else |
|
const char *freesasa_version = ""; |
|
#endif |
|
|
|
#ifdef PACKAGE_STRING |
|
const char *freesasa_string = PACKAGE_STRING; |
|
#else |
|
const char *freesasa_string = "FreeSASA"; |
|
#endif |
|
|
|
|
|
|
|
|
|
#ifdef USE_THREADS |
|
#define DEF_NUMBER_THREADS 2 |
|
#else |
|
#define DEF_NUMBER_THREADS 1 |
|
#endif |
|
const int FREESASA_DEF_NUMBER_THREADS = DEF_NUMBER_THREADS; |
|
|
|
const freesasa_parameters freesasa_default_parameters = { |
|
.alg = FREESASA_DEF_ALGORITHM, |
|
.probe_radius = FREESASA_DEF_PROBE_RADIUS, |
|
.shrake_rupley_n_points = FREESASA_DEF_SR_N, |
|
.lee_richards_n_slices = FREESASA_DEF_LR_N, |
|
.n_threads = DEF_NUMBER_THREADS, |
|
}; |
|
|
|
static freesasa_result * |
|
result_new(int n) |
|
{ |
|
freesasa_result *result = malloc(sizeof(freesasa_result)); |
|
|
|
if (result == NULL) { |
|
mem_fail(); |
|
return NULL; |
|
} |
|
|
|
result->sasa = malloc(sizeof(double) * n); |
|
|
|
if (result->sasa == NULL) { |
|
mem_fail(); |
|
freesasa_result_free(result); |
|
return NULL; |
|
} |
|
|
|
result->n_atoms = n; |
|
|
|
return result; |
|
} |
|
|
|
void |
|
freesasa_result_free(freesasa_result *r) |
|
{ |
|
if (r) { |
|
free(r->sasa); |
|
free(r); |
|
} |
|
} |
|
|
|
freesasa_result* |
|
freesasa_calc(const coord_t *c, |
|
const double *radii, |
|
const freesasa_parameters *parameters) |
|
|
|
{ |
|
assert(c); |
|
assert(radii); |
|
|
|
freesasa_result *result = result_new(freesasa_coord_n(c)); |
|
int ret; |
|
|
|
if (result == NULL) { |
|
fail_msg(""); |
|
return NULL; |
|
} |
|
|
|
if (parameters == NULL) parameters = &freesasa_default_parameters; |
|
|
|
switch(parameters->alg) { |
|
case FREESASA_SHRAKE_RUPLEY: |
|
ret = freesasa_shrake_rupley(result->sasa, c, radii, parameters); |
|
break; |
|
case FREESASA_LEE_RICHARDS: |
|
ret = freesasa_lee_richards(result->sasa, c, radii, parameters); |
|
break; |
|
default: |
|
assert(0); |
|
break; |
|
} |
|
if (ret == FREESASA_FAIL) { |
|
freesasa_result_free(result); |
|
return NULL; |
|
} |
|
|
|
result->total = 0; |
|
for (int i = 0; i < freesasa_coord_n(c); ++i) { |
|
result->total += result->sasa[i]; |
|
} |
|
result->parameters = *parameters; |
|
|
|
return result; |
|
} |
|
|
|
freesasa_result* |
|
freesasa_calc_coord(const double *xyz, |
|
const double *radii, |
|
int n, |
|
const freesasa_parameters *parameters) |
|
{ |
|
assert(xyz); |
|
assert(radii); |
|
assert(n > 0); |
|
|
|
coord_t *coord = NULL; |
|
freesasa_result *result = NULL; |
|
|
|
coord = freesasa_coord_new_linked(xyz,n); |
|
if (coord != NULL) result = freesasa_calc(coord, radii, parameters); |
|
if (result == NULL) fail_msg(""); |
|
|
|
freesasa_coord_free(coord); |
|
|
|
return result; |
|
} |
|
|
|
freesasa_result* |
|
freesasa_calc_structure(const freesasa_structure* structure, |
|
const freesasa_parameters* parameters) |
|
{ |
|
assert(structure); |
|
|
|
return freesasa_calc(freesasa_structure_xyz(structure), |
|
freesasa_structure_radius(structure), |
|
parameters); |
|
} |
|
|
|
freesasa_node * |
|
freesasa_calc_tree(const freesasa_structure *structure, |
|
const freesasa_parameters *parameters, |
|
const char *name) |
|
{ |
|
assert(structure); |
|
|
|
freesasa_node *tree = NULL; |
|
freesasa_result *result = freesasa_calc(freesasa_structure_xyz(structure), |
|
freesasa_structure_radius(structure), |
|
parameters); |
|
|
|
if (result != NULL) { |
|
tree = freesasa_tree_init(result, structure, name); |
|
} else { |
|
fail_msg(""); |
|
} |
|
|
|
if (tree == NULL) { |
|
fail_msg(""); |
|
} |
|
|
|
freesasa_result_free(result); |
|
|
|
return tree; |
|
} |
|
|
|
static inline void |
|
count_err(int return_value, int *n_err) |
|
{ |
|
if (return_value == FREESASA_FAIL) { |
|
(*n_err)++; |
|
} |
|
} |
|
|
|
int |
|
freesasa_tree_export(FILE *file, |
|
freesasa_node *root, |
|
int options) |
|
{ |
|
assert(freesasa_node_type(root) == FREESASA_NODE_ROOT); |
|
int n_err = 0; |
|
if (options & FREESASA_LOG) { |
|
count_err(freesasa_write_log(file, root), &n_err); |
|
} |
|
if (options & FREESASA_RES) { |
|
count_err(freesasa_write_res(file, root), &n_err); |
|
} |
|
if (options & FREESASA_SEQ) { |
|
count_err(freesasa_write_seq(file, root), &n_err); |
|
} |
|
if (options & FREESASA_PDB) { |
|
count_err(freesasa_write_pdb(file, root), &n_err); |
|
} |
|
if (options & FREESASA_RSA) { |
|
count_err(freesasa_write_rsa(file, root, options), &n_err); |
|
} |
|
if (options & FREESASA_JSON) { |
|
if (USE_JSON) count_err(freesasa_write_json(file, root, options), &n_err); |
|
else return fail_msg("library was built without support for JSON output"); |
|
} |
|
if (options & FREESASA_XML) { |
|
if (USE_XML) count_err(freesasa_write_xml(file, root, options), &n_err); |
|
else return fail_msg("library was built without support for XML output"); |
|
} |
|
if (n_err > 0) { |
|
return fail_msg("there were errors when writing output"); |
|
} |
|
return FREESASA_SUCCESS; |
|
} |
|
|
|
freesasa_result * |
|
freesasa_result_clone(const freesasa_result *result) |
|
{ |
|
freesasa_result *clone = result_new(result->n_atoms); |
|
if (clone == NULL) { |
|
fail_msg(""); |
|
return NULL; |
|
} |
|
|
|
clone->n_atoms = result->n_atoms; |
|
clone->total = result->total; |
|
clone->parameters = result->parameters; |
|
memcpy(clone->sasa, result->sasa, sizeof(double) * clone->n_atoms); |
|
|
|
return clone; |
|
} |
|
|
|
const char* |
|
freesasa_alg_name(freesasa_algorithm alg) |
|
{ |
|
switch(alg) { |
|
case FREESASA_SHRAKE_RUPLEY: |
|
return "Shrake & Rupley"; |
|
case FREESASA_LEE_RICHARDS: |
|
return "Lee & Richards"; |
|
} |
|
assert(0 && "Illegal algorithm"); |
|
} |
|
|