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);