BreadcrumbHomeResourcesBlog How To Access IMSL C Functions From Python March 17, 2016 How to Access IMSL C Functions from PythonEmbedded AnalyticsIn this article, we describe how to access IMSL C Numerical Library functions from Python using the IMSL Python Numerical Library (PyNL) as a framework. PyNL consists of a set of Python wrappers for a subset of the functions in IMSL C. It also features a foundation of components that can be used to add additional wrappers, extending it to call any function in IMSL C.The details discussed assume that PyNL is installed. The discussion is based on developing a Python wrapper for the imsls_d_empirical_quantiles() function in IMSL C.Note: The wrappers provided with PyNL are more extensive and include features such as robust error handling and documentation using Sphinx. These wrappers should be considered an additional source for guidance on how to access IMSL C functions from Python.Guide to Creating a New Python PackageOnce PyNL is installed, we recommend creating a new package within the PyNL area in your Python site-packages area. This allows multiple user-written wrappers to coexist with the wrappers already provided with PyNL.The following steps serve as a guide to creating a new package, where PYNL_AREA refers to the site-packages/imsl folder in your Python installation.Create a new folder named PYNL_AREA/user_lib. Add a file named __init__.py to the PYNL_AREA/user_lib folder. The existing file, PYNL_AREA/cluster/__init__.py can be used as a guide for the contents of this file. Add the package name ‘user_lib’ to the file PYNL_AREA/__init__.py. Expose the name of the IMSL C function to be wrapped in PYNL_AREA/_imsllib.py. For example, to expose the IMSL C function imsls_d_empirical_quantiles(), add the following line at the end of the set of other functions that are exposed: self.expose("imsls_d_empirical_quantiles", None, _err_check, "stat") Use the file PYNL_AREA/_imsllib.py as a guide on where to add this line. This sets up the exception handling of PyNL to throw Python exceptions when errors are detected.Note: If you are wrapping a C/Math function, the final argument to self.expose should be "math" rather than "stat".Steps to Wrapping an IMSL C Function Using PyNLThere are three basic steps to wrapping an IMSL C function using PyNL as a framework:Performing data conversionSetting up arguments to be passed to the IMSL C functionPackaging results from the IMSL C functionThis example wraps the C/Stat function imsls_d_empirical_quantiles(), illustrating these three basic steps.Place the wrapper file empirical_quantiles.py in PYNL_AREA/user_lib."""Empirical Quantiles related functions.""" import ctypes as _ctypes import numpy as _numpy import imsl._constants as _constants import imsl._imsllib as _imsllib import collections as _collections def empirical_quantiles(x, qprop): r"""Compute empirical quantiles.""" ref_type = _numpy.float64 # Convert Data _x = _numpy.asarray(x, order='C', dtype=ref_type) if _x.ndim != 1: raise ValueError("x must be a 1-D array") _qprop = _numpy.asarray(qprop, order='C', dtype=ref_type) if _qprop.ndim != 1: raise ValueError("qprop must be a 1-D array") _n_obs = _x.shape[0] _n_qprop = _qprop.shape[0] # Set up arguments to be passed to the CNL function. args = [] # Required input argument list args.append(_ctypes.c_int(_n_obs)) args.append(_x.ctypes.data_as(_ctypes.c_void_p)) args.append(_ctypes.c_int(_n_qprop)) args.append(_qprop.ctypes.data_as(_ctypes.c_void_p)) # Create space for results _result = _numpy.empty(_n_qprop, dtype=ref_type) args.append(_constants.IMSLS_RETURN_USER) args.append(_result.ctypes.data_as(_ctypes.c_void_p)) _n_missing = _ctypes.c_int32() args.append(_constants.IMSLS_N_MISSING) args.append(_ctypes.byref(_n_missing)) _xlo = _numpy.empty(_n_qprop, dtype=ref_type) args.append(_constants.IMSLS_XLO_USER) args.append(_xlo.ctypes.data_as(_ctypes.c_void_p)) _xhi = _numpy.empty(_n_qprop, dtype=ref_type) args.append(_constants.IMSLS_XHI_USER) args.append(_xhi.ctypes.data_as(_ctypes.c_void_p)) args.append(0) # Terminating zero for CNL argument list. # Call the CNL function _imsllib.imsllib.imsls_d_empirical_quantiles(*args) # Package results from the CNL function result = _collections.namedtuple("empirical_quantiles", ["quantiles", "n_missing", "xlo", "xhi"]) result.quantiles = _result result.n_missing = _n_missing result.xlo = _xlo result.xhi = _xhi return result Example of Using PyNL WrappersIn this example, five empirical quantiles from a sample of size 30 are obtained. Notice that the 0.5 quantile corresponds to the sample median. The data are from Hinkley (1977) and Velleman and Hoaglin (1981). They are the measurements (in inches) of precipitation in Minneapolis/St. Paul during the month of March for 30 consecutive years.import imsl.user_lib as user_lib x = [0.77, 1.74, 0.81, 1.20, 1.95, 1.20, 0.47, 1.43, 3.37, 2.20, 3.00, 3.09, 1.51, 2.10, 0.52, 1.62, 1.31, 0.32, 0.59, 0.81, 2.81, 1.87, 1.18, 1.35, 4.75, 2.48, 0.96, 1.89, 0.90, 2.05] qprop = [0.01, 0.5, 0.9, 0.95, 0.99] result = user_lib.empirical_quantiles(x, prop) print(" Smaller Empirical Larger") print("Quantile Datum Quantile Datum") for i in range(5): print("{:6.2f} {:9.2f} {:9.2f} {:9.2f}".format( qprop[i], result.xlo[i], result.quantiles[i], result.xhi[i])) Example Output Smaller Empirical Larger Quantile Datum Quantile Datum 0.01 0.32 0.32 0.32 0.50 1.43 1.47 1.51 0.90 3.00 3.08 3.09 0.95 3.37 3.99 4.75 0.99 4.75 4.75 4.75 Additional Resources and Next StepsWant to try IMSL on your project? Request a trial today by clicking the button below.Free TrialAdditional ResourcesCreating a Python Wrapper for an IMSL C Function