Author: bugman Date: Mon Apr 29 11:39:33 2013 New Revision: 19608 URL: http://svn.gna.org/viewcvs/relax?rev=19608&view=rev Log: Merged revisions 19595-19607 via svnmerge from svn+ssh://bugman@xxxxxxxxxxx/svn/relax/trunk ........ r19595 | bugman | 2013-04-29 09:47:39 +0200 (Mon, 29 Apr 2013) | 3 lines Clean up of unused headers and declarations in the exponential curve C module. ........ r19596 | bugman | 2013-04-29 09:54:20 +0200 (Mon, 29 Apr 2013) | 5 lines The relax_fit C module setup() function now uses the Py_RETURN_NONE macro to terminate. This macro does exactly what the old code does anyway. ........ r19597 | bugman | 2013-04-29 09:56:54 +0200 (Mon, 29 Apr 2013) | 3 lines Removed an unused declaration in the relax_fit C module setup() function. ........ r19598 | bugman | 2013-04-29 09:58:26 +0200 (Mon, 29 Apr 2013) | 3 lines Increased the maximum number of relaxation times for the relax_fit C module to 50. ........ r19599 | bugman | 2013-04-29 10:04:56 +0200 (Mon, 29 Apr 2013) | 8 lines Shifted the C array creation to the relax_fit C module header. The params, values, sd, relax_times, and scaling_matrix C arrays are now declared and allocated in the header file rather than using malloc() calls in the setup() function. This is to attempt to remove a memory leak. The arrays are now of fixed length and reused for each setup() call. These, as well as the other variables declared in the header are no longer declared in the functions. ........ r19600 | bugman | 2013-04-29 10:22:41 +0200 (Mon, 29 Apr 2013) | 3 lines Improved the Python and C documentation of the functions of the relax_fit C module. ........ r19601 | bugman | 2013-04-29 10:31:46 +0200 (Mon, 29 Apr 2013) | 5 lines Converted the Py_BuildValue() calls to PyFloat_FromDouble() in the relax_fit C module. This doesn't change much. ........ r19602 | bugman | 2013-04-29 10:35:15 +0200 (Mon, 29 Apr 2013) | 3 lines Documentation improvements for the back_calc_I() function of the relax_fit C module. ........ r19603 | bugman | 2013-04-29 10:36:42 +0200 (Mon, 29 Apr 2013) | 3 lines Spacing fixes. ........ r19604 | bugman | 2013-04-29 11:11:06 +0200 (Mon, 29 Apr 2013) | 5 lines The exponential C file now uses the exp() function from math.h rather than Python.h. This file is independent from Python. ........ r19605 | bugman | 2013-04-29 11:15:16 +0200 (Mon, 29 Apr 2013) | 6 lines The numpy include is no longer used for the compilation of the C modules. Numpy is not used at all in the C modules, so this just adds an annoying dependency for those who need to compile the module themselves. ........ r19606 | bugman | 2013-04-29 11:27:57 +0200 (Mon, 29 Apr 2013) | 7 lines Removed some bad calls to status.exec_lock.release(). This commit may have to be reverted in the future. The problem is that the execution lock is not being held when these calls are made. The calls were added as a kludge to handle certain situations where the execution lock was not released. There may be cases were this behaviour is still needed. ........ r19607 | bugman | 2013-04-29 11:37:47 +0200 (Mon, 29 Apr 2013) | 8 lines Big bug fix for a memory leak in the relaxation curve-fitting C module. Proper reference counting is used for the temporary 'element' Python objects used in the conversion between Python and C objects. The use of the Py_CLEAR() macro removes the memory leak. However the number of references as seen by sys.gettotalrefcount() in a debugging Python version keeps rising and might be a problem in the future. ........ Modified: branches/relax_disp/ (props changed) branches/relax_disp/prompt/interpreter.py branches/relax_disp/sconstruct branches/relax_disp/target_functions/exponential.c branches/relax_disp/target_functions/relax_fit.c branches/relax_disp/target_functions/relax_fit.h Propchange: branches/relax_disp/ ------------------------------------------------------------------------------ --- svnmerge-integrated (original) +++ svnmerge-integrated Mon Apr 29 11:39:33 2013 @@ -1,1 +1,1 @@ -/trunk:1-19593 +/trunk:1-19607 Modified: branches/relax_disp/prompt/interpreter.py URL: http://svn.gna.org/viewcvs/relax/branches/relax_disp/prompt/interpreter.py?rev=19608&r1=19607&r2=19608&view=diff ============================================================================== --- branches/relax_disp/prompt/interpreter.py (original) +++ branches/relax_disp/prompt/interpreter.py Mon Apr 29 11:39:33 2013 @@ -469,9 +469,6 @@ # Catch ctrl-C. except KeyboardInterrupt: - # Unlock execution. - status.exec_lock.release() - # Throw the error. if status.debug: raise @@ -506,9 +503,6 @@ # Throw all other errors. except: - # Unlock execution. - status.exec_lock.release() - # Raise the error. raise Modified: branches/relax_disp/sconstruct URL: http://svn.gna.org/viewcvs/relax/branches/relax_disp/sconstruct?rev=19608&r1=19607&r2=19608&view=diff ============================================================================== --- branches/relax_disp/sconstruct (original) +++ branches/relax_disp/sconstruct Mon Apr 29 11:39:33 2013 @@ -25,7 +25,6 @@ # Import statements. -from numpy import get_include from os import getcwd, path, remove, rmdir, sep, walk import platform from re import search @@ -540,9 +539,6 @@ py_bin_minpath = sys.prefix + path.sep + 'bin' py_bin_fullpath = py_bin_minpath + path.sep + 'python' + `sys.version_info[0]` + '.' + `sys.version_info[1]` - # Get the numpy include path (for numpy/arrayobject.h). - numpy_path = get_include() - # Relaxation curve fitting build environment. env = Environment() @@ -551,9 +547,9 @@ # C flags. if SYSTEM == 'Windows': - cflags = '/nologo /I\"' + py_include_minpath + '\" /I\"' + numpy_path + '\"' + cflags = '/nologo /I\"' + py_include_minpath + '\"' else: - cflags = '-I' + py_include_fullpath + ' -I' + numpy_path + cflags = '-I' + py_include_fullpath if env['PLATFORM'] == 'darwin': for arch in archs: cflags += ' -arch %s' % arch Modified: branches/relax_disp/target_functions/exponential.c URL: http://svn.gna.org/viewcvs/relax/branches/relax_disp/target_functions/exponential.c?rev=19608&r1=19607&r2=19608&view=diff ============================================================================== --- branches/relax_disp/target_functions/exponential.c (original) +++ branches/relax_disp/target_functions/exponential.c Mon Apr 29 11:39:33 2013 @@ -18,12 +18,8 @@ */ -/* This include must come first */ -#include <Python.h> - -/* The header for all functions which will be called */ -#include "relax_fit.h" - +/* The exponential function is needed. */ +#include <math.h> void exponential(double *params, double *relax_times, double *back_calc, int num_times) { @@ -31,7 +27,6 @@ */ /* Declarations */ - double Rx, I0; int i; Modified: branches/relax_disp/target_functions/relax_fit.c URL: http://svn.gna.org/viewcvs/relax/branches/relax_disp/target_functions/relax_fit.c?rev=19608&r1=19607&r2=19608&view=diff ============================================================================== --- branches/relax_disp/target_functions/relax_fit.c (original) +++ branches/relax_disp/target_functions/relax_fit.c Mon Apr 29 11:39:33 2013 @@ -29,14 +29,13 @@ static PyObject * setup(PyObject *self, PyObject *args, PyObject *keywords) { + /* Set up the module in preparation for calls to the target function. */ + /* Python object declarations */ PyObject *values_arg, *sd_arg, *relax_times_arg, *scaling_matrix_arg; PyObject *element; /* Normal declarations */ - extern double *params, *values, *sd, *relax_times, *scaling_matrix; - extern double relax_time_array; - extern int num_params, num_times; int i; /* The keyword list */ @@ -45,19 +44,13 @@ /* Parse the function arguments */ if (!PyArg_ParseTupleAndKeywords(args, keywords, "iiOOOO", keyword_list, &num_params, &num_times, &values_arg, &sd_arg, &relax_times_arg, &scaling_matrix_arg)) return NULL; - - /* Dynamic C arrays */ - params = (double *) malloc(sizeof(double)*num_params); - values = (double *) malloc(sizeof(double)*num_times); - sd = (double *) malloc(sizeof(double)*num_times); - relax_times = (double *) malloc(sizeof(double)*num_times); - scaling_matrix = (double *) malloc(sizeof(double)*num_params); /* Place the parameter related arguments into C arrays */ for (i = 0; i < num_params; i++) { /* The diagonalised scaling matrix list argument element */ element = PySequence_GetItem(scaling_matrix_arg, i); scaling_matrix[i] = PyFloat_AsDouble(element); + Py_CLEAR(element); } /* Place the time related arguments into C arrays */ @@ -65,34 +58,35 @@ /* The value argument element */ element = PySequence_GetItem(values_arg, i); values[i] = PyFloat_AsDouble(element); + Py_CLEAR(element); /* The sd argument element */ element = PySequence_GetItem(sd_arg, i); sd[i] = PyFloat_AsDouble(element); + Py_CLEAR(element); /* The relax_times argument element */ element = PySequence_GetItem(relax_times_arg, i); relax_times[i] = PyFloat_AsDouble(element); - } - - /* Return nothing */ - Py_INCREF(Py_None); - return Py_None; + Py_CLEAR(element); + } + + /* The macro for returning the Python None object */ + Py_RETURN_NONE; } static PyObject * func(PyObject *self, PyObject *args) { - /* Function for calculating and returning the chi-squared value. + /* Target function for calculating and returning the chi-squared value. * * Firstly the back calculated intensities are generated, then the chi-squared statistic is - * calculated + * calculated. */ /* Declarations */ PyObject *params_arg; PyObject *element; - extern double *params; int i; /* Parse the function arguments, the only argument should be the parameter array */ @@ -104,8 +98,9 @@ /* Get the element */ element = PySequence_GetItem(params_arg, i); - /* Convert to a C double */ + /* Convert to a C double, then free the memory. */ params[i] = PyFloat_AsDouble(element); + Py_CLEAR(element); /* Scale the parameter */ params[i] = params[i] * scaling_matrix[i]; @@ -115,13 +110,16 @@ exponential(params, relax_times, back_calc, num_times); /* Calculate and return the chi-squared value */ - return Py_BuildValue("f", chi2(values,sd,back_calc,num_times)); + return PyFloat_FromDouble(chi2(values, sd, back_calc, num_times)); } static PyObject * dfunc(PyObject *self, PyObject *args) { - /* Function for calculating and returning the chi-squared gradient. */ + /* Target function for calculating and returning the chi-squared gradient. + * + * This is currently unimplemented. + */ /* Declarations */ PyObject *params_arg; @@ -143,24 +141,26 @@ static PyObject * d2func(PyObject *self, PyObject *args) { - /* Function for calculating and returning the chi-squared Hessian. */ - return Py_BuildValue("f", 0.0); + /* Target function for calculating and returning the chi-squared Hessian. + * + * This is currently unimplemented. + */ + + return PyFloat_FromDouble(0.0); } static PyObject * back_calc_I(PyObject *self, PyObject *args) { - /* Function for returning as a numpy array the back calculated peak intensities */ + /* Return the back calculated peak intensities as a Python list. */ /* Declarations */ PyObject *back_calc_py = PyList_New(num_times); - extern double back_calc[]; - extern int num_times; int i; /* Copy the values out of the C array into the Python array */ for (i = 0; i < num_times; i++) - PyList_SetItem(back_calc_py, i, Py_BuildValue("f", back_calc[i])); + PyList_SetItem(back_calc_py, i, PyFloat_FromDouble(back_calc[i])); /* Return the numpy array */ return back_calc_py; @@ -169,12 +169,33 @@ /* The method table for the functions called by Python */ static PyMethodDef relax_fit_methods[] = { - {"setup", (PyCFunction)setup, METH_VARARGS | METH_KEYWORDS, "The main relaxation curve fitting setup function."}, - {"func", func, METH_VARARGS}, - {"dfunc", dfunc, METH_VARARGS}, - {"d2func", d2func, METH_VARARGS}, - {"back_calc_I", back_calc_I, METH_VARARGS}, - {NULL, NULL, 0, NULL} /* Sentinel */ + { + "setup", + (PyCFunction)setup, + METH_VARARGS | METH_KEYWORDS, + "Set up the module in preparation for calls to the target function." + }, { + "func", + func, + METH_VARARGS, + "Target function for calculating and returning the chi-squared value.\n\nFirstly the back calculated intensities are generated, then the chi-squared statistic is calculated." + }, { + "dfunc", + dfunc, + METH_VARARGS, + "Target function for calculating and returning the chi-squared gradient.\n\nThis is currently unimplemented." + }, { + "d2func", + d2func, + METH_VARARGS, + "Target function for calculating and returning the chi-squared Hessian.\n\nThis is currently unimplemented." + }, { + "back_calc_I", + back_calc_I, + METH_VARARGS, + "Return the back calculated peak intensities as a Python list." + }, + {NULL, NULL, 0, NULL} /* Sentinel */ }; Modified: branches/relax_disp/target_functions/relax_fit.h URL: http://svn.gna.org/viewcvs/relax/branches/relax_disp/target_functions/relax_fit.h?rev=19608&r1=19607&r2=19608&view=diff ============================================================================== --- branches/relax_disp/target_functions/relax_fit.h (original) +++ branches/relax_disp/target_functions/relax_fit.h Mon Apr 29 11:39:33 2013 @@ -1,5 +1,5 @@ /* - * Copyright (C) 2006-2012 Edward d'Auvergne + * Copyright (C) 2006-2013 Edward d'Auvergne * * This file is part of the program relax (http://www.nmr-relax.com). * @@ -22,7 +22,7 @@ #define MAXPARAMS 3 /* The maximum number of spectral time points */ -#define MAXTIMES 30 +#define MAXTIMES 50 /* Python 2.2 and earlier support for Python C modules */ #ifndef PyMODINIT_FUNC @@ -37,8 +37,10 @@ /* Variables sent to the setup function to be stored for later use */ int num_params, num_times; -/* Pointers to PyObjects */ -double *params, *values, *sd, *relax_times, *scaling_matrix; - /* Variables used for storage during the function calls of optimisation */ double back_calc[MAXTIMES]; +double params[MAXPARAMS]; +double values[MAXTIMES]; +double sd[MAXTIMES]; +double relax_times[MAXTIMES]; +double scaling_matrix[MAXPARAMS];