jfaustin's picture
secretion-scores (#4)
a3f3d91 verified
/**
This source file contains everything that is in freesasa.h
interface and does not have a natural home in any of the other
source files.
*/
#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
// Allows compilation with different defaults
// depending on USE_THREADS. but still exposing the value in a header
// that doesn't depend on USE_THREADS
#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); //should never get here
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");
}