Generated by Cython 0.29.23
Yellow lines hint at Python interaction.
Click on a line that starts with a "+
" to see the C code that Cython generated for it.
Raw output: birmingham_method.c
+001: #!/usr/bin/env python3
__pyx_t_1 = __Pyx_PyDict_NewPresized(0); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 1, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_1); if (PyDict_SetItem(__pyx_d, __pyx_n_s_test, __pyx_t_1) < 0) __PYX_ERR(0, 1, __pyx_L1_error) __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
002: # -*- coding: utf-8 -*-
003:
004:
005: # pept is a Python library that unifies Positron Emission Particle
006: # Tracking (PEPT) research, including tracking, simulation, data analysis
007: # and visualisation tools.
008: #
009: # If you used this codebase or any software making use of it in a scientific
010: # publication, you must cite the following paper:
011: # Nicuşan AL, Windows-Yule CR. Positron emission particle tracking
012: # using machine learning. Review of Scientific Instruments.
013: # 2020 Jan 1;91(1):013329.
014: # https://doi.org/10.1063/1.5129251
015: #
016: # Copyright (C) 2019-2021 the pept developers
017: #
018: # This program is free software: you can redistribute it and/or modify
019: # it under the terms of the GNU General Public License as published by
020: # the Free Software Foundation, either version 3 of the License, or
021: # (at your option) any later version.
022: #
023: # This program is distributed in the hope that it will be useful,
024: # but WITHOUT ANY WARRANTY; without even the implied warranty of
025: # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
026: # GNU General Public License for more details.
027: #
028: # You should have received a copy of the GNU General Public License
029: # along with this program. If not, see <https://www.gnu.org/licenses/>.
030: # pept is a Python library that unifies Positron Emission Particle
031: # Tracking (PEPT) research, including tracking, simulation, data analysis
032: # and visualisation tools
033:
034:
035: # File : birmingham_method.pyx
036: # License : GNU v3.0
037: # Author : Sam Manger
038: # Date : 21.08.2019
039:
040:
041: # cython: language_level=3
042: # cython: boundscheck=False
043: # cython: wraparound=False
044: # cython: initializedcheck=False
045: # cython: nonecheck=False
046: # cython: embedsignature=True
047: # cython: cdivision=True
048:
049:
+050: import numpy as np # import numpy for Python functions
__pyx_t_1 = __Pyx_Import(__pyx_n_s_numpy, 0, 0); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 50, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_1); if (PyDict_SetItem(__pyx_d, __pyx_n_s_np, __pyx_t_1) < 0) __PYX_ERR(0, 50, __pyx_L1_error) __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
051: cimport numpy as np # import numpy for C functions (numpy's C API)
052:
053:
054: cdef extern from "birmingham_method_ext.c":
055: # C is included here so that it doesn't need to be compiled externally
056: pass
057:
058:
059: cdef extern from "birmingham_method_ext.h":
060: void birmingham_method_ext(
061: const double *, const Py_ssize_t, const Py_ssize_t,
062: double *, int *, const double
063: ) nogil
064:
065: void calculate(
066: double *, double *, double *, double *, double *, double *,
067: double *, double *, double *, double *, double *, double *,
068: double *, double *, double *, double *, double *,
069: int *, int, int, double *
070: ) nogil
071:
072:
073: # cpdef means it is defined both for Python and C code;
074: # cdef means it is defined only for C code;
075:
076: # Cython has a cool function to automatically get memoryviews of the input
077: # parameters => double[:, :] receives a 2D numpy array.
+078: cpdef birmingham_method(
static PyObject *__pyx_pw_4pept_8tracking_17birmingham_method_10extensions_17birmingham_method_1birmingham_method(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/ static PyObject *__pyx_f_4pept_8tracking_17birmingham_method_10extensions_17birmingham_method_birmingham_method(__Pyx_memviewslice __pyx_v_lines, double __pyx_v_fopt, CYTHON_UNUSED int __pyx_skip_dispatch) { Py_ssize_t __pyx_v_nrows; Py_ssize_t __pyx_v_ncols; PyArrayObject *__pyx_v_location = 0; PyArrayObject *__pyx_v_used = 0; __Pyx_LocalBuf_ND __pyx_pybuffernd_location; __Pyx_Buffer __pyx_pybuffer_location; __Pyx_LocalBuf_ND __pyx_pybuffernd_used; __Pyx_Buffer __pyx_pybuffer_used; PyObject *__pyx_r = NULL; __Pyx_RefNannyDeclarations __Pyx_RefNannySetupContext("birmingham_method", 0); __pyx_pybuffer_location.pybuffer.buf = NULL; __pyx_pybuffer_location.refcount = 0; __pyx_pybuffernd_location.data = NULL; __pyx_pybuffernd_location.rcbuffer = &__pyx_pybuffer_location; __pyx_pybuffer_used.pybuffer.buf = NULL; __pyx_pybuffer_used.refcount = 0; __pyx_pybuffernd_used.data = NULL; __pyx_pybuffernd_used.rcbuffer = &__pyx_pybuffer_used; /* … */ /* function exit code */ __pyx_L1_error:; __Pyx_XDECREF(__pyx_t_1); __Pyx_XDECREF(__pyx_t_2); __Pyx_XDECREF(__pyx_t_3); __Pyx_XDECREF(__pyx_t_4); __Pyx_XDECREF(__pyx_t_6); { PyObject *__pyx_type, *__pyx_value, *__pyx_tb; __Pyx_PyThreadState_declare __Pyx_PyThreadState_assign __Pyx_ErrFetch(&__pyx_type, &__pyx_value, &__pyx_tb); __Pyx_SafeReleaseBuffer(&__pyx_pybuffernd_location.rcbuffer->pybuffer); __Pyx_SafeReleaseBuffer(&__pyx_pybuffernd_used.rcbuffer->pybuffer); __Pyx_ErrRestore(__pyx_type, __pyx_value, __pyx_tb);} __Pyx_AddTraceback("pept.tracking.birmingham_method.extensions.birmingham_method.birmingham_method", __pyx_clineno, __pyx_lineno, __pyx_filename); __pyx_r = 0; goto __pyx_L2; __pyx_L0:; __Pyx_SafeReleaseBuffer(&__pyx_pybuffernd_location.rcbuffer->pybuffer); __Pyx_SafeReleaseBuffer(&__pyx_pybuffernd_used.rcbuffer->pybuffer); __pyx_L2:; __Pyx_XDECREF((PyObject *)__pyx_v_location); __Pyx_XDECREF((PyObject *)__pyx_v_used); __Pyx_XGIVEREF(__pyx_r); __Pyx_RefNannyFinishContext(); return __pyx_r; } /* Python wrapper */ static PyObject *__pyx_pw_4pept_8tracking_17birmingham_method_10extensions_17birmingham_method_1birmingham_method(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/ static char __pyx_doc_4pept_8tracking_17birmingham_method_10extensions_17birmingham_method_birmingham_method[] = "birmingham_method(double[:, :] lines, double fopt)\nUse the Birmingham Method to find one tracer location from the LoRs\n stored in `lines`.\n\n Function signature:\n birmingham_method(\n double[:, :] lines, # LoRs in a sample\n double fopt # Fraction of LoRs used to find tracer\n )\n\n This function receives a numpy array of LoRs (one \"sample\") from python,\n computing the minimum distance point (MDP). A number of lines that lie\n outside the standard deviation of the MDP are then removed from the set,\n and the MDP is recalculated. This process is repeated until approximately\n a fixed fraction (fopt) of the original lines is left.\n\n The found tracer position is then returned along with a boolean mask of\n the LoRs that were used to compute it.\n\n Parameters\n ----------\n lines : (N, M >= 7) numpy.ndarray\n A numpy array of the lines of respones (LoRs) that will be used to find\n a tracer location; each LoR is stored as a timestamp, the 3D\n coordinates of two points defining the line, followed by any additional\n data. The data columns are then `[time, x1, y1, z1, x2, y2, z2, etc]`.\n Note that the extra data is simply ignored by this function.\n fopt : float\n A float number between 0 and 1 representing the fraction of LoRs that\n will be used to compute the tracer location.\n\n Returns\n -------\n location : (5,) numpy.ndarray\n The computed tracer location, with data columns formatted as\n `[time, x, y, z, error]`.\n used : (N,) numpy.ndarray\n A boolean mask of the LoRs that were used to compute the tracer\n location; that is, a vector of the same length as `lines`, containing 1\n for the rows that were used, and 0 otherwise.\n\n Notes\n -----\n This is a low-level Cython function that does not do any checks on the\n input data - it is meant to be used in ot""her modules / libraries. For a\n normal user, the `pept.tracking.birmingham_method.BirminghamMethod` class\n methods `fit_sample` and `fit` are recommended as higher-level APIs. They\n do check the input parameters and are easier to use.\n "; static PyObject *__pyx_pw_4pept_8tracking_17birmingham_method_10extensions_17birmingham_method_1birmingham_method(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds) { __Pyx_memviewslice __pyx_v_lines = { 0, 0, { 0 }, { 0 }, { 0 } }; double __pyx_v_fopt; PyObject *__pyx_r = 0; __Pyx_RefNannyDeclarations __Pyx_RefNannySetupContext("birmingham_method (wrapper)", 0); { static PyObject **__pyx_pyargnames[] = {&__pyx_n_s_lines,&__pyx_n_s_fopt,0}; PyObject* values[2] = {0,0}; if (unlikely(__pyx_kwds)) { Py_ssize_t kw_args; const Py_ssize_t pos_args = PyTuple_GET_SIZE(__pyx_args); switch (pos_args) { case 2: values[1] = PyTuple_GET_ITEM(__pyx_args, 1); CYTHON_FALLTHROUGH; case 1: values[0] = PyTuple_GET_ITEM(__pyx_args, 0); CYTHON_FALLTHROUGH; case 0: break; default: goto __pyx_L5_argtuple_error; } kw_args = PyDict_Size(__pyx_kwds); switch (pos_args) { case 0: if (likely((values[0] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_lines)) != 0)) kw_args--; else goto __pyx_L5_argtuple_error; CYTHON_FALLTHROUGH; case 1: if (likely((values[1] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_fopt)) != 0)) kw_args--; else { __Pyx_RaiseArgtupleInvalid("birmingham_method", 1, 2, 2, 1); __PYX_ERR(0, 78, __pyx_L3_error) } } if (unlikely(kw_args > 0)) { if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "birmingham_method") < 0)) __PYX_ERR(0, 78, __pyx_L3_error) } } else if (PyTuple_GET_SIZE(__pyx_args) != 2) { goto __pyx_L5_argtuple_error; } else { values[0] = PyTuple_GET_ITEM(__pyx_args, 0); values[1] = PyTuple_GET_ITEM(__pyx_args, 1); } __pyx_v_lines = __Pyx_PyObject_to_MemoryviewSlice_dsds_double(values[0], PyBUF_WRITABLE); if (unlikely(!__pyx_v_lines.memview)) __PYX_ERR(0, 79, __pyx_L3_error) __pyx_v_fopt = __pyx_PyFloat_AsDouble(values[1]); if (unlikely((__pyx_v_fopt == (double)-1) && PyErr_Occurred())) __PYX_ERR(0, 80, __pyx_L3_error) } goto __pyx_L4_argument_unpacking_done; __pyx_L5_argtuple_error:; __Pyx_RaiseArgtupleInvalid("birmingham_method", 1, 2, 2, PyTuple_GET_SIZE(__pyx_args)); __PYX_ERR(0, 78, __pyx_L3_error) __pyx_L3_error:; __Pyx_AddTraceback("pept.tracking.birmingham_method.extensions.birmingham_method.birmingham_method", __pyx_clineno, __pyx_lineno, __pyx_filename); __Pyx_RefNannyFinishContext(); return NULL; __pyx_L4_argument_unpacking_done:; __pyx_r = __pyx_pf_4pept_8tracking_17birmingham_method_10extensions_17birmingham_method_birmingham_method(__pyx_self, __pyx_v_lines, __pyx_v_fopt); int __pyx_lineno = 0; const char *__pyx_filename = NULL; int __pyx_clineno = 0; /* function exit code */ __Pyx_RefNannyFinishContext(); return __pyx_r; } static PyObject *__pyx_pf_4pept_8tracking_17birmingham_method_10extensions_17birmingham_method_birmingham_method(CYTHON_UNUSED PyObject *__pyx_self, __Pyx_memviewslice __pyx_v_lines, double __pyx_v_fopt) { PyObject *__pyx_r = NULL; __Pyx_RefNannyDeclarations __Pyx_RefNannySetupContext("birmingham_method", 0); __Pyx_XDECREF(__pyx_r); __pyx_t_1 = __pyx_f_4pept_8tracking_17birmingham_method_10extensions_17birmingham_method_birmingham_method(__pyx_v_lines, __pyx_v_fopt, 0); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 78, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_1); __pyx_r = __pyx_t_1; __pyx_t_1 = 0; goto __pyx_L0; /* function exit code */ __pyx_L1_error:; __Pyx_XDECREF(__pyx_t_1); __Pyx_AddTraceback("pept.tracking.birmingham_method.extensions.birmingham_method.birmingham_method", __pyx_clineno, __pyx_lineno, __pyx_filename); __pyx_r = NULL; __pyx_L0:; __PYX_XDEC_MEMVIEW(&__pyx_v_lines, 1); __Pyx_XGIVEREF(__pyx_r); __Pyx_RefNannyFinishContext(); return __pyx_r; }
079: double[:, :] lines,
080: double fopt
081: ):
082: '''Use the Birmingham Method to find one tracer location from the LoRs
083: stored in `lines`.
084:
085: Function signature:
086: birmingham_method(
087: double[:, :] lines, # LoRs in a sample
088: double fopt # Fraction of LoRs used to find tracer
089: )
090:
091: This function receives a numpy array of LoRs (one "sample") from python,
092: computing the minimum distance point (MDP). A number of lines that lie
093: outside the standard deviation of the MDP are then removed from the set,
094: and the MDP is recalculated. This process is repeated until approximately
095: a fixed fraction (fopt) of the original lines is left.
096:
097: The found tracer position is then returned along with a boolean mask of
098: the LoRs that were used to compute it.
099:
100: Parameters
101: ----------
102: lines : (N, M >= 7) numpy.ndarray
103: A numpy array of the lines of respones (LoRs) that will be used to find
104: a tracer location; each LoR is stored as a timestamp, the 3D
105: coordinates of two points defining the line, followed by any additional
106: data. The data columns are then `[time, x1, y1, z1, x2, y2, z2, etc]`.
107: Note that the extra data is simply ignored by this function.
108: fopt : float
109: A float number between 0 and 1 representing the fraction of LoRs that
110: will be used to compute the tracer location.
111:
112: Returns
113: -------
114: location : (5,) numpy.ndarray
115: The computed tracer location, with data columns formatted as
116: `[time, x, y, z, error]`.
117: used : (N,) numpy.ndarray
118: A boolean mask of the LoRs that were used to compute the tracer
119: location; that is, a vector of the same length as `lines`, containing 1
120: for the rows that were used, and 0 otherwise.
121:
122: Notes
123: -----
124: This is a low-level Cython function that does not do any checks on the
125: input data - it is meant to be used in other modules / libraries. For a
126: normal user, the `pept.tracking.birmingham_method.BirminghamMethod` class
127: methods `fit_sample` and `fit` are recommended as higher-level APIs. They
128: do check the input parameters and are easier to use.
129: '''
130:
131: # Py_ssize_t is the one "strange" type from Cython - it is the type used
132: # for indexing arrays, as pointers must have a certain number of bits that
133: # is platform-dependent; that type is stored as a C macro in `ssize_t` that
134: # Cython also provides as `Py_ssize_t`.
+135: cdef Py_ssize_t nrows = lines.shape[0]
__pyx_v_nrows = (__pyx_v_lines.shape[0]);
+136: cdef Py_ssize_t ncols = lines.shape[1]
__pyx_v_ncols = (__pyx_v_lines.shape[1]);
137:
138: # np.float64 == C double ; np.intc == C int ;
+139: cdef np.ndarray[double, ndim = 1] location = np.zeros(5, dtype = np.float64)
__Pyx_GetModuleGlobalName(__pyx_t_1, __pyx_n_s_np); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 139, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_1); __pyx_t_2 = __Pyx_PyObject_GetAttrStr(__pyx_t_1, __pyx_n_s_zeros); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 139, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_2); __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; __pyx_t_1 = __Pyx_PyDict_NewPresized(1); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 139, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_1); __Pyx_GetModuleGlobalName(__pyx_t_3, __pyx_n_s_np); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 139, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_3); __pyx_t_4 = __Pyx_PyObject_GetAttrStr(__pyx_t_3, __pyx_n_s_float64); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 139, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_4); __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; if (PyDict_SetItem(__pyx_t_1, __pyx_n_s_dtype, __pyx_t_4) < 0) __PYX_ERR(0, 139, __pyx_L1_error) __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; __pyx_t_4 = __Pyx_PyObject_Call(__pyx_t_2, __pyx_tuple_, __pyx_t_1); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 139, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_4); __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; if (!(likely(((__pyx_t_4) == Py_None) || likely(__Pyx_TypeTest(__pyx_t_4, __pyx_ptype_5numpy_ndarray))))) __PYX_ERR(0, 139, __pyx_L1_error) __pyx_t_5 = ((PyArrayObject *)__pyx_t_4); { __Pyx_BufFmt_StackElem __pyx_stack[1]; if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_pybuffernd_location.rcbuffer->pybuffer, (PyObject*)__pyx_t_5, &__Pyx_TypeInfo_double, PyBUF_FORMAT| PyBUF_STRIDES, 1, 0, __pyx_stack) == -1)) { __pyx_v_location = ((PyArrayObject *)Py_None); __Pyx_INCREF(Py_None); __pyx_pybuffernd_location.rcbuffer->pybuffer.buf = NULL; __PYX_ERR(0, 139, __pyx_L1_error) } else {__pyx_pybuffernd_location.diminfo[0].strides = __pyx_pybuffernd_location.rcbuffer->pybuffer.strides[0]; __pyx_pybuffernd_location.diminfo[0].shape = __pyx_pybuffernd_location.rcbuffer->pybuffer.shape[0]; } } __pyx_t_5 = 0; __pyx_v_location = ((PyArrayObject *)__pyx_t_4); __pyx_t_4 = 0; /* … */ __pyx_tuple_ = PyTuple_Pack(1, __pyx_int_5); if (unlikely(!__pyx_tuple_)) __PYX_ERR(0, 139, __pyx_L1_error) __Pyx_GOTREF(__pyx_tuple_); __Pyx_GIVEREF(__pyx_tuple_);
+140: cdef np.ndarray[int, ndim = 1] used = np.ones(nrows, dtype = np.intc)
__Pyx_GetModuleGlobalName(__pyx_t_4, __pyx_n_s_np); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 140, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_4); __pyx_t_1 = __Pyx_PyObject_GetAttrStr(__pyx_t_4, __pyx_n_s_ones); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 140, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_1); __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; __pyx_t_4 = PyInt_FromSsize_t(__pyx_v_nrows); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 140, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_4); __pyx_t_2 = PyTuple_New(1); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 140, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_2); __Pyx_GIVEREF(__pyx_t_4); PyTuple_SET_ITEM(__pyx_t_2, 0, __pyx_t_4); __pyx_t_4 = 0; __pyx_t_4 = __Pyx_PyDict_NewPresized(1); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 140, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_4); __Pyx_GetModuleGlobalName(__pyx_t_3, __pyx_n_s_np); if (unlikely(!__pyx_t_3)) __PYX_ERR(0, 140, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_3); __pyx_t_6 = __Pyx_PyObject_GetAttrStr(__pyx_t_3, __pyx_n_s_intc); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 140, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_6); __Pyx_DECREF(__pyx_t_3); __pyx_t_3 = 0; if (PyDict_SetItem(__pyx_t_4, __pyx_n_s_dtype, __pyx_t_6) < 0) __PYX_ERR(0, 140, __pyx_L1_error) __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0; __pyx_t_6 = __Pyx_PyObject_Call(__pyx_t_1, __pyx_t_2, __pyx_t_4); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 140, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_6); __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0; __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0; __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0; if (!(likely(((__pyx_t_6) == Py_None) || likely(__Pyx_TypeTest(__pyx_t_6, __pyx_ptype_5numpy_ndarray))))) __PYX_ERR(0, 140, __pyx_L1_error) __pyx_t_7 = ((PyArrayObject *)__pyx_t_6); { __Pyx_BufFmt_StackElem __pyx_stack[1]; if (unlikely(__Pyx_GetBufferAndValidate(&__pyx_pybuffernd_used.rcbuffer->pybuffer, (PyObject*)__pyx_t_7, &__Pyx_TypeInfo_int, PyBUF_FORMAT| PyBUF_STRIDES, 1, 0, __pyx_stack) == -1)) { __pyx_v_used = ((PyArrayObject *)Py_None); __Pyx_INCREF(Py_None); __pyx_pybuffernd_used.rcbuffer->pybuffer.buf = NULL; __PYX_ERR(0, 140, __pyx_L1_error) } else {__pyx_pybuffernd_used.diminfo[0].strides = __pyx_pybuffernd_used.rcbuffer->pybuffer.strides[0]; __pyx_pybuffernd_used.diminfo[0].shape = __pyx_pybuffernd_used.rcbuffer->pybuffer.shape[0]; } } __pyx_t_7 = 0; __pyx_v_used = ((PyArrayObject *)__pyx_t_6); __pyx_t_6 = 0;
141:
142: # Release the GIL as we're in a thread-safe C function for most of our
143: # computation time.
+144: with nogil:
{ #ifdef WITH_THREAD PyThreadState *_save; Py_UNBLOCK_THREADS __Pyx_FastGIL_Remember(); #endif /*try:*/ { /* … */ /*finally:*/ { /*normal exit:*/{ #ifdef WITH_THREAD __Pyx_FastGIL_Forget(); Py_BLOCK_THREADS #endif goto __pyx_L5; } __pyx_L5:; } }
+145: birmingham_method_ext(
birmingham_method_ext((&(*((double *) ( /* dim=1 */ (( /* dim=0 */ (__pyx_v_lines.data + __pyx_t_8 * __pyx_v_lines.strides[0]) ) + __pyx_t_9 * __pyx_v_lines.strides[1]) )))), __pyx_v_nrows, __pyx_v_ncols, (&(*__Pyx_BufPtrStrided1d(double *, __pyx_pybuffernd_location.rcbuffer->pybuffer.buf, __pyx_t_10, __pyx_pybuffernd_location.diminfo[0].strides))), (&(*__Pyx_BufPtrStrided1d(int *, __pyx_pybuffernd_used.rcbuffer->pybuffer.buf, __pyx_t_11, __pyx_pybuffernd_used.diminfo[0].strides))), __pyx_v_fopt); }
+146: &lines[0, 0],
__pyx_t_8 = 0; __pyx_t_9 = 0;
147: nrows,
148: ncols,
+149: &location[0],
__pyx_t_10 = 0;
+150: &used[0],
__pyx_t_11 = 0;
151: fopt
152: )
153:
+154: return location, used
__Pyx_XDECREF(__pyx_r); __pyx_t_6 = PyTuple_New(2); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 154, __pyx_L1_error) __Pyx_GOTREF(__pyx_t_6); __Pyx_INCREF(((PyObject *)__pyx_v_location)); __Pyx_GIVEREF(((PyObject *)__pyx_v_location)); PyTuple_SET_ITEM(__pyx_t_6, 0, ((PyObject *)__pyx_v_location)); __Pyx_INCREF(((PyObject *)__pyx_v_used)); __Pyx_GIVEREF(((PyObject *)__pyx_v_used)); PyTuple_SET_ITEM(__pyx_t_6, 1, ((PyObject *)__pyx_v_used)); __pyx_r = __pyx_t_6; __pyx_t_6 = 0; goto __pyx_L0;
155:
156: