Generated by Cython 0.29.21
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: occupancy_ext.c
+001: # -*- coding: utf-8 -*-
__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:
003:
004: # pept is a Python library that unifies Positron Emission Particle
005: # Tracking (PEPT) research, including tracking, simulation, data analysis
006: # and visualisation tools.
007: #
008: # If you used this codebase or any software making use of it in a scientific
009: # publication, you must cite the following paper:
010: # Nicuşan AL, Windows-Yule CR. Positron emission particle tracking
011: # using machine learning. Review of Scientific Instruments.
012: # 2020 Jan 1;91(1):013329.
013: # https://doi.org/10.1063/1.5129251
014: #
015: # Copyright (C) 2020 Andrei Leonard Nicusan
016: #
017: # This program is free software: you can redistribute it and/or modify
018: # it under the terms of the GNU General Public License as published by
019: # the Free Software Foundation, either version 3 of the License, or
020: # (at your option) any later version.
021: #
022: # This program is distributed in the hope that it will be useful,
023: # but WITHOUT ANY WARRANTY; without even the implied warranty of
024: # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
025: # GNU General Public License for more details.
026: #
027: # You should have received a copy of the GNU General Public License
028: # along with this program. If not, see <https://www.gnu.org/licenses/>.
029: # pept is a Python library that unifies Positron Emission Particle
030: # Tracking (PEPT) research, including tracking, simulation, data analysis
031: # and visualisation tools
032:
033:
034: # File : occupancy_ext.pyx
035: # License : GNU v3.0
036: # Author : Andrei Leonard Nicusan <a.l.nicusan@bham.ac.uk>
037: # Date : 23.11.2020
038:
039:
040: # cython: language_level=3
041: # cython: boundscheck=False
042: # cython: wraparound=False
043: # cython: initializedcheck=False
044: # cython: nonecheck=False
045: # cython: embedsignature=True
046: # cython: cdivision=True
047:
048:
049: #import numpy as np
050:
051: from libc.math cimport floor, sqrt, acos, M_PI
052: from libc.float cimport DBL_MAX
053:
054:
+055: cdef inline double fabs(double x) nogil:
static CYTHON_INLINE double __pyx_f_4pept_10processing_13occupancy_ext_fabs(double __pyx_v_x) { double __pyx_r; /* … */ /* function exit code */ __pyx_L0:; return __pyx_r; }
+056: return (x if x >= 0 else -x)
if (((__pyx_v_x >= 0.0) != 0)) { __pyx_t_1 = __pyx_v_x; } else { __pyx_t_1 = (-__pyx_v_x); } __pyx_r = __pyx_t_1; goto __pyx_L0;
057:
058:
+059: cdef inline double dist(double x1, double y1, double x2, double y2) nogil:
static CYTHON_INLINE double __pyx_f_4pept_10processing_13occupancy_ext_dist(double __pyx_v_x1, double __pyx_v_y1, double __pyx_v_x2, double __pyx_v_y2) { double __pyx_r; /* … */ /* function exit code */ __pyx_L0:; return __pyx_r; }
060: # Distance between two 2D points
+061: return sqrt((x1 - x2) ** 2 + (y1 - y2) ** 2)
__pyx_r = sqrt((pow((__pyx_v_x1 - __pyx_v_x2), 2.0) + pow((__pyx_v_y1 - __pyx_v_y2), 2.0))); goto __pyx_L0;
062:
063:
+064: cdef inline double dist2(double x1, double y1, double x2, double y2) nogil:
static CYTHON_INLINE double __pyx_f_4pept_10processing_13occupancy_ext_dist2(double __pyx_v_x1, double __pyx_v_y1, double __pyx_v_x2, double __pyx_v_y2) { double __pyx_r; /* … */ /* function exit code */ __pyx_L0:; return __pyx_r; }
065: # Squared distance between two 2D points
+066: return (x1 - x2) ** 2 + (y1 - y2) ** 2
__pyx_r = (pow((__pyx_v_x1 - __pyx_v_x2), 2.0) + pow((__pyx_v_y1 - __pyx_v_y2), 2.0)); goto __pyx_L0;
067:
068:
+069: cdef inline double term(double r, double _c, double _p) nogil:
static CYTHON_INLINE double __pyx_f_4pept_10processing_13occupancy_ext_term(double __pyx_v_r, double __pyx_v__c, double __pyx_v__p) { double __pyx_r; /* … */ /* function exit code */ __pyx_L0:; return __pyx_r; }
070: # Term in calculation of `one_corner`
071: # Same for xc / xp and yc / yp
+072: return sqrt(r ** 2 - (_c - _p) ** 2)
__pyx_r = sqrt((pow(__pyx_v_r, 2.0) - pow((__pyx_v__c - __pyx_v__p), 2.0))); goto __pyx_L0;
073:
074:
+075: cdef inline double triangle(
static CYTHON_INLINE double __pyx_f_4pept_10processing_13occupancy_ext_triangle(double __pyx_v_x1, double __pyx_v_y1, double __pyx_v_x2, double __pyx_v_y2, double __pyx_v_x3, double __pyx_v_y3) { double __pyx_r; /* … */ /* function exit code */ __pyx_L0:; return __pyx_r; }
076: double x1, double y1, double x2, double y2, double x3, double y3
077: ) nogil:
+078: return 0.5 * fabs(x1 * (y2 - y3) + x2 * (y3 - y1) + x3 * (y1 - y2))
__pyx_r = (0.5 * __pyx_f_4pept_10processing_13occupancy_ext_fabs((((__pyx_v_x1 * (__pyx_v_y2 - __pyx_v_y3)) + (__pyx_v_x2 * (__pyx_v_y3 - __pyx_v_y1))) + (__pyx_v_x3 * (__pyx_v_y1 - __pyx_v_y2))))); goto __pyx_L0;
079:
080:
+081: cdef inline double dist_pl(
static CYTHON_INLINE double __pyx_f_4pept_10processing_13occupancy_ext_dist_pl(double __pyx_v_x0, double __pyx_v_y0, double __pyx_v_x1, double __pyx_v_y1, double __pyx_v_x2, double __pyx_v_y2) { double __pyx_v_denom; double __pyx_v_nom; double __pyx_r; /* … */ /* function exit code */ __pyx_L0:; return __pyx_r; }
082: double x0,
083: double y0,
084: double x1,
085: double y1,
086: double x2,
087: double y2
088: ) nogil:
089: # Distance from a point (x0, y0) to a line defined by two points
090: # (x1, y1) and (x2, y2)
+091: denom = dist(x1, y1, x2, y2)
__pyx_v_denom = __pyx_f_4pept_10processing_13occupancy_ext_dist(__pyx_v_x1, __pyx_v_y1, __pyx_v_x2, __pyx_v_y2);
+092: nom = fabs((y2 - y1) * x0 - (x2 - x1) * y0 + x2 * y1 - y2 * x1)
__pyx_v_nom = __pyx_f_4pept_10processing_13occupancy_ext_fabs((((((__pyx_v_y2 - __pyx_v_y1) * __pyx_v_x0) - ((__pyx_v_x2 - __pyx_v_x1) * __pyx_v_y0)) + (__pyx_v_x2 * __pyx_v_y1)) - (__pyx_v_y2 * __pyx_v_x1)));
093:
+094: return nom / denom
__pyx_r = (__pyx_v_nom / __pyx_v_denom); goto __pyx_L0;
095:
096:
+097: cdef inline double circular_segment(double r, double h) nogil:
static CYTHON_INLINE double __pyx_f_4pept_10processing_13occupancy_ext_circular_segment(double __pyx_v_r, double __pyx_v_h) { double __pyx_r; /* … */ /* function exit code */ __pyx_L0:; return __pyx_r; }
098: # Area of a circular segment from a circle of radius r and a line
099: # If the distance from the circle centre to the line is d, then
100: # h = r - d
+101: if h < 0.0: # Happens for very small distances (d = r * 1e-13)
__pyx_t_1 = ((__pyx_v_h < 0.0) != 0); if (__pyx_t_1) { /* … */ }
+102: return 0.0
__pyx_r = 0.0; goto __pyx_L0;
103:
+104: return r ** 2 * acos((r - h) / r) - (r - h) * sqrt(2 * r * h - h ** 2)
__pyx_r = ((pow(__pyx_v_r, 2.0) * acos(((__pyx_v_r - __pyx_v_h) / __pyx_v_r))) - ((__pyx_v_r - __pyx_v_h) * sqrt((((2.0 * __pyx_v_r) * __pyx_v_h) - pow(__pyx_v_h, 2.0))))); goto __pyx_L0;
105:
106:
+107: cdef inline double zero_corner(
static CYTHON_INLINE double __pyx_f_4pept_10processing_13occupancy_ext_zero_corner(CYTHON_UNUSED Py_ssize_t *__pyx_v_corners, double __pyx_v_px, double __pyx_v_py, double __pyx_v_xsize, double __pyx_v_ysize, double __pyx_v_x0, double __pyx_v_y0, double __pyx_v_r) { double __pyx_v_h; double __pyx_v_area; double __pyx_v_xmin; double __pyx_v_xmax; double __pyx_v_ymin; double __pyx_v_ymax; double __pyx_r; /* … */ /* function exit code */ __pyx_L0:; return __pyx_r; }
108: Py_ssize_t[4] corners,
109: double px,
110: double py,
111: double xsize,
112: double ysize,
113: double x0,
114: double y0,
115: double r,
116: ) nogil:
117: '''Compute the overlapping area between a circle and a rectangle when
118: exactly one of the rectangle's corners are inside the circle.
119:
120: Parameters
121: ----------
122: corners
123: Vector of 0 and 1 for the corner that is inside the circle. The
124: corners are in trigonometric order.
125:
126: px, py
127: The pixel x and y coordinates.
128:
129: xsize, ysize
130: The pixel width and height.
131:
132: x, y
133: The circle origin x and y coordinates
134:
135: r
136: The circle radius
137:
138: Returns
139: -------
140: The overlapping area.
141: '''
142:
143: # Distance from circle centre x0, y0 to line defined by the two
144: # intersections above and h = (r - d)
145: cdef double h
+146: cdef double area = 0.
__pyx_v_area = 0.;
+147: cdef double xmin = px - xsize / 2
__pyx_v_xmin = (__pyx_v_px - (__pyx_v_xsize / 2.0));
+148: cdef double xmax = px + xsize / 2
__pyx_v_xmax = (__pyx_v_px + (__pyx_v_xsize / 2.0));
+149: cdef double ymin = py - ysize / 2
__pyx_v_ymin = (__pyx_v_py - (__pyx_v_ysize / 2.0));
+150: cdef double ymax = py + ysize / 2
__pyx_v_ymax = (__pyx_v_py + (__pyx_v_ysize / 2.0));
151:
152: # Corner case - if zero corners are inside, there might be no intersection
153: # This happens when the centre of the particle is in one of the corners
+154: if ((x0 <= xmin and y0 <= ymin) or # Bottom left
__pyx_t_2 = ((__pyx_v_x0 <= __pyx_v_xmin) != 0); if (!__pyx_t_2) { goto __pyx_L5_next_or; } else { } __pyx_t_2 = ((__pyx_v_y0 <= __pyx_v_ymin) != 0); if (!__pyx_t_2) { } else { __pyx_t_1 = __pyx_t_2; goto __pyx_L4_bool_binop_done; } __pyx_L5_next_or:; /* … */ if (__pyx_t_1) { /* … */ }
+155: (x0 >= xmax and y0 <= ymin) or # Bottom right
__pyx_t_2 = ((__pyx_v_x0 >= __pyx_v_xmax) != 0); if (!__pyx_t_2) { goto __pyx_L7_next_or; } else { } __pyx_t_2 = ((__pyx_v_y0 <= __pyx_v_ymin) != 0); if (!__pyx_t_2) { } else { __pyx_t_1 = __pyx_t_2; goto __pyx_L4_bool_binop_done; } __pyx_L7_next_or:;
+156: (x0 >= xmax and y0 >= ymax) or # Top right
__pyx_t_2 = ((__pyx_v_x0 >= __pyx_v_xmax) != 0); if (!__pyx_t_2) { goto __pyx_L9_next_or; } else { } __pyx_t_2 = ((__pyx_v_y0 >= __pyx_v_ymax) != 0); if (!__pyx_t_2) { } else { __pyx_t_1 = __pyx_t_2; goto __pyx_L4_bool_binop_done; } __pyx_L9_next_or:;
+157: (x0 <= xmin and y0 >= ymax)): # Top left
__pyx_t_2 = ((__pyx_v_x0 <= __pyx_v_xmin) != 0); if (__pyx_t_2) { } else { __pyx_t_1 = __pyx_t_2; goto __pyx_L4_bool_binop_done; } __pyx_t_2 = ((__pyx_v_y0 >= __pyx_v_ymax) != 0); __pyx_t_1 = __pyx_t_2; __pyx_L4_bool_binop_done:;
+158: return 0.
__pyx_r = 0.; goto __pyx_L0;
159:
160: # Particle is fully encapsulated
+161: if xmin < x0 < xmax and ymin < y0 < ymax:
__pyx_t_2 = (__pyx_v_xmin < __pyx_v_x0); if (__pyx_t_2) { __pyx_t_2 = (__pyx_v_x0 < __pyx_v_xmax); } __pyx_t_3 = (__pyx_t_2 != 0); if (__pyx_t_3) { } else { __pyx_t_1 = __pyx_t_3; goto __pyx_L13_bool_binop_done; } __pyx_t_3 = (__pyx_v_ymin < __pyx_v_y0); if (__pyx_t_3) { __pyx_t_3 = (__pyx_v_y0 < __pyx_v_ymax); } __pyx_t_2 = (__pyx_t_3 != 0); __pyx_t_1 = __pyx_t_2; __pyx_L13_bool_binop_done:; if (__pyx_t_1) { /* … */ }
+162: return M_PI * r * r
__pyx_r = ((M_PI * __pyx_v_r) * __pyx_v_r); goto __pyx_L0;
163: # Below
+164: elif xmin < x0 < xmax:
__pyx_t_1 = (__pyx_v_xmin < __pyx_v_x0); if (__pyx_t_1) { __pyx_t_1 = (__pyx_v_x0 < __pyx_v_xmax); } __pyx_t_2 = (__pyx_t_1 != 0); if (__pyx_t_2) { /* … */ goto __pyx_L12; }
+165: h = ysize / 2 + r - fabs(py - y0)
__pyx_v_h = (((__pyx_v_ysize / 2.0) + __pyx_v_r) - __pyx_f_4pept_10processing_13occupancy_ext_fabs((__pyx_v_py - __pyx_v_y0)));
166: # Above
167: else:
+168: h = xsize / 2 + r - fabs(px - x0)
/*else*/ { __pyx_v_h = (((__pyx_v_xsize / 2.0) + __pyx_v_r) - __pyx_f_4pept_10processing_13occupancy_ext_fabs((__pyx_v_px - __pyx_v_x0))); } __pyx_L12:;
169:
170: # Area of the circular segment
+171: area += circular_segment(r, h)
__pyx_v_area = (__pyx_v_area + __pyx_f_4pept_10processing_13occupancy_ext_circular_segment(__pyx_v_r, __pyx_v_h));
172:
+173: return area
__pyx_r = __pyx_v_area; goto __pyx_L0;
174:
175:
+176: cdef inline double one_corner(
static CYTHON_INLINE double __pyx_f_4pept_10processing_13occupancy_ext_one_corner(Py_ssize_t *__pyx_v_corners, double __pyx_v_px, double __pyx_v_py, double __pyx_v_xsize, double __pyx_v_ysize, double __pyx_v_x0, double __pyx_v_y0, double __pyx_v_r) { double __pyx_v_xc; double __pyx_v_yc; double __pyx_v_x1; double __pyx_v_y1; double __pyx_v_x2; double __pyx_v_y2; double __pyx_v_d; double __pyx_v_h; double __pyx_v_area; double __pyx_v_xmin; double __pyx_v_xmax; double __pyx_v_ymin; double __pyx_v_ymax; double __pyx_r; /* … */ /* function exit code */ __pyx_L0:; return __pyx_r; }
177: Py_ssize_t[4] corners,
178: double px,
179: double py,
180: double xsize,
181: double ysize,
182: double x0,
183: double y0,
184: double r,
185: ) nogil:
186: '''Compute the overlapping area between a circle and a rectangle when
187: exactly one of the rectangle's corners are inside the circle.
188:
189: Parameters
190: ----------
191: corners
192: Vector of 0 and 1 for the corner that is inside the circle. The
193: corners are in trigonometric order.
194:
195: px, py
196: The pixel x and y coordinates.
197:
198: xsize, ysize
199: The pixel width and height.
200:
201: x, y
202: The circle origin x and y coordinates
203:
204: r
205: The circle radius
206:
207: Returns
208: -------
209: The overlapping area.
210: '''
211:
212: # The bounded corner coordinates
+213: cdef double xc = 0, yc = 0
__pyx_v_xc = 0.0; __pyx_v_yc = 0.0;
214:
215: # The coords of the two intersections between the circle and the rectangle
+216: cdef double x1 = 0, y1 = 0, x2 = 0, y2 = 0
__pyx_v_x1 = 0.0; __pyx_v_y1 = 0.0; __pyx_v_x2 = 0.0; __pyx_v_y2 = 0.0;
217:
218: # Distance from circle centre x0, y0 to line defined by the two
219: # intersections above and h = (r - d)
220: cdef double d, h
221:
+222: cdef double area = 0.
__pyx_v_area = 0.;
223:
224: # Pixel boundaries
+225: cdef double xmin = px - xsize / 2
__pyx_v_xmin = (__pyx_v_px - (__pyx_v_xsize / 2.0));
+226: cdef double xmax = px + xsize / 2
__pyx_v_xmax = (__pyx_v_px + (__pyx_v_xsize / 2.0));
+227: cdef double ymin = py - ysize / 2
__pyx_v_ymin = (__pyx_v_py - (__pyx_v_ysize / 2.0));
+228: cdef double ymax = py + ysize / 2
__pyx_v_ymax = (__pyx_v_py + (__pyx_v_ysize / 2.0));
229:
230: # Lower left corner
+231: if corners[0] == 1:
__pyx_t_1 = (((__pyx_v_corners[0]) == 1) != 0); if (__pyx_t_1) { /* … */ goto __pyx_L3; }
+232: xc = xmin
__pyx_v_xc = __pyx_v_xmin;
+233: yc = ymin
__pyx_v_yc = __pyx_v_ymin;
234:
+235: x1 = x0 + term(r, yc, y0)
__pyx_v_x1 = (__pyx_v_x0 + __pyx_f_4pept_10processing_13occupancy_ext_term(__pyx_v_r, __pyx_v_yc, __pyx_v_y0));
+236: y1 = yc
__pyx_v_y1 = __pyx_v_yc;
237:
+238: x2 = xc
__pyx_v_x2 = __pyx_v_xc;
+239: y2 = y0 + term(r, xc, x0)
__pyx_v_y2 = (__pyx_v_y0 + __pyx_f_4pept_10processing_13occupancy_ext_term(__pyx_v_r, __pyx_v_xc, __pyx_v_x0));
240:
241: # Lower right corner
+242: elif corners[1] == 1:
__pyx_t_1 = (((__pyx_v_corners[1]) == 1) != 0); if (__pyx_t_1) { /* … */ goto __pyx_L3; }
+243: xc = xmax
__pyx_v_xc = __pyx_v_xmax;
+244: yc = ymin
__pyx_v_yc = __pyx_v_ymin;
245:
+246: x1 = xc
__pyx_v_x1 = __pyx_v_xc;
+247: y1 = y0 + term(r, xc, x0)
__pyx_v_y1 = (__pyx_v_y0 + __pyx_f_4pept_10processing_13occupancy_ext_term(__pyx_v_r, __pyx_v_xc, __pyx_v_x0));
248:
+249: x2 = x0 - term(r, yc, y0)
__pyx_v_x2 = (__pyx_v_x0 - __pyx_f_4pept_10processing_13occupancy_ext_term(__pyx_v_r, __pyx_v_yc, __pyx_v_y0));
+250: y2 = yc
__pyx_v_y2 = __pyx_v_yc;
251:
252: # Upper right corner
+253: elif corners[2] == 1:
__pyx_t_1 = (((__pyx_v_corners[2]) == 1) != 0); if (__pyx_t_1) { /* … */ goto __pyx_L3; }
+254: xc = xmax
__pyx_v_xc = __pyx_v_xmax;
+255: yc = ymax
__pyx_v_yc = __pyx_v_ymax;
256:
+257: x1 = x0 - term(r, yc, y0)
__pyx_v_x1 = (__pyx_v_x0 - __pyx_f_4pept_10processing_13occupancy_ext_term(__pyx_v_r, __pyx_v_yc, __pyx_v_y0));
+258: y1 = yc
__pyx_v_y1 = __pyx_v_yc;
259:
+260: x2 = xc
__pyx_v_x2 = __pyx_v_xc;
+261: y2 = y0 - term(r, xc, x0)
__pyx_v_y2 = (__pyx_v_y0 - __pyx_f_4pept_10processing_13occupancy_ext_term(__pyx_v_r, __pyx_v_xc, __pyx_v_x0));
262:
263: # Upper left corner
+264: elif corners[3] == 1:
__pyx_t_1 = (((__pyx_v_corners[3]) == 1) != 0); if (__pyx_t_1) { /* … */ } __pyx_L3:;
+265: xc = xmin
__pyx_v_xc = __pyx_v_xmin;
+266: yc = ymax
__pyx_v_yc = __pyx_v_ymax;
267:
+268: x1 = x0 + term(r, yc, y0)
__pyx_v_x1 = (__pyx_v_x0 + __pyx_f_4pept_10processing_13occupancy_ext_term(__pyx_v_r, __pyx_v_yc, __pyx_v_y0));
+269: y1 = yc
__pyx_v_y1 = __pyx_v_yc;
270:
+271: x2 = xc
__pyx_v_x2 = __pyx_v_xc;
+272: y2 = y0 - term(r, xc, x0)
__pyx_v_y2 = (__pyx_v_y0 - __pyx_f_4pept_10processing_13occupancy_ext_term(__pyx_v_r, __pyx_v_xc, __pyx_v_x0));
273:
+274: d = dist_pl(x0, y0, x1, y1, x2, y2)
__pyx_v_d = __pyx_f_4pept_10processing_13occupancy_ext_dist_pl(__pyx_v_x0, __pyx_v_y0, __pyx_v_x1, __pyx_v_y1, __pyx_v_x2, __pyx_v_y2);
+275: h = r - d
__pyx_v_h = (__pyx_v_r - __pyx_v_d);
276:
277: # Area of the circular segment
+278: area += circular_segment(r, h)
__pyx_v_area = (__pyx_v_area + __pyx_f_4pept_10processing_13occupancy_ext_circular_segment(__pyx_v_r, __pyx_v_h));
279:
280: # Area of the triangle
+281: area += dist(xc, yc, x1, y1) * dist(xc, yc, x2, y2) / 2
__pyx_v_area = (__pyx_v_area + ((__pyx_f_4pept_10processing_13occupancy_ext_dist(__pyx_v_xc, __pyx_v_yc, __pyx_v_x1, __pyx_v_y1) * __pyx_f_4pept_10processing_13occupancy_ext_dist(__pyx_v_xc, __pyx_v_yc, __pyx_v_x2, __pyx_v_y2)) / 2.0));
282:
+283: return area
__pyx_r = __pyx_v_area; goto __pyx_L0;
284:
285:
+286: cdef inline double two_corner(
static CYTHON_INLINE double __pyx_f_4pept_10processing_13occupancy_ext_two_corner(Py_ssize_t *__pyx_v_corners, double __pyx_v_px, double __pyx_v_py, double __pyx_v_xsize, double __pyx_v_ysize, double __pyx_v_x0, double __pyx_v_y0, double __pyx_v_r) { double __pyx_v_xc1; double __pyx_v_yc1; double __pyx_v_xc2; double __pyx_v_yc2; double __pyx_v_x1; double __pyx_v_y1; double __pyx_v_x2; double __pyx_v_y2; double __pyx_v_d; double __pyx_v_h; double __pyx_v_area; double __pyx_v_xmin; double __pyx_v_xmax; double __pyx_v_ymin; double __pyx_v_ymax; double __pyx_r; /* … */ /* function exit code */ __pyx_L0:; return __pyx_r; }
287: Py_ssize_t[4] corners,
288: double px,
289: double py,
290: double xsize,
291: double ysize,
292: double x0,
293: double y0,
294: double r,
295: ) nogil:
296: '''Compute the overlapping area between a circle and a rectangle when
297: exactly one of the rectangle's corners are inside the circle.
298:
299: Parameters
300: ----------
301: corners
302: Vector of 0 and 1 for the corner that is inside the circle. The
303: corners are in trigonometric order.
304:
305: px, py
306: The pixel x and y coordinates.
307:
308: xsize, ysize
309: The pixel width and height.
310:
311: x, y
312: The circle origin x and y coordinates
313:
314: r
315: The circle radius
316:
317: Returns
318: -------
319: The overlapping area.
320: '''
321:
322: # The bounded corner coordinates
+323: cdef double xc1 = 0, yc1 = 0, xc2 = 0, yc2 = 0
__pyx_v_xc1 = 0.0; __pyx_v_yc1 = 0.0; __pyx_v_xc2 = 0.0; __pyx_v_yc2 = 0.0;
324:
325: # The coords of the two intersections between the circle and the rectangle
+326: cdef double x1 = 0, y1 = 0, x2 = 0, y2 = 0
__pyx_v_x1 = 0.0; __pyx_v_y1 = 0.0; __pyx_v_x2 = 0.0; __pyx_v_y2 = 0.0;
327:
328: # Distance from circle centre x0, y0 to line defined by the two
329: # intersections above and h = (r - d)
330: cdef double d, h
331:
+332: cdef double area = 0.
__pyx_v_area = 0.;
333:
334: # Pixel boundaries
+335: cdef double xmin = px - xsize / 2
__pyx_v_xmin = (__pyx_v_px - (__pyx_v_xsize / 2.0));
+336: cdef double xmax = px + xsize / 2
__pyx_v_xmax = (__pyx_v_px + (__pyx_v_xsize / 2.0));
+337: cdef double ymin = py - ysize / 2
__pyx_v_ymin = (__pyx_v_py - (__pyx_v_ysize / 2.0));
+338: cdef double ymax = py + ysize / 2
__pyx_v_ymax = (__pyx_v_py + (__pyx_v_ysize / 2.0));
339:
340: # Bottom corners
+341: if corners[0] == 1 and corners[1] == 1:
__pyx_t_2 = (((__pyx_v_corners[0]) == 1) != 0); if (__pyx_t_2) { } else { __pyx_t_1 = __pyx_t_2; goto __pyx_L4_bool_binop_done; } __pyx_t_2 = (((__pyx_v_corners[1]) == 1) != 0); __pyx_t_1 = __pyx_t_2; __pyx_L4_bool_binop_done:; if (__pyx_t_1) { /* … */ goto __pyx_L3; }
+342: xc1 = xmin
__pyx_v_xc1 = __pyx_v_xmin;
+343: yc1 = ymin
__pyx_v_yc1 = __pyx_v_ymin;
344:
+345: xc2 = xmax
__pyx_v_xc2 = __pyx_v_xmax;
+346: yc2 = ymin
__pyx_v_yc2 = __pyx_v_ymin;
347:
+348: x1 = xc1
__pyx_v_x1 = __pyx_v_xc1;
+349: y1 = y0 + term(r, xc1, x0)
__pyx_v_y1 = (__pyx_v_y0 + __pyx_f_4pept_10processing_13occupancy_ext_term(__pyx_v_r, __pyx_v_xc1, __pyx_v_x0));
350:
+351: x2 = xc2
__pyx_v_x2 = __pyx_v_xc2;
+352: y2 = y0 + term(r, xc2, x0)
__pyx_v_y2 = (__pyx_v_y0 + __pyx_f_4pept_10processing_13occupancy_ext_term(__pyx_v_r, __pyx_v_xc2, __pyx_v_x0));
353:
354: # Top corners
+355: elif corners[2] == 1 and corners[3] == 1:
__pyx_t_2 = (((__pyx_v_corners[2]) == 1) != 0); if (__pyx_t_2) { } else { __pyx_t_1 = __pyx_t_2; goto __pyx_L6_bool_binop_done; } __pyx_t_2 = (((__pyx_v_corners[3]) == 1) != 0); __pyx_t_1 = __pyx_t_2; __pyx_L6_bool_binop_done:; if (__pyx_t_1) { /* … */ goto __pyx_L3; }
+356: xc1 = xmin
__pyx_v_xc1 = __pyx_v_xmin;
+357: yc1 = ymax
__pyx_v_yc1 = __pyx_v_ymax;
358:
+359: xc2 = xmax
__pyx_v_xc2 = __pyx_v_xmax;
+360: yc2 = ymax
__pyx_v_yc2 = __pyx_v_ymax;
361:
+362: x1 = xc1
__pyx_v_x1 = __pyx_v_xc1;
+363: y1 = y0 - term(r, xc1, x0)
__pyx_v_y1 = (__pyx_v_y0 - __pyx_f_4pept_10processing_13occupancy_ext_term(__pyx_v_r, __pyx_v_xc1, __pyx_v_x0));
364:
+365: x2 = xc2
__pyx_v_x2 = __pyx_v_xc2;
+366: y2 = y0 - term(r, xc2, x0)
__pyx_v_y2 = (__pyx_v_y0 - __pyx_f_4pept_10processing_13occupancy_ext_term(__pyx_v_r, __pyx_v_xc2, __pyx_v_x0));
367:
368: # Right corners
+369: elif corners[1] == 1 and corners[2] == 1:
__pyx_t_2 = (((__pyx_v_corners[1]) == 1) != 0); if (__pyx_t_2) { } else { __pyx_t_1 = __pyx_t_2; goto __pyx_L8_bool_binop_done; } __pyx_t_2 = (((__pyx_v_corners[2]) == 1) != 0); __pyx_t_1 = __pyx_t_2; __pyx_L8_bool_binop_done:; if (__pyx_t_1) { /* … */ goto __pyx_L3; }
+370: xc1 = xmax
__pyx_v_xc1 = __pyx_v_xmax;
+371: yc1 = ymin
__pyx_v_yc1 = __pyx_v_ymin;
372:
+373: xc2 = xmax
__pyx_v_xc2 = __pyx_v_xmax;
+374: yc2 = ymax
__pyx_v_yc2 = __pyx_v_ymax;
375:
+376: x1 = x0 - term(r, yc1, y0)
__pyx_v_x1 = (__pyx_v_x0 - __pyx_f_4pept_10processing_13occupancy_ext_term(__pyx_v_r, __pyx_v_yc1, __pyx_v_y0));
+377: y1 = yc1
__pyx_v_y1 = __pyx_v_yc1;
378:
+379: x2 = x0 - term(r, yc2, y0)
__pyx_v_x2 = (__pyx_v_x0 - __pyx_f_4pept_10processing_13occupancy_ext_term(__pyx_v_r, __pyx_v_yc2, __pyx_v_y0));
+380: y2 = yc2
__pyx_v_y2 = __pyx_v_yc2;
381:
382: # Left corners
+383: elif corners[0] == 1 and corners[3] == 1:
__pyx_t_2 = (((__pyx_v_corners[0]) == 1) != 0); if (__pyx_t_2) { } else { __pyx_t_1 = __pyx_t_2; goto __pyx_L10_bool_binop_done; } __pyx_t_2 = (((__pyx_v_corners[3]) == 1) != 0); __pyx_t_1 = __pyx_t_2; __pyx_L10_bool_binop_done:; if (__pyx_t_1) { /* … */ } __pyx_L3:;
+384: xc1 = xmin
__pyx_v_xc1 = __pyx_v_xmin;
+385: yc1 = ymin
__pyx_v_yc1 = __pyx_v_ymin;
386:
+387: xc2 = xmin
__pyx_v_xc2 = __pyx_v_xmin;
+388: yc2 = ymax
__pyx_v_yc2 = __pyx_v_ymax;
389:
+390: x1 = x0 + term(r, yc1, y0)
__pyx_v_x1 = (__pyx_v_x0 + __pyx_f_4pept_10processing_13occupancy_ext_term(__pyx_v_r, __pyx_v_yc1, __pyx_v_y0));
+391: y1 = yc1
__pyx_v_y1 = __pyx_v_yc1;
392:
+393: x2 = x0 + term(r, yc2, y0)
__pyx_v_x2 = (__pyx_v_x0 + __pyx_f_4pept_10processing_13occupancy_ext_term(__pyx_v_r, __pyx_v_yc2, __pyx_v_y0));
+394: y2 = yc2
__pyx_v_y2 = __pyx_v_yc2;
395:
+396: d = dist_pl(x0, y0, x1, y1, x2, y2)
__pyx_v_d = __pyx_f_4pept_10processing_13occupancy_ext_dist_pl(__pyx_v_x0, __pyx_v_y0, __pyx_v_x1, __pyx_v_y1, __pyx_v_x2, __pyx_v_y2);
+397: h = r - d
__pyx_v_h = (__pyx_v_r - __pyx_v_d);
398:
399: # Area of the circular segment
+400: area += circular_segment(r, h)
__pyx_v_area = (__pyx_v_area + __pyx_f_4pept_10processing_13occupancy_ext_circular_segment(__pyx_v_r, __pyx_v_h));
401:
402: # Area of triangle1 and triangle2
+403: area += triangle(x1, y1, xc2, yc2, xc1, yc1)
__pyx_v_area = (__pyx_v_area + __pyx_f_4pept_10processing_13occupancy_ext_triangle(__pyx_v_x1, __pyx_v_y1, __pyx_v_xc2, __pyx_v_yc2, __pyx_v_xc1, __pyx_v_yc1));
+404: area += triangle(x1, y1, xc2, yc2, x2, y2)
__pyx_v_area = (__pyx_v_area + __pyx_f_4pept_10processing_13occupancy_ext_triangle(__pyx_v_x1, __pyx_v_y1, __pyx_v_xc2, __pyx_v_yc2, __pyx_v_x2, __pyx_v_y2));
405:
+406: return area
__pyx_r = __pyx_v_area; goto __pyx_L0;
407:
408:
+409: cdef inline double three_corner(
static CYTHON_INLINE double __pyx_f_4pept_10processing_13occupancy_ext_three_corner(Py_ssize_t *__pyx_v_corners, double __pyx_v_px, double __pyx_v_py, double __pyx_v_xsize, double __pyx_v_ysize, double __pyx_v_x0, double __pyx_v_y0, double __pyx_v_r) { double __pyx_v_xc1; double __pyx_v_yc1; CYTHON_UNUSED double __pyx_v_xc2; CYTHON_UNUSED double __pyx_v_yc2; double __pyx_v_xc3; double __pyx_v_yc3; double __pyx_v_xc4; double __pyx_v_yc4; double __pyx_v_x1; double __pyx_v_y1; double __pyx_v_x2; double __pyx_v_y2; double __pyx_v_d; double __pyx_v_h; double __pyx_v_area; double __pyx_v_xmin; double __pyx_v_xmax; double __pyx_v_ymin; double __pyx_v_ymax; double __pyx_r; /* … */ /* function exit code */ __pyx_L0:; return __pyx_r; }
410: Py_ssize_t[4] corners,
411: double px,
412: double py,
413: double xsize,
414: double ysize,
415: double x0,
416: double y0,
417: double r,
418: ) nogil:
419: '''Compute the overlapping area between a circle and a rectangle when
420: exactly one of the rectangle's corners are inside the circle.
421:
422: Parameters
423: ----------
424: corners
425: Vector of 0 and 1 for the corner that is inside the circle. The
426: corners are in trigonometric order.
427:
428: px, py
429: The pixel x and y coordinates.
430:
431: xsize, ysize
432: The pixel width and height.
433:
434: x, y
435: The circle origin x and y coordinates
436:
437: r
438: The circle radius
439:
440: Returns
441: -------
442: The overlapping area.
443: '''
444:
445: # The bounded corner coordinates
+446: cdef double xc1 = 0, yc1 = 0, xc2 = 0, yc2 = 0
__pyx_v_xc1 = 0.0; __pyx_v_yc1 = 0.0; __pyx_v_xc2 = 0.0; __pyx_v_yc2 = 0.0;
+447: cdef double xc3 = 0, yc3 = 0, xc4 = 0, yc4 = 0
__pyx_v_xc3 = 0.0; __pyx_v_yc3 = 0.0; __pyx_v_xc4 = 0.0; __pyx_v_yc4 = 0.0;
448:
449: # The coords of the two intersections between the circle and the rectangle
+450: cdef double x1 = 0, y1 = 0, x2 = 0, y2 = 0
__pyx_v_x1 = 0.0; __pyx_v_y1 = 0.0; __pyx_v_x2 = 0.0; __pyx_v_y2 = 0.0;
451:
452: # Distance from circle centre x0, y0 to line defined by the two
453: # intersections above and h = (r - d)
454: cdef double d, h
455:
+456: cdef double area = 0.
__pyx_v_area = 0.;
457:
458: # Pixel boundaries
+459: cdef double xmin = px - xsize / 2
__pyx_v_xmin = (__pyx_v_px - (__pyx_v_xsize / 2.0));
+460: cdef double xmax = px + xsize / 2
__pyx_v_xmax = (__pyx_v_px + (__pyx_v_xsize / 2.0));
+461: cdef double ymin = py - ysize / 2
__pyx_v_ymin = (__pyx_v_py - (__pyx_v_ysize / 2.0));
+462: cdef double ymax = py + ysize / 2
__pyx_v_ymax = (__pyx_v_py + (__pyx_v_ysize / 2.0));
463:
464: # Bottom right three corners
+465: if corners[0] == 1 and corners[1] == 1 and corners[2] == 1:
__pyx_t_2 = (((__pyx_v_corners[0]) == 1) != 0); if (__pyx_t_2) { } else { __pyx_t_1 = __pyx_t_2; goto __pyx_L4_bool_binop_done; } __pyx_t_2 = (((__pyx_v_corners[1]) == 1) != 0); if (__pyx_t_2) { } else { __pyx_t_1 = __pyx_t_2; goto __pyx_L4_bool_binop_done; } __pyx_t_2 = (((__pyx_v_corners[2]) == 1) != 0); __pyx_t_1 = __pyx_t_2; __pyx_L4_bool_binop_done:; if (__pyx_t_1) { /* … */ goto __pyx_L3; }
+466: xc1 = xmin
__pyx_v_xc1 = __pyx_v_xmin;
+467: yc1 = ymin
__pyx_v_yc1 = __pyx_v_ymin;
468:
+469: xc2 = xmax
__pyx_v_xc2 = __pyx_v_xmax;
+470: yc2 = ymin
__pyx_v_yc2 = __pyx_v_ymin;
471:
+472: xc3 = xmax
__pyx_v_xc3 = __pyx_v_xmax;
+473: yc3 = ymax
__pyx_v_yc3 = __pyx_v_ymax;
474:
+475: xc4 = xmin # Corner outside
__pyx_v_xc4 = __pyx_v_xmin;
+476: yc4 = ymax # Corner outside
__pyx_v_yc4 = __pyx_v_ymax;
477:
+478: x1 = x0 - term(r, yc3, y0)
__pyx_v_x1 = (__pyx_v_x0 - __pyx_f_4pept_10processing_13occupancy_ext_term(__pyx_v_r, __pyx_v_yc3, __pyx_v_y0));
+479: y1 = yc3
__pyx_v_y1 = __pyx_v_yc3;
480:
+481: x2 = xc1
__pyx_v_x2 = __pyx_v_xc1;
+482: y2 = y0 + term(r, xc1, x0)
__pyx_v_y2 = (__pyx_v_y0 + __pyx_f_4pept_10processing_13occupancy_ext_term(__pyx_v_r, __pyx_v_xc1, __pyx_v_x0));
483:
484: # Top right three corners
+485: elif corners[1] == 1 and corners[2] == 1 and corners[3] == 1:
__pyx_t_2 = (((__pyx_v_corners[1]) == 1) != 0); if (__pyx_t_2) { } else { __pyx_t_1 = __pyx_t_2; goto __pyx_L7_bool_binop_done; } __pyx_t_2 = (((__pyx_v_corners[2]) == 1) != 0); if (__pyx_t_2) { } else { __pyx_t_1 = __pyx_t_2; goto __pyx_L7_bool_binop_done; } __pyx_t_2 = (((__pyx_v_corners[3]) == 1) != 0); __pyx_t_1 = __pyx_t_2; __pyx_L7_bool_binop_done:; if (__pyx_t_1) { /* … */ goto __pyx_L3; }
+486: xc1 = xmax
__pyx_v_xc1 = __pyx_v_xmax;
+487: yc1 = ymin
__pyx_v_yc1 = __pyx_v_ymin;
488:
+489: xc2 = xmax
__pyx_v_xc2 = __pyx_v_xmax;
+490: yc2 = ymax
__pyx_v_yc2 = __pyx_v_ymax;
491:
+492: xc3 = xmin
__pyx_v_xc3 = __pyx_v_xmin;
+493: yc3 = ymax
__pyx_v_yc3 = __pyx_v_ymax;
494:
+495: xc4 = xmin # Corner outside
__pyx_v_xc4 = __pyx_v_xmin;
+496: yc4 = ymin # Corner outside
__pyx_v_yc4 = __pyx_v_ymin;
497:
+498: x1 = xc3
__pyx_v_x1 = __pyx_v_xc3;
+499: y1 = y0 - term(r, xc3, x0)
__pyx_v_y1 = (__pyx_v_y0 - __pyx_f_4pept_10processing_13occupancy_ext_term(__pyx_v_r, __pyx_v_xc3, __pyx_v_x0));
500:
+501: x2 = x0 - term(r, yc1, y0)
__pyx_v_x2 = (__pyx_v_x0 - __pyx_f_4pept_10processing_13occupancy_ext_term(__pyx_v_r, __pyx_v_yc1, __pyx_v_y0));
+502: y2 = yc1
__pyx_v_y2 = __pyx_v_yc1;
503:
504: # Top left three corners
+505: elif corners[2] == 1 and corners[3] == 1 and corners[0] == 1:
__pyx_t_2 = (((__pyx_v_corners[2]) == 1) != 0); if (__pyx_t_2) { } else { __pyx_t_1 = __pyx_t_2; goto __pyx_L10_bool_binop_done; } __pyx_t_2 = (((__pyx_v_corners[3]) == 1) != 0); if (__pyx_t_2) { } else { __pyx_t_1 = __pyx_t_2; goto __pyx_L10_bool_binop_done; } __pyx_t_2 = (((__pyx_v_corners[0]) == 1) != 0); __pyx_t_1 = __pyx_t_2; __pyx_L10_bool_binop_done:; if (__pyx_t_1) { /* … */ goto __pyx_L3; }
+506: xc1 = xmax
__pyx_v_xc1 = __pyx_v_xmax;
+507: yc1 = ymax
__pyx_v_yc1 = __pyx_v_ymax;
508:
+509: xc2 = xmin
__pyx_v_xc2 = __pyx_v_xmin;
+510: yc2 = ymax
__pyx_v_yc2 = __pyx_v_ymax;
511:
+512: xc3 = xmin
__pyx_v_xc3 = __pyx_v_xmin;
+513: yc3 = ymin
__pyx_v_yc3 = __pyx_v_ymin;
514:
+515: xc4 = xmax # Corner outside
__pyx_v_xc4 = __pyx_v_xmax;
+516: yc4 = ymin # Corner outside
__pyx_v_yc4 = __pyx_v_ymin;
517:
+518: x1 = xc1
__pyx_v_x1 = __pyx_v_xc1;
+519: y1 = y0 - term(r, xc1, x0)
__pyx_v_y1 = (__pyx_v_y0 - __pyx_f_4pept_10processing_13occupancy_ext_term(__pyx_v_r, __pyx_v_xc1, __pyx_v_x0));
520:
+521: x2 = x0 + term(r, yc3, y0)
__pyx_v_x2 = (__pyx_v_x0 + __pyx_f_4pept_10processing_13occupancy_ext_term(__pyx_v_r, __pyx_v_yc3, __pyx_v_y0));
+522: y2 = yc3
__pyx_v_y2 = __pyx_v_yc3;
523:
524: # Bottom left three corners
+525: elif corners[0] == 1 and corners[1] == 1 and corners[3] == 1:
__pyx_t_2 = (((__pyx_v_corners[0]) == 1) != 0); if (__pyx_t_2) { } else { __pyx_t_1 = __pyx_t_2; goto __pyx_L13_bool_binop_done; } __pyx_t_2 = (((__pyx_v_corners[1]) == 1) != 0); if (__pyx_t_2) { } else { __pyx_t_1 = __pyx_t_2; goto __pyx_L13_bool_binop_done; } __pyx_t_2 = (((__pyx_v_corners[3]) == 1) != 0); __pyx_t_1 = __pyx_t_2; __pyx_L13_bool_binop_done:; if (__pyx_t_1) { /* … */ } __pyx_L3:;
+526: xc1 = xmin
__pyx_v_xc1 = __pyx_v_xmin;
+527: yc1 = ymax
__pyx_v_yc1 = __pyx_v_ymax;
528:
+529: xc2 = xmin
__pyx_v_xc2 = __pyx_v_xmin;
+530: yc2 = ymin
__pyx_v_yc2 = __pyx_v_ymin;
531:
+532: xc3 = xmax
__pyx_v_xc3 = __pyx_v_xmax;
+533: yc3 = ymin
__pyx_v_yc3 = __pyx_v_ymin;
534:
+535: xc4 = xmax # Corner outside
__pyx_v_xc4 = __pyx_v_xmax;
+536: yc4 = ymax # Corner outside
__pyx_v_yc4 = __pyx_v_ymax;
537:
+538: x1 = xc3
__pyx_v_x1 = __pyx_v_xc3;
+539: y1 = y0 + term(r, xc3, x0)
__pyx_v_y1 = (__pyx_v_y0 + __pyx_f_4pept_10processing_13occupancy_ext_term(__pyx_v_r, __pyx_v_xc3, __pyx_v_x0));
540:
+541: x2 = x0 + term(r, yc1, y0)
__pyx_v_x2 = (__pyx_v_x0 + __pyx_f_4pept_10processing_13occupancy_ext_term(__pyx_v_r, __pyx_v_yc1, __pyx_v_y0));
+542: y2 = yc1
__pyx_v_y2 = __pyx_v_yc1;
543:
+544: d = dist_pl(x0, y0, x1, y1, x2, y2)
__pyx_v_d = __pyx_f_4pept_10processing_13occupancy_ext_dist_pl(__pyx_v_x0, __pyx_v_y0, __pyx_v_x1, __pyx_v_y1, __pyx_v_x2, __pyx_v_y2);
+545: h = r - d
__pyx_v_h = (__pyx_v_r - __pyx_v_d);
546:
547: # Area of the circular segment
+548: area += circular_segment(r, h)
__pyx_v_area = (__pyx_v_area + __pyx_f_4pept_10processing_13occupancy_ext_circular_segment(__pyx_v_r, __pyx_v_h));
549:
550: # Area of the rectangle
+551: area += xsize * ysize
__pyx_v_area = (__pyx_v_area + (__pyx_v_xsize * __pyx_v_ysize));
552:
553: # Area of triangle
+554: area -= dist(x1, y1, xc4, yc4) * dist(x2, y2, xc4, yc4) / 2
__pyx_v_area = (__pyx_v_area - ((__pyx_f_4pept_10processing_13occupancy_ext_dist(__pyx_v_x1, __pyx_v_y1, __pyx_v_xc4, __pyx_v_yc4) * __pyx_f_4pept_10processing_13occupancy_ext_dist(__pyx_v_x2, __pyx_v_y2, __pyx_v_xc4, __pyx_v_yc4)) / 2.0));
555:
+556: return area
__pyx_r = __pyx_v_area; goto __pyx_L0;
557:
558:
+559: cdef inline double four_corner(
static CYTHON_INLINE double __pyx_f_4pept_10processing_13occupancy_ext_four_corner(CYTHON_UNUSED Py_ssize_t *__pyx_v_corners, CYTHON_UNUSED double __pyx_v_px, CYTHON_UNUSED double __pyx_v_py, double __pyx_v_xsize, double __pyx_v_ysize, CYTHON_UNUSED double __pyx_v_x0, CYTHON_UNUSED double __pyx_v_y0, CYTHON_UNUSED double __pyx_v_r) { double __pyx_r; /* … */ /* function exit code */ __pyx_L0:; return __pyx_r; }
560: Py_ssize_t[4] corners,
561: double px,
562: double py,
563: double xsize,
564: double ysize,
565: double x0,
566: double y0,
567: double r,
568: ) nogil:
569: '''Compute the overlapping area between a circle and a rectangle when
570: exactly one of the rectangle's corners are inside the circle.
571:
572: Parameters
573: ----------
574: corners
575: Vector of 0 and 1 for the corner that is inside the circle. The
576: corners are in trigonometric order.
577:
578: px, py
579: The pixel x and y coordinates.
580:
581: xsize, ysize
582: The pixel width and height.
583:
584: x, y
585: The circle origin x and y coordinates
586:
587: r
588: The circle radius
589:
590: Returns
591: -------
592: The overlapping area.
593: '''
594:
+595: return xsize * ysize
__pyx_r = (__pyx_v_xsize * __pyx_v_ysize); goto __pyx_L0;
596:
597:
598:
+599: cpdef void occupancy2d_ext(
static PyObject *__pyx_pw_4pept_10processing_13occupancy_ext_1occupancy2d_ext(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/ static void __pyx_f_4pept_10processing_13occupancy_ext_occupancy2d_ext(__Pyx_memviewslice __pyx_v_pixels, __Pyx_memviewslice __pyx_v_positions, __Pyx_memviewslice __pyx_v_radii, __Pyx_memviewslice __pyx_v_xlim, __Pyx_memviewslice __pyx_v_ylim, CYTHON_UNUSED int __pyx_skip_dispatch) { Py_ssize_t __pyx_v_nrows; Py_ssize_t __pyx_v_nx; Py_ssize_t __pyx_v_ny; double __pyx_v_xsize; double __pyx_v_ysize; double __pyx_v_x; double __pyx_v_y; double __pyx_v_r; double __pyx_v_px; double __pyx_v_py; Py_ssize_t __pyx_v_min_nx; Py_ssize_t __pyx_v_max_nx; Py_ssize_t __pyx_v_min_ny; Py_ssize_t __pyx_v_max_ny; Py_ssize_t __pyx_v_num_corners; Py_ssize_t __pyx_v_corners[4]; Py_ssize_t __pyx_v_i; Py_ssize_t __pyx_v_j; Py_ssize_t __pyx_v_k; Py_ssize_t __pyx_v_l; /* … */ /* function exit code */ } /* Python wrapper */ static PyObject *__pyx_pw_4pept_10processing_13occupancy_ext_1occupancy2d_ext(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/ static char __pyx_doc_4pept_10processing_13occupancy_ext_occupancy2d_ext[] = "occupancy2d_ext(double[:, :] pixels, double[:, :] positions, double[:] radii, double[:] xlim, double[:] ylim) -> void\nCompute the 2D occupancy of circles of different radii.\n\n ::\n\n Function signature:\n\n void occupancy2d_ext(\n double[:, :] pixels,\n double[:, :] positions,\n double[:] radii,\n double[:] xlim,\n double[:] ylim,\n ) nogil\n\n This corresponds to the pixellisation of circular particles, such that\n each pixel's value corresponds to the area covered by the particle.\n\n It is important that all parameters sent to this function are initialised\n properly. Please see the parameters below, or the function *will* segfault.\n Alternatively, use the `pept.processing.occupancy2d` function which is\n more robust and initialises all parameters for you.\n\n Parameters\n ----------\n pixels: (M, N) numpy.ndarray[ndim = 2, dtype = numpy.float64]\n The 2D grid of pixels, initialised to zero. It can be created with\n `numpy.zeros((nrows, ncols))`.\n\n positions: (P, 2) numpy.ndarray[ndim = 2, dtype = numpy.float64]\n The particles' 2D positions, where all rows are formatted as\n `[x_coordinate, y_coordinate]`.\n\n radii: (P,) numpy.ndarray[ndim = 1, dtype = numpy.float64]\n The radii of each particle. It must have the same length as\n `positions`.\n\n xlim: (2,) numpy.ndarray[ndim = 1, dtype = numpy.float64]\n The limits of the system over which the pixels span in the\n x-dimension, formatted as [xmin, xmax].\n\n ylim: (2,) numpy.ndarray[ndim = 1, dtype = numpy.float64]\n The limits of the system over which the pixels span in the\n y-dimension, formatted as [ymin, ymax].\n\n "; static PyObject *__pyx_pw_4pept_10processing_13occupancy_ext_1occupancy2d_ext(PyObject *__pyx_self, PyObject *__pyx_args, PyObject *__pyx_kwds) { __Pyx_memviewslice __pyx_v_pixels = { 0, 0, { 0 }, { 0 }, { 0 } }; __Pyx_memviewslice __pyx_v_positions = { 0, 0, { 0 }, { 0 }, { 0 } }; __Pyx_memviewslice __pyx_v_radii = { 0, 0, { 0 }, { 0 }, { 0 } }; __Pyx_memviewslice __pyx_v_xlim = { 0, 0, { 0 }, { 0 }, { 0 } }; __Pyx_memviewslice __pyx_v_ylim = { 0, 0, { 0 }, { 0 }, { 0 } }; PyObject *__pyx_r = 0; __Pyx_RefNannyDeclarations __Pyx_RefNannySetupContext("occupancy2d_ext (wrapper)", 0); { static PyObject **__pyx_pyargnames[] = {&__pyx_n_s_pixels,&__pyx_n_s_positions,&__pyx_n_s_radii,&__pyx_n_s_xlim,&__pyx_n_s_ylim,0}; PyObject* values[5] = {0,0,0,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 5: values[4] = PyTuple_GET_ITEM(__pyx_args, 4); CYTHON_FALLTHROUGH; case 4: values[3] = PyTuple_GET_ITEM(__pyx_args, 3); CYTHON_FALLTHROUGH; case 3: values[2] = PyTuple_GET_ITEM(__pyx_args, 2); CYTHON_FALLTHROUGH; 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_pixels)) != 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_positions)) != 0)) kw_args--; else { __Pyx_RaiseArgtupleInvalid("occupancy2d_ext", 1, 5, 5, 1); __PYX_ERR(0, 599, __pyx_L3_error) } CYTHON_FALLTHROUGH; case 2: if (likely((values[2] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_radii)) != 0)) kw_args--; else { __Pyx_RaiseArgtupleInvalid("occupancy2d_ext", 1, 5, 5, 2); __PYX_ERR(0, 599, __pyx_L3_error) } CYTHON_FALLTHROUGH; case 3: if (likely((values[3] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_xlim)) != 0)) kw_args--; else { __Pyx_RaiseArgtupleInvalid("occupancy2d_ext", 1, 5, 5, 3); __PYX_ERR(0, 599, __pyx_L3_error) } CYTHON_FALLTHROUGH; case 4: if (likely((values[4] = __Pyx_PyDict_GetItemStr(__pyx_kwds, __pyx_n_s_ylim)) != 0)) kw_args--; else { __Pyx_RaiseArgtupleInvalid("occupancy2d_ext", 1, 5, 5, 4); __PYX_ERR(0, 599, __pyx_L3_error) } } if (unlikely(kw_args > 0)) { if (unlikely(__Pyx_ParseOptionalKeywords(__pyx_kwds, __pyx_pyargnames, 0, values, pos_args, "occupancy2d_ext") < 0)) __PYX_ERR(0, 599, __pyx_L3_error) } } else if (PyTuple_GET_SIZE(__pyx_args) != 5) { goto __pyx_L5_argtuple_error; } else { values[0] = PyTuple_GET_ITEM(__pyx_args, 0); values[1] = PyTuple_GET_ITEM(__pyx_args, 1); values[2] = PyTuple_GET_ITEM(__pyx_args, 2); values[3] = PyTuple_GET_ITEM(__pyx_args, 3); values[4] = PyTuple_GET_ITEM(__pyx_args, 4); } __pyx_v_pixels = __Pyx_PyObject_to_MemoryviewSlice_dsds_double(values[0], PyBUF_WRITABLE); if (unlikely(!__pyx_v_pixels.memview)) __PYX_ERR(0, 600, __pyx_L3_error) __pyx_v_positions = __Pyx_PyObject_to_MemoryviewSlice_dsds_double(values[1], PyBUF_WRITABLE); if (unlikely(!__pyx_v_positions.memview)) __PYX_ERR(0, 601, __pyx_L3_error) __pyx_v_radii = __Pyx_PyObject_to_MemoryviewSlice_ds_double(values[2], PyBUF_WRITABLE); if (unlikely(!__pyx_v_radii.memview)) __PYX_ERR(0, 602, __pyx_L3_error) __pyx_v_xlim = __Pyx_PyObject_to_MemoryviewSlice_ds_double(values[3], PyBUF_WRITABLE); if (unlikely(!__pyx_v_xlim.memview)) __PYX_ERR(0, 603, __pyx_L3_error) __pyx_v_ylim = __Pyx_PyObject_to_MemoryviewSlice_ds_double(values[4], PyBUF_WRITABLE); if (unlikely(!__pyx_v_ylim.memview)) __PYX_ERR(0, 604, __pyx_L3_error) } goto __pyx_L4_argument_unpacking_done; __pyx_L5_argtuple_error:; __Pyx_RaiseArgtupleInvalid("occupancy2d_ext", 1, 5, 5, PyTuple_GET_SIZE(__pyx_args)); __PYX_ERR(0, 599, __pyx_L3_error) __pyx_L3_error:; __Pyx_AddTraceback("pept.processing.occupancy_ext.occupancy2d_ext", __pyx_clineno, __pyx_lineno, __pyx_filename); __Pyx_RefNannyFinishContext(); return NULL; __pyx_L4_argument_unpacking_done:; __pyx_r = __pyx_pf_4pept_10processing_13occupancy_ext_occupancy2d_ext(__pyx_self, __pyx_v_pixels, __pyx_v_positions, __pyx_v_radii, __pyx_v_xlim, __pyx_v_ylim); 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_10processing_13occupancy_ext_occupancy2d_ext(CYTHON_UNUSED PyObject *__pyx_self, __Pyx_memviewslice __pyx_v_pixels, __Pyx_memviewslice __pyx_v_positions, __Pyx_memviewslice __pyx_v_radii, __Pyx_memviewslice __pyx_v_xlim, __Pyx_memviewslice __pyx_v_ylim) { PyObject *__pyx_r = NULL; __Pyx_RefNannyDeclarations __Pyx_RefNannySetupContext("occupancy2d_ext", 0); __Pyx_XDECREF(__pyx_r); __pyx_t_1 = __Pyx_void_to_None(__pyx_f_4pept_10processing_13occupancy_ext_occupancy2d_ext(__pyx_v_pixels, __pyx_v_positions, __pyx_v_radii, __pyx_v_xlim, __pyx_v_ylim, 0)); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 599, __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.processing.occupancy_ext.occupancy2d_ext", __pyx_clineno, __pyx_lineno, __pyx_filename); __pyx_r = NULL; __pyx_L0:; __PYX_XDEC_MEMVIEW(&__pyx_v_pixels, 1); __PYX_XDEC_MEMVIEW(&__pyx_v_positions, 1); __PYX_XDEC_MEMVIEW(&__pyx_v_radii, 1); __PYX_XDEC_MEMVIEW(&__pyx_v_xlim, 1); __PYX_XDEC_MEMVIEW(&__pyx_v_ylim, 1); __Pyx_XGIVEREF(__pyx_r); __Pyx_RefNannyFinishContext(); return __pyx_r; }
600: double[:, :] pixels,
601: double[:, :] positions,
602: double[:] radii,
603: double[:] xlim,
604: double[:] ylim,
605: ) nogil:
606: '''Compute the 2D occupancy of circles of different radii.
607:
608: ::
609:
610: Function signature:
611:
612: void occupancy2d_ext(
613: double[:, :] pixels,
614: double[:, :] positions,
615: double[:] radii,
616: double[:] xlim,
617: double[:] ylim,
618: ) nogil
619:
620: This corresponds to the pixellisation of circular particles, such that
621: each pixel's value corresponds to the area covered by the particle.
622:
623: It is important that all parameters sent to this function are initialised
624: properly. Please see the parameters below, or the function *will* segfault.
625: Alternatively, use the `pept.processing.occupancy2d` function which is
626: more robust and initialises all parameters for you.
627:
628: Parameters
629: ----------
630: pixels: (M, N) numpy.ndarray[ndim = 2, dtype = numpy.float64]
631: The 2D grid of pixels, initialised to zero. It can be created with
632: `numpy.zeros((nrows, ncols))`.
633:
634: positions: (P, 2) numpy.ndarray[ndim = 2, dtype = numpy.float64]
635: The particles' 2D positions, where all rows are formatted as
636: `[x_coordinate, y_coordinate]`.
637:
638: radii: (P,) numpy.ndarray[ndim = 1, dtype = numpy.float64]
639: The radii of each particle. It must have the same length as
640: `positions`.
641:
642: xlim: (2,) numpy.ndarray[ndim = 1, dtype = numpy.float64]
643: The limits of the system over which the pixels span in the
644: x-dimension, formatted as [xmin, xmax].
645:
646: ylim: (2,) numpy.ndarray[ndim = 1, dtype = numpy.float64]
647: The limits of the system over which the pixels span in the
648: y-dimension, formatted as [ymin, ymax].
649:
650: '''
+651: cdef Py_ssize_t nrows = positions.shape[0]
__pyx_v_nrows = (__pyx_v_positions.shape[0]);
652:
+653: cdef Py_ssize_t nx = pixels.shape[0]
__pyx_v_nx = (__pyx_v_pixels.shape[0]);
+654: cdef Py_ssize_t ny = pixels.shape[1]
__pyx_v_ny = (__pyx_v_pixels.shape[1]);
655:
+656: cdef double xsize = (xlim[1] - xlim[0]) / nx
__pyx_t_1 = 1; __pyx_t_2 = 0; __pyx_v_xsize = (((*((double *) ( /* dim=0 */ (__pyx_v_xlim.data + __pyx_t_1 * __pyx_v_xlim.strides[0]) ))) - (*((double *) ( /* dim=0 */ (__pyx_v_xlim.data + __pyx_t_2 * __pyx_v_xlim.strides[0]) )))) / ((double)__pyx_v_nx));
+657: cdef double ysize = (ylim[1] - ylim[0]) / ny
__pyx_t_2 = 1; __pyx_t_1 = 0; __pyx_v_ysize = (((*((double *) ( /* dim=0 */ (__pyx_v_ylim.data + __pyx_t_2 * __pyx_v_ylim.strides[0]) ))) - (*((double *) ( /* dim=0 */ (__pyx_v_ylim.data + __pyx_t_1 * __pyx_v_ylim.strides[0]) )))) / ((double)__pyx_v_ny));
658:
659: # print((
660: # f"nrows = {nrows}\n"
661: # f"nx = {nx}\n"
662: # f"ny = {ny}\n"
663: # f"xsize = {xsize}\n"
664: # f"ysize = {ysize}\n"
665: # ))
666:
667: cdef double x, y, r # Particle x, y, radius
668: cdef double px, py # Pixel centre x, y
669:
670: cdef Py_ssize_t min_nx, max_nx
671: cdef Py_ssize_t min_ny, max_ny
672:
673: cdef Py_ssize_t num_corners # Number of intersected corners
674: cdef Py_ssize_t[4] corners # Intersected corners indices
675:
676: cdef Py_ssize_t i, j, k, l
677:
+678: for i in range(nrows):
__pyx_t_3 = __pyx_v_nrows; __pyx_t_4 = __pyx_t_3; for (__pyx_t_5 = 0; __pyx_t_5 < __pyx_t_4; __pyx_t_5+=1) { __pyx_v_i = __pyx_t_5;
679: # Aliases
+680: x = positions[i, 0]
__pyx_t_1 = __pyx_v_i; __pyx_t_2 = 0; __pyx_v_x = (*((double *) ( /* dim=1 */ (( /* dim=0 */ (__pyx_v_positions.data + __pyx_t_1 * __pyx_v_positions.strides[0]) ) + __pyx_t_2 * __pyx_v_positions.strides[1]) )));
+681: y = positions[i, 1]
__pyx_t_2 = __pyx_v_i; __pyx_t_1 = 1; __pyx_v_y = (*((double *) ( /* dim=1 */ (( /* dim=0 */ (__pyx_v_positions.data + __pyx_t_2 * __pyx_v_positions.strides[0]) ) + __pyx_t_1 * __pyx_v_positions.strides[1]) )));
+682: r = radii[i]
__pyx_t_1 = __pyx_v_i; __pyx_v_r = (*((double *) ( /* dim=0 */ (__pyx_v_radii.data + __pyx_t_1 * __pyx_v_radii.strides[0]) )));
683:
+684: if r == 0:
__pyx_t_6 = ((__pyx_v_r == 0.0) != 0); if (__pyx_t_6) { /* … */ }
+685: if x == xlim[1]:
__pyx_t_1 = 1; __pyx_t_6 = ((__pyx_v_x == (*((double *) ( /* dim=0 */ (__pyx_v_xlim.data + __pyx_t_1 * __pyx_v_xlim.strides[0]) )))) != 0); if (__pyx_t_6) { /* … */ goto __pyx_L6; }
+686: min_nx = nx - 1
__pyx_v_min_nx = (__pyx_v_nx - 1);
687: else:
+688: min_nx = <Py_ssize_t>floor((x - xlim[0]) / xsize)
/*else*/ { __pyx_t_1 = 0; __pyx_v_min_nx = ((Py_ssize_t)floor(((__pyx_v_x - (*((double *) ( /* dim=0 */ (__pyx_v_xlim.data + __pyx_t_1 * __pyx_v_xlim.strides[0]) )))) / __pyx_v_xsize))); } __pyx_L6:;
689:
+690: if y == ylim[1]:
__pyx_t_1 = 1; __pyx_t_6 = ((__pyx_v_y == (*((double *) ( /* dim=0 */ (__pyx_v_ylim.data + __pyx_t_1 * __pyx_v_ylim.strides[0]) )))) != 0); if (__pyx_t_6) { /* … */ goto __pyx_L7; }
+691: min_ny = ny - 1
__pyx_v_min_ny = (__pyx_v_ny - 1);
692: else:
+693: min_ny = <Py_ssize_t>floor((y - ylim[0]) / ysize)
/*else*/ { __pyx_t_1 = 0; __pyx_v_min_ny = ((Py_ssize_t)floor(((__pyx_v_y - (*((double *) ( /* dim=0 */ (__pyx_v_ylim.data + __pyx_t_1 * __pyx_v_ylim.strides[0]) )))) / __pyx_v_ysize))); } __pyx_L7:;
694:
+695: if min_nx >= nx or min_nx < 0:
__pyx_t_7 = ((__pyx_v_min_nx >= __pyx_v_nx) != 0); if (!__pyx_t_7) { } else { __pyx_t_6 = __pyx_t_7; goto __pyx_L9_bool_binop_done; } __pyx_t_7 = ((__pyx_v_min_nx < 0) != 0); __pyx_t_6 = __pyx_t_7; __pyx_L9_bool_binop_done:; if (__pyx_t_6) { /* … */ }
+696: continue
goto __pyx_L3_continue;
+697: if min_ny >= ny or min_ny < 0:
__pyx_t_7 = ((__pyx_v_min_ny >= __pyx_v_ny) != 0); if (!__pyx_t_7) { } else { __pyx_t_6 = __pyx_t_7; goto __pyx_L12_bool_binop_done; } __pyx_t_7 = ((__pyx_v_min_ny < 0) != 0); __pyx_t_6 = __pyx_t_7; __pyx_L12_bool_binop_done:; if (__pyx_t_6) { /* … */ }
+698: continue
goto __pyx_L3_continue;
699:
+700: pixels[min_nx, min_ny] += 1
__pyx_t_1 = __pyx_v_min_nx; __pyx_t_2 = __pyx_v_min_ny; *((double *) ( /* dim=1 */ (( /* dim=0 */ (__pyx_v_pixels.data + __pyx_t_1 * __pyx_v_pixels.strides[0]) ) + __pyx_t_2 * __pyx_v_pixels.strides[1]) )) += 1.0;
+701: continue
goto __pyx_L3_continue;
702:
703: # Find minimum and maximum pixel indices over which the particle spans.
704: # This corresponds to the intersected cells
+705: min_nx = <Py_ssize_t>floor((x - r - xlim[0]) / xsize)
__pyx_t_2 = 0; __pyx_v_min_nx = ((Py_ssize_t)floor((((__pyx_v_x - __pyx_v_r) - (*((double *) ( /* dim=0 */ (__pyx_v_xlim.data + __pyx_t_2 * __pyx_v_xlim.strides[0]) )))) / __pyx_v_xsize)));
+706: max_nx = <Py_ssize_t>floor((x + r - xlim[0]) / xsize)
__pyx_t_2 = 0; __pyx_v_max_nx = ((Py_ssize_t)floor((((__pyx_v_x + __pyx_v_r) - (*((double *) ( /* dim=0 */ (__pyx_v_xlim.data + __pyx_t_2 * __pyx_v_xlim.strides[0]) )))) / __pyx_v_xsize)));
707:
+708: min_ny = <Py_ssize_t>floor((y - r - ylim[0]) / ysize)
__pyx_t_2 = 0; __pyx_v_min_ny = ((Py_ssize_t)floor((((__pyx_v_y - __pyx_v_r) - (*((double *) ( /* dim=0 */ (__pyx_v_ylim.data + __pyx_t_2 * __pyx_v_ylim.strides[0]) )))) / __pyx_v_ysize)));
+709: max_ny = <Py_ssize_t>floor((y + r - ylim[0]) / ysize)
__pyx_t_2 = 0; __pyx_v_max_ny = ((Py_ssize_t)floor((((__pyx_v_y + __pyx_v_r) - (*((double *) ( /* dim=0 */ (__pyx_v_ylim.data + __pyx_t_2 * __pyx_v_ylim.strides[0]) )))) / __pyx_v_ysize)));
710:
711: # print((
712: # "Before thresholding\n"
713: # f"x = {x}\n"
714: # f"y = {y}\n"
715: # f"r = {r}\n"
716: # f"min_nx = {min_nx}\n"
717: # f"max_nx = {max_nx}\n"
718: # f"min_ny = {min_ny}\n"
719: # f"max_ny = {max_ny}\n"
720: # ))
721:
722: # Check pixel indices are within the system bounds
+723: if min_nx >= nx:
__pyx_t_6 = ((__pyx_v_min_nx >= __pyx_v_nx) != 0); if (__pyx_t_6) { /* … */ }
+724: continue
goto __pyx_L3_continue;
+725: elif min_nx < 0:
__pyx_t_6 = ((__pyx_v_min_nx < 0) != 0); if (__pyx_t_6) { /* … */ }
+726: min_nx = 0
__pyx_v_min_nx = 0;
727:
+728: if max_nx < 0:
__pyx_t_6 = ((__pyx_v_max_nx < 0) != 0); if (__pyx_t_6) { /* … */ }
+729: continue
goto __pyx_L3_continue;
+730: elif max_nx >= nx:
__pyx_t_6 = ((__pyx_v_max_nx >= __pyx_v_nx) != 0); if (__pyx_t_6) { /* … */ }
+731: max_nx = nx - 1
__pyx_v_max_nx = (__pyx_v_nx - 1);
732:
+733: if min_ny >= ny:
__pyx_t_6 = ((__pyx_v_min_ny >= __pyx_v_ny) != 0); if (__pyx_t_6) { /* … */ }
+734: continue
goto __pyx_L3_continue;
+735: elif min_ny < 0:
__pyx_t_6 = ((__pyx_v_min_ny < 0) != 0); if (__pyx_t_6) { /* … */ }
+736: min_ny = 0
__pyx_v_min_ny = 0;
737:
+738: if max_ny < 0:
__pyx_t_6 = ((__pyx_v_max_ny < 0) != 0); if (__pyx_t_6) { /* … */ }
+739: continue
goto __pyx_L3_continue;
+740: elif max_ny >= ny:
__pyx_t_6 = ((__pyx_v_max_ny >= __pyx_v_ny) != 0); if (__pyx_t_6) { /* … */ }
+741: max_ny = ny - 1
__pyx_v_max_ny = (__pyx_v_ny - 1);
742:
743: # print((
744: # "After thresholding\n"
745: # f"x = {x}\n"
746: # f"y = {y}\n"
747: # f"r = {r}\n"
748: # f"min_nx = {min_nx}\n"
749: # f"max_nx = {max_nx}\n"
750: # f"min_ny = {min_ny}\n"
751: # f"max_ny = {max_ny}\n"
752: # ))
753:
754:
755: # Iterate over all intersected pixels, computing the area covered by
756: # the particle
+757: for j in range(min_nx, max_nx + 1):
__pyx_t_8 = (__pyx_v_max_nx + 1); __pyx_t_9 = __pyx_t_8; for (__pyx_t_10 = __pyx_v_min_nx; __pyx_t_10 < __pyx_t_9; __pyx_t_10+=1) { __pyx_v_j = __pyx_t_10;
+758: for k in range(min_ny, max_ny + 1):
__pyx_t_11 = (__pyx_v_max_ny + 1); __pyx_t_12 = __pyx_t_11; for (__pyx_t_13 = __pyx_v_min_ny; __pyx_t_13 < __pyx_t_12; __pyx_t_13+=1) { __pyx_v_k = __pyx_t_13;
759: # Find the number of pixel corners inside the particle
+760: num_corners = 0
__pyx_v_num_corners = 0;
+761: for l in range(4):
for (__pyx_t_14 = 0; __pyx_t_14 < 4; __pyx_t_14+=1) { __pyx_v_l = __pyx_t_14;
+762: corners[l] = 0
(__pyx_v_corners[__pyx_v_l]) = 0; }
763:
764: # Pixel centre coordinates
+765: px = xlim[0] + (j + 0.5) * xsize
__pyx_t_2 = 0; __pyx_v_px = ((*((double *) ( /* dim=0 */ (__pyx_v_xlim.data + __pyx_t_2 * __pyx_v_xlim.strides[0]) ))) + ((__pyx_v_j + 0.5) * __pyx_v_xsize));
+766: py = ylim[0] + (k + 0.5) * ysize
__pyx_t_2 = 0; __pyx_v_py = ((*((double *) ( /* dim=0 */ (__pyx_v_ylim.data + __pyx_t_2 * __pyx_v_ylim.strides[0]) ))) + ((__pyx_v_k + 0.5) * __pyx_v_ysize));
767:
768: # print((
769: # f"For pixel indices [{j}, {k}]:\n"
770: # f"px = {px}\n"
771: # f"py = {py}\n"
772: # f"r2 = {r * r}\n"
773: # f"dist2 = {dist2(px - 0.5 * xsize, py - 0.5 * ysize, x, y)}\n"
774: # f"dist2 = {dist2(px + 0.5 * xsize, py - 0.5 * ysize, x, y)}\n"
775: # f"dist2 = {dist2(px + 0.5 * xsize, py + 0.5 * ysize, x, y)}\n"
776: # f"dist2 = {dist2(px - 0.5 * xsize, py + 0.5 * ysize, x, y)}\n"
777: # ))
778:
779: # Lower left corner
+780: if dist2(px - 0.5 * xsize, py - 0.5 * ysize, x, y) < r * r:
__pyx_t_6 = ((__pyx_f_4pept_10processing_13occupancy_ext_dist2((__pyx_v_px - (0.5 * __pyx_v_xsize)), (__pyx_v_py - (0.5 * __pyx_v_ysize)), __pyx_v_x, __pyx_v_y) < (__pyx_v_r * __pyx_v_r)) != 0); if (__pyx_t_6) { /* … */ }
+781: num_corners += 1
__pyx_v_num_corners = (__pyx_v_num_corners + 1);
+782: corners[0] = 1
(__pyx_v_corners[0]) = 1;
783:
784: # Lower right corner
+785: if dist2(px + 0.5 * xsize, py - 0.5 * ysize, x, y) < r * r:
__pyx_t_6 = ((__pyx_f_4pept_10processing_13occupancy_ext_dist2((__pyx_v_px + (0.5 * __pyx_v_xsize)), (__pyx_v_py - (0.5 * __pyx_v_ysize)), __pyx_v_x, __pyx_v_y) < (__pyx_v_r * __pyx_v_r)) != 0); if (__pyx_t_6) { /* … */ }
+786: num_corners += 1
__pyx_v_num_corners = (__pyx_v_num_corners + 1);
+787: corners[1] = 1
(__pyx_v_corners[1]) = 1;
788:
789: # Upper right corner
+790: if dist2(px + 0.5 * xsize, py + 0.5 * ysize, x, y) < r * r:
__pyx_t_6 = ((__pyx_f_4pept_10processing_13occupancy_ext_dist2((__pyx_v_px + (0.5 * __pyx_v_xsize)), (__pyx_v_py + (0.5 * __pyx_v_ysize)), __pyx_v_x, __pyx_v_y) < (__pyx_v_r * __pyx_v_r)) != 0); if (__pyx_t_6) { /* … */ }
+791: num_corners += 1
__pyx_v_num_corners = (__pyx_v_num_corners + 1);
+792: corners[2] = 1
(__pyx_v_corners[2]) = 1;
793:
794: # Upper left corner
+795: if dist2(px - 0.5 * xsize, py + 0.5 * ysize, x, y) < r * r:
__pyx_t_6 = ((__pyx_f_4pept_10processing_13occupancy_ext_dist2((__pyx_v_px - (0.5 * __pyx_v_xsize)), (__pyx_v_py + (0.5 * __pyx_v_ysize)), __pyx_v_x, __pyx_v_y) < (__pyx_v_r * __pyx_v_r)) != 0); if (__pyx_t_6) { /* … */ }
+796: num_corners += 1
__pyx_v_num_corners = (__pyx_v_num_corners + 1);
+797: corners[3] = 1
(__pyx_v_corners[3]) = 1;
798:
799: # print((
800: # f"num_corners = {num_corners}\n"
801: # f"corners = [{corners[0], corners[1], corners[2], corners[3]}]\n"
802: # ))
803:
+804: if num_corners == 0:
switch (__pyx_v_num_corners) { case 0: /* … */ break; case 1:
+805: pixels[j, k] += zero_corner(corners, px, py, xsize, ysize, x, y, r)
__pyx_t_2 = __pyx_v_j; __pyx_t_1 = __pyx_v_k; *((double *) ( /* dim=1 */ (( /* dim=0 */ (__pyx_v_pixels.data + __pyx_t_2 * __pyx_v_pixels.strides[0]) ) + __pyx_t_1 * __pyx_v_pixels.strides[1]) )) += __pyx_f_4pept_10processing_13occupancy_ext_zero_corner(__pyx_v_corners, __pyx_v_px, __pyx_v_py, __pyx_v_xsize, __pyx_v_ysize, __pyx_v_x, __pyx_v_y, __pyx_v_r);
+806: elif num_corners == 1:
break; case 2:
+807: pixels[j, k] += one_corner(corners, px, py, xsize, ysize, x, y, r)
__pyx_t_1 = __pyx_v_j; __pyx_t_2 = __pyx_v_k; *((double *) ( /* dim=1 */ (( /* dim=0 */ (__pyx_v_pixels.data + __pyx_t_1 * __pyx_v_pixels.strides[0]) ) + __pyx_t_2 * __pyx_v_pixels.strides[1]) )) += __pyx_f_4pept_10processing_13occupancy_ext_one_corner(__pyx_v_corners, __pyx_v_px, __pyx_v_py, __pyx_v_xsize, __pyx_v_ysize, __pyx_v_x, __pyx_v_y, __pyx_v_r);
+808: elif num_corners == 2:
break; case 3:
+809: pixels[j, k] += two_corner(corners, px, py, xsize, ysize, x, y, r)
__pyx_t_2 = __pyx_v_j; __pyx_t_1 = __pyx_v_k; *((double *) ( /* dim=1 */ (( /* dim=0 */ (__pyx_v_pixels.data + __pyx_t_2 * __pyx_v_pixels.strides[0]) ) + __pyx_t_1 * __pyx_v_pixels.strides[1]) )) += __pyx_f_4pept_10processing_13occupancy_ext_two_corner(__pyx_v_corners, __pyx_v_px, __pyx_v_py, __pyx_v_xsize, __pyx_v_ysize, __pyx_v_x, __pyx_v_y, __pyx_v_r);
+810: elif num_corners == 3:
break; case 4:
+811: pixels[j, k] += three_corner(corners, px, py, xsize, ysize, x, y, r)
__pyx_t_1 = __pyx_v_j; __pyx_t_2 = __pyx_v_k; *((double *) ( /* dim=1 */ (( /* dim=0 */ (__pyx_v_pixels.data + __pyx_t_1 * __pyx_v_pixels.strides[0]) ) + __pyx_t_2 * __pyx_v_pixels.strides[1]) )) += __pyx_f_4pept_10processing_13occupancy_ext_three_corner(__pyx_v_corners, __pyx_v_px, __pyx_v_py, __pyx_v_xsize, __pyx_v_ysize, __pyx_v_x, __pyx_v_y, __pyx_v_r);
+812: elif num_corners == 4:
break; default: break; } } } __pyx_L3_continue:; }
+813: pixels[j, k] += four_corner(corners, px, py, xsize, ysize, x, y, r)
__pyx_t_2 = __pyx_v_j; __pyx_t_1 = __pyx_v_k; *((double *) ( /* dim=1 */ (( /* dim=0 */ (__pyx_v_pixels.data + __pyx_t_2 * __pyx_v_pixels.strides[0]) ) + __pyx_t_1 * __pyx_v_pixels.strides[1]) )) += __pyx_f_4pept_10processing_13occupancy_ext_four_corner(__pyx_v_corners, __pyx_v_px, __pyx_v_py, __pyx_v_xsize, __pyx_v_ysize, __pyx_v_x, __pyx_v_y, __pyx_v_r);