numina.array
— Array manipulation¶
-
process_ramp
(inp[, out=None, axis=2, ron=0.0, gain=1.0, nsig=4.0, dt=1.0, saturation=65631])¶ New in version 0.8.2.
Compute the result 2d array computing slopes in a 3d array or ramp.
Parameters: - inp – input array
- out – output array
- axis – unused
- ron – readout noise of the detector
- gain – gain of the detector
- nsig – rejection level to detect glitched and cosmic rays
- dt – time interval between exposures
- saturation – saturation level
Returns: a 2d array
numina.array.background
— Background estimation¶
numina.array.blocks
— Generation of blocks¶
numina.array.bpm
— Bad Pixel Mask interpolation¶
numina.array.combine
— Array combination¶
Combination methods in numina.array.combine
¶
All these functions return a PyCapsule
, that
can be passed to generic_combine()
-
mean_method
()¶ Mean method
-
median_method
()¶ Median method
-
sigmaclip_method
([low=0.0[, high=0.0]])¶ Sigmaclip method
Parameters: - low – Number of sigmas to reject under the mean
- high – Number of sigmas to reject over the mean
Raises: ValueError
if low or high are negative
-
quantileclip_method
([fclip=0.0])¶ Quantile clip method
Parameters: fclip – Fraction of points to reject on both ends Raises: ValueError
if fclip is negative or greater than 0.4
-
minmax_method
([nmin=0[, nmax=0]])¶ Min-max method
Parameters: - nmin – Number of minimum points to reject
- nmax – Number of maximum points to reject
Raises: ValueError
if nmin or nmax are negative
Extending generic_combine()
¶
New combination methods can be implemented and used by generic_combine()
The combine function expects a PyCapsule
object containing a pointer
to a C function implementing the combination method.
-
int
combine
(double *data, double *weights, size_t size, double *out[3], void *func_data)¶ Operate on two arrays, containing data and weights. The result, its variance and the number of points used in the calculation (useful when there is some kind of rejection) are stored in out[0], out[1] and out[2].
Parameters: - data – a pointer to an array containing the data
- weights – a pointer to an array containing weights
- size – the size of data and weights
- out – an array of pointers to the pixels in the result arrays
- func_data – additional parameters of the function encoded as a void pointer
Returns: 1 if operation succeeded, 0 in case of error.
If the function uses dynamically allocated data stored in func_data, we must also implement a function that deallocates the data once it is used.
-
void
destructor_function
(PyObject* cobject)¶ Parameters: - cobject – the object owning dynamically allocated data
Simple combine method¶
As an example, I’m going to implement a combination method that returns the minimum of the input arrays. Let’s call the method min_method
First, we implement the C function. I’m going to use some C++ here (it makes the code very simple).
int min_combine(double *data, double *weights, size_t size, double *out[3],
void *func_data) {
double* res = std::min_element(data, data + size);
*out[0] = *res;
// I'm not going to compute the variance for the minimum
// but it should go here
*out[1] = 0.0;
*out[2] = size;
return 1;
}
A destructor function is not needed in this case as we are not using func_data.
The next step is to build a Python extension. First we need to create a function
returning the PyCapsule
in C code like this:
static PyObject *
py_method_min(PyObject *obj, PyObject *args) {
if (not PyArg_ParseTuple(args, "")) {
PyErr_SetString(PyExc_RuntimeError, "invalid parameters");
return NULL;
}
return PyCapsule_New((void*)min_function, "numina.cmethod", NULL);
}
The string "numina.cmethod"
is the name of the PyCapsule
. It cannot be loadded
unless it is the name expected by the C code.
The code to load it in a module is like this:
static PyMethodDef mymod_methods[] = {
{"min_combine", (PyCFunction) py_method_min, METH_VARARGS, "Minimum method."},
...,
{ NULL, NULL, 0, NULL } /* sentinel */
};
PyMODINIT_FUNC
init_mymodule(void)
{
PyObject *m;
m = Py_InitModule("_mymodule", mymod_methods);
}
When compiled, this code created a file _mymodule.so that can be loaded by the Python interpreter. This module will contain, among others, a min_combine function.
>>> from _mymodule import min_combine
>>> method = min_combine()
...
>>> o = generic_combine(method, arrays)
A combine method with parameters¶
A combine method with parameters follow a similar approach. Let’s say we want to implement a sigma-clipping method. We need to pass the function a low and a high rejection limits. Both numbers are real numbers greater than zero.
First, the Python function. I’m skipping error checking code hre.
static PyObject *
py_method_sigmaclip(PyObject *obj, PyObject *args) {
double low = 0.0;
double high = 0.0;
PyObject *cap = NULL;
if (!PyArg_ParseTuple(args, "dd", &low, &high)) {
PyErr_SetString(PyExc_RuntimeError, "invalid parameters");
return NULL;
}
cap = PyCapsule_New((void*) my_sigmaclip_function, "numina.cmethod", my_destructor);
/* Allocating space for the two parameters */
/* We use Python memory allocator */
double *funcdata = (double*)PyMem_Malloc(2 * sizeof(double));
funcdata[0] = low;
funcdata[1] = high;
PyCapsule_SetContext(cap, funcdata);
return cap;
}
Notice that in this case we construct the PyCObject
using the same function
than in the previouis case. The aditional data is stored as Context.
The deallocator is simply:
void my_destructor_function(PyObject* cap) {
void* cdata = PyCapsule_GetContext(cap);
PyMem_Free(cdata);
}
and the combine function is:
int my_sigmaclip_function(double *data, double *weights, size_t size, double *out[3],
void *func_data) {
double* fdata = (double*) func_data;
double slow = *fdata;
double shigh = *(fdata + 1);
/* Operations go here */
return 1;
}
Once the module is created and loaded, a sample session would be:
>>> from _mymodule import min_combine
>>> method = sigmaclip_combine(3.0, 3.0)
...
>>> o = generic_combine(method, arrays)