Generated by Cython 3.0.11

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: dead_interval_tracker.pyx

 01: cimport numpy
+02: import numpy
  __pyx_t_4 = __Pyx_ImportDottedModule(__pyx_n_s_numpy, NULL); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 2, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_4);
  if (PyDict_SetItem(__pyx_d, __pyx_n_s_numpy, __pyx_t_4) < 0) __PYX_ERR(0, 2, __pyx_L1_error)
  __Pyx_DECREF(__pyx_t_4); __pyx_t_4 = 0;
 03: 
 04: from fcio_def cimport FCIOMaxChannels
 05: 
+06: cdef class DeadIntervalBuffer():
struct __pyx_obj_4fcio_DeadIntervalBuffer {
  PyObject_HEAD
  struct __pyx_vtabstruct_4fcio_DeadIntervalBuffer *__pyx_vtab;
  long interval_begin[FCIOMaxChannels][0x800];
  long interval_end[FCIOMaxChannels][0x800];
  int current_write[FCIOMaxChannels];
  int current_read[FCIOMaxChannels];
  int fill[FCIOMaxChannels];
  PyArrayObject *current_interval;
};
/* … */
struct __pyx_vtabstruct_4fcio_DeadIntervalBuffer {
  PyObject *(*add)(struct __pyx_obj_4fcio_DeadIntervalBuffer *, long, long, int, int);
  PyObject *(*is_before)(struct __pyx_obj_4fcio_DeadIntervalBuffer *, long, int, int);
  PyObject *(*read)(struct __pyx_obj_4fcio_DeadIntervalBuffer *, int, int);
};
static struct __pyx_vtabstruct_4fcio_DeadIntervalBuffer *__pyx_vtabptr_4fcio_DeadIntervalBuffer;

 07:   # maximum interval buffer size
 08:   # is given by the maximum number of events
 09:   # storable in the hardware
 10:   DEF FC_MAX_EVENTS = 2048
 11:   cdef long[FCIOMaxChannels][FC_MAX_EVENTS] interval_begin
 12:   cdef long[FCIOMaxChannels][FC_MAX_EVENTS] interval_end
 13:   cdef int[FCIOMaxChannels] current_write
 14:   cdef int[FCIOMaxChannels] current_read
 15:   cdef int[FCIOMaxChannels] fill
 16: 
 17:   cdef numpy.ndarray current_interval
 18: 
+19:   def __cinit__(self):
/* Python wrapper */
static int __pyx_pw_4fcio_18DeadIntervalBuffer_1__cinit__(PyObject *__pyx_v_self, PyObject *__pyx_args, PyObject *__pyx_kwds); /*proto*/
static int __pyx_pw_4fcio_18DeadIntervalBuffer_1__cinit__(PyObject *__pyx_v_self, PyObject *__pyx_args, PyObject *__pyx_kwds) {
  CYTHON_UNUSED Py_ssize_t __pyx_nargs;
  CYTHON_UNUSED PyObject *const *__pyx_kwvalues;
  int __pyx_r;
  __Pyx_RefNannyDeclarations
  __Pyx_RefNannySetupContext("__cinit__ (wrapper)", 0);
  #if CYTHON_ASSUME_SAFE_MACROS
  __pyx_nargs = PyTuple_GET_SIZE(__pyx_args);
  #else
  __pyx_nargs = PyTuple_Size(__pyx_args); if (unlikely(__pyx_nargs < 0)) return -1;
  #endif
  __pyx_kwvalues = __Pyx_KwValues_VARARGS(__pyx_args, __pyx_nargs);
  if (unlikely(__pyx_nargs > 0)) {
    __Pyx_RaiseArgtupleInvalid("__cinit__", 1, 0, 0, __pyx_nargs); return -1;}
  if (unlikely(__pyx_kwds) && __Pyx_NumKwargs_VARARGS(__pyx_kwds) && unlikely(!__Pyx_CheckKeywordStrings(__pyx_kwds, "__cinit__", 0))) return -1;
  __pyx_r = __pyx_pf_4fcio_18DeadIntervalBuffer___cinit__(((struct __pyx_obj_4fcio_DeadIntervalBuffer *)__pyx_v_self));

  /* function exit code */
  __Pyx_RefNannyFinishContext();
  return __pyx_r;
}

static int __pyx_pf_4fcio_18DeadIntervalBuffer___cinit__(struct __pyx_obj_4fcio_DeadIntervalBuffer *__pyx_v_self) {
  int __pyx_v_i;
  long __pyx_v_j;
  int __pyx_r;
/* … */
  /* function exit code */
  __pyx_r = 0;
  goto __pyx_L0;
  __pyx_L1_error:;
  __Pyx_XDECREF(__pyx_t_6);
  __Pyx_XDECREF(__pyx_t_7);
  __Pyx_XDECREF(__pyx_t_8);
  __Pyx_XDECREF(__pyx_t_9);
  __Pyx_XDECREF(__pyx_t_10);
  __Pyx_AddTraceback("fcio.DeadIntervalBuffer.__cinit__", __pyx_clineno, __pyx_lineno, __pyx_filename);
  __pyx_r = -1;
  __pyx_L0:;
  __Pyx_RefNannyFinishContext();
  return __pyx_r;
}
+20:     for i in range(FCIOMaxChannels):
  __pyx_t_1 = FCIOMaxChannels;
  __pyx_t_2 = __pyx_t_1;
  for (__pyx_t_3 = 0; __pyx_t_3 < __pyx_t_2; __pyx_t_3+=1) {
    __pyx_v_i = __pyx_t_3;
+21:       self.current_write[i] = FC_MAX_EVENTS-1
    (__pyx_v_self->current_write[__pyx_v_i]) = 0x7ff;
+22:       self.current_read[i] = 0
    (__pyx_v_self->current_read[__pyx_v_i]) = 0;
+23:       self.fill[i] = 0
    (__pyx_v_self->fill[__pyx_v_i]) = 0;
+24:       for j in range(FC_MAX_EVENTS):
    for (__pyx_t_4 = 0; __pyx_t_4 < 0x800; __pyx_t_4+=1) {
      __pyx_v_j = __pyx_t_4;
+25:         if (self.interval_begin[i][j] != 0):
      __pyx_t_5 = (((__pyx_v_self->interval_begin[__pyx_v_i])[__pyx_v_j]) != 0);
      if (__pyx_t_5) {
/* … */
      }
    }
  }
+26:           print("not zero")
        __pyx_t_6 = __Pyx_PyObject_Call(__pyx_builtin_print, __pyx_tuple__17, NULL); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 26, __pyx_L1_error)
        __Pyx_GOTREF(__pyx_t_6);
        __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
/* … */
  __pyx_tuple__17 = PyTuple_Pack(1, __pyx_kp_s_not_zero); if (unlikely(!__pyx_tuple__17)) __PYX_ERR(0, 26, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_tuple__17);
  __Pyx_GIVEREF(__pyx_tuple__17);
 27:       #  self.interval_end[i][j] = 0
 28: 
+29:     self.current_interval = numpy.zeros((FCIOMaxChannels,), dtype=numpy.int64)
  __Pyx_GetModuleGlobalName(__pyx_t_6, __pyx_n_s_numpy); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 29, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_6);
  __pyx_t_7 = __Pyx_PyObject_GetAttrStr(__pyx_t_6, __pyx_n_s_zeros); if (unlikely(!__pyx_t_7)) __PYX_ERR(0, 29, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_7);
  __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
  __pyx_t_6 = __Pyx_PyInt_From_int(FCIOMaxChannels); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 29, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_6);
  __pyx_t_8 = PyTuple_New(1); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 29, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_8);
  __Pyx_GIVEREF(__pyx_t_6);
  if (__Pyx_PyTuple_SET_ITEM(__pyx_t_8, 0, __pyx_t_6)) __PYX_ERR(0, 29, __pyx_L1_error);
  __pyx_t_6 = 0;
  __pyx_t_6 = PyTuple_New(1); if (unlikely(!__pyx_t_6)) __PYX_ERR(0, 29, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_6);
  __Pyx_GIVEREF(__pyx_t_8);
  if (__Pyx_PyTuple_SET_ITEM(__pyx_t_6, 0, __pyx_t_8)) __PYX_ERR(0, 29, __pyx_L1_error);
  __pyx_t_8 = 0;
  __pyx_t_8 = __Pyx_PyDict_NewPresized(1); if (unlikely(!__pyx_t_8)) __PYX_ERR(0, 29, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_8);
  __Pyx_GetModuleGlobalName(__pyx_t_9, __pyx_n_s_numpy); if (unlikely(!__pyx_t_9)) __PYX_ERR(0, 29, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_9);
  __pyx_t_10 = __Pyx_PyObject_GetAttrStr(__pyx_t_9, __pyx_n_s_int64); if (unlikely(!__pyx_t_10)) __PYX_ERR(0, 29, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_10);
  __Pyx_DECREF(__pyx_t_9); __pyx_t_9 = 0;
  if (PyDict_SetItem(__pyx_t_8, __pyx_n_s_dtype, __pyx_t_10) < 0) __PYX_ERR(0, 29, __pyx_L1_error)
  __Pyx_DECREF(__pyx_t_10); __pyx_t_10 = 0;
  __pyx_t_10 = __Pyx_PyObject_Call(__pyx_t_7, __pyx_t_6, __pyx_t_8); if (unlikely(!__pyx_t_10)) __PYX_ERR(0, 29, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_10);
  __Pyx_DECREF(__pyx_t_7); __pyx_t_7 = 0;
  __Pyx_DECREF(__pyx_t_6); __pyx_t_6 = 0;
  __Pyx_DECREF(__pyx_t_8); __pyx_t_8 = 0;
  if (!(likely(((__pyx_t_10) == Py_None) || likely(__Pyx_TypeTest(__pyx_t_10, __pyx_ptype_5numpy_ndarray))))) __PYX_ERR(0, 29, __pyx_L1_error)
  __Pyx_GIVEREF(__pyx_t_10);
  __Pyx_GOTREF((PyObject *)__pyx_v_self->current_interval);
  __Pyx_DECREF((PyObject *)__pyx_v_self->current_interval);
  __pyx_v_self->current_interval = ((PyArrayObject *)__pyx_t_10);
  __pyx_t_10 = 0;
 30: 
+31:   def __dealloc__(self):
/* Python wrapper */
static void __pyx_pw_4fcio_18DeadIntervalBuffer_3__dealloc__(PyObject *__pyx_v_self); /*proto*/
static void __pyx_pw_4fcio_18DeadIntervalBuffer_3__dealloc__(PyObject *__pyx_v_self) {
  CYTHON_UNUSED PyObject *const *__pyx_kwvalues;
  __Pyx_RefNannyDeclarations
  __Pyx_RefNannySetupContext("__dealloc__ (wrapper)", 0);
  __pyx_kwvalues = __Pyx_KwValues_VARARGS(__pyx_args, __pyx_nargs);
  __pyx_pf_4fcio_18DeadIntervalBuffer_2__dealloc__(((struct __pyx_obj_4fcio_DeadIntervalBuffer *)__pyx_v_self));

  /* function exit code */
  __Pyx_RefNannyFinishContext();
}

static void __pyx_pf_4fcio_18DeadIntervalBuffer_2__dealloc__(CYTHON_UNUSED struct __pyx_obj_4fcio_DeadIntervalBuffer *__pyx_v_self) {

  /* function exit code */
}
 32:     pass
 33: 
+34:   cdef add(self, long interval_start, long interval_stop, int trace_idx_start, int ntraces):
static PyObject *__pyx_f_4fcio_18DeadIntervalBuffer_add(struct __pyx_obj_4fcio_DeadIntervalBuffer *__pyx_v_self, long __pyx_v_interval_start, long __pyx_v_interval_stop, int __pyx_v_trace_idx_start, int __pyx_v_ntraces) {
  int __pyx_v_add_slot;
  int __pyx_v_trace_idx;
  PyObject *__pyx_v_offset = NULL;
  PyObject *__pyx_r = NULL;
/* … */
  /* function exit code */
  __pyx_r = Py_None; __Pyx_INCREF(Py_None);
  goto __pyx_L0;
  __pyx_L1_error:;
  __Pyx_XDECREF(__pyx_t_1);
  __Pyx_XDECREF(__pyx_t_2);
  __Pyx_XDECREF(__pyx_t_5);
  __Pyx_AddTraceback("fcio.DeadIntervalBuffer.add", __pyx_clineno, __pyx_lineno, __pyx_filename);
  __pyx_r = 0;
  __pyx_L0:;
  __Pyx_XDECREF(__pyx_v_offset);
  __Pyx_XGIVEREF(__pyx_r);
  __Pyx_RefNannyFinishContext();
  return __pyx_r;
}
 35:     cdef int add_slot
 36:     cdef int trace_idx
+37:     for offset in range(ntraces):
  __pyx_t_1 = __Pyx_PyInt_From_int(__pyx_v_ntraces); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 37, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  __pyx_t_2 = __Pyx_PyObject_CallOneArg(__pyx_builtin_range, __pyx_t_1); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 37, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_2);
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
  if (likely(PyList_CheckExact(__pyx_t_2)) || PyTuple_CheckExact(__pyx_t_2)) {
    __pyx_t_1 = __pyx_t_2; __Pyx_INCREF(__pyx_t_1);
    __pyx_t_3 = 0;
    __pyx_t_4 = NULL;
  } else {
    __pyx_t_3 = -1; __pyx_t_1 = PyObject_GetIter(__pyx_t_2); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 37, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_1);
    __pyx_t_4 = __Pyx_PyObject_GetIterNextFunc(__pyx_t_1); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 37, __pyx_L1_error)
  }
  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
  for (;;) {
    if (likely(!__pyx_t_4)) {
      if (likely(PyList_CheckExact(__pyx_t_1))) {
        {
          Py_ssize_t __pyx_temp = __Pyx_PyList_GET_SIZE(__pyx_t_1);
          #if !CYTHON_ASSUME_SAFE_MACROS
          if (unlikely((__pyx_temp < 0))) __PYX_ERR(0, 37, __pyx_L1_error)
          #endif
          if (__pyx_t_3 >= __pyx_temp) break;
        }
        #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS
        __pyx_t_2 = PyList_GET_ITEM(__pyx_t_1, __pyx_t_3); __Pyx_INCREF(__pyx_t_2); __pyx_t_3++; if (unlikely((0 < 0))) __PYX_ERR(0, 37, __pyx_L1_error)
        #else
        __pyx_t_2 = __Pyx_PySequence_ITEM(__pyx_t_1, __pyx_t_3); __pyx_t_3++; if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 37, __pyx_L1_error)
        __Pyx_GOTREF(__pyx_t_2);
        #endif
      } else {
        {
          Py_ssize_t __pyx_temp = __Pyx_PyTuple_GET_SIZE(__pyx_t_1);
          #if !CYTHON_ASSUME_SAFE_MACROS
          if (unlikely((__pyx_temp < 0))) __PYX_ERR(0, 37, __pyx_L1_error)
          #endif
          if (__pyx_t_3 >= __pyx_temp) break;
        }
        #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS
        __pyx_t_2 = PyTuple_GET_ITEM(__pyx_t_1, __pyx_t_3); __Pyx_INCREF(__pyx_t_2); __pyx_t_3++; if (unlikely((0 < 0))) __PYX_ERR(0, 37, __pyx_L1_error)
        #else
        __pyx_t_2 = __Pyx_PySequence_ITEM(__pyx_t_1, __pyx_t_3); __pyx_t_3++; if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 37, __pyx_L1_error)
        __Pyx_GOTREF(__pyx_t_2);
        #endif
      }
    } else {
      __pyx_t_2 = __pyx_t_4(__pyx_t_1);
      if (unlikely(!__pyx_t_2)) {
        PyObject* exc_type = PyErr_Occurred();
        if (exc_type) {
          if (likely(__Pyx_PyErr_GivenExceptionMatches(exc_type, PyExc_StopIteration))) PyErr_Clear();
          else __PYX_ERR(0, 37, __pyx_L1_error)
        }
        break;
      }
      __Pyx_GOTREF(__pyx_t_2);
    }
    __Pyx_XDECREF_SET(__pyx_v_offset, __pyx_t_2);
    __pyx_t_2 = 0;
/* … */
  }
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+38:       trace_idx = trace_idx_start + offset
    __pyx_t_2 = __Pyx_PyInt_From_int(__pyx_v_trace_idx_start); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 38, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_2);
    __pyx_t_5 = PyNumber_Add(__pyx_t_2, __pyx_v_offset); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 38, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_5);
    __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
    __pyx_t_6 = __Pyx_PyInt_As_int(__pyx_t_5); if (unlikely((__pyx_t_6 == (int)-1) && PyErr_Occurred())) __PYX_ERR(0, 38, __pyx_L1_error)
    __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
    __pyx_v_trace_idx = __pyx_t_6;
+39:       if self.fill[trace_idx] >= FC_MAX_EVENTS:
    __pyx_t_7 = ((__pyx_v_self->fill[__pyx_v_trace_idx]) >= 0x800);
    if (unlikely(__pyx_t_7)) {
/* … */
    }
+40:         raise ValueError("ERROR fcio-py: dead-time buffer full, requires source code updates with new defines to change.")
      __pyx_t_5 = __Pyx_PyObject_Call(__pyx_builtin_ValueError, __pyx_tuple__18, NULL); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 40, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_5);
      __Pyx_Raise(__pyx_t_5, 0, 0, 0);
      __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
      __PYX_ERR(0, 40, __pyx_L1_error)
/* … */
  __pyx_tuple__18 = PyTuple_Pack(1, __pyx_kp_s_ERROR_fcio_py_dead_time_buffer_f); if (unlikely(!__pyx_tuple__18)) __PYX_ERR(0, 40, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_tuple__18);
  __Pyx_GIVEREF(__pyx_tuple__18);
+41:       add_slot = self.current_write[trace_idx]
    __pyx_v_add_slot = (__pyx_v_self->current_write[__pyx_v_trace_idx]);
+42:       if interval_stop > self.interval_end[trace_idx][add_slot]:
    __pyx_t_7 = (__pyx_v_interval_stop > ((__pyx_v_self->interval_end[__pyx_v_trace_idx])[__pyx_v_add_slot]));
    if (__pyx_t_7) {
/* … */
    }
+43:         add_slot = (add_slot + 1) % FC_MAX_EVENTS
      __pyx_v_add_slot = __Pyx_mod_long((__pyx_v_add_slot + 1), 0x800);
+44:         self.fill[trace_idx] += 1
      __pyx_t_6 = __pyx_v_trace_idx;
      (__pyx_v_self->fill[__pyx_t_6]) = ((__pyx_v_self->fill[__pyx_t_6]) + 1);
 45: 
+46:         self.interval_begin[trace_idx][add_slot] = interval_start
      ((__pyx_v_self->interval_begin[__pyx_v_trace_idx])[__pyx_v_add_slot]) = __pyx_v_interval_start;
+47:         self.interval_end[trace_idx][add_slot] = interval_stop
      ((__pyx_v_self->interval_end[__pyx_v_trace_idx])[__pyx_v_add_slot]) = __pyx_v_interval_stop;
+48:         self.current_write[trace_idx] = add_slot
      (__pyx_v_self->current_write[__pyx_v_trace_idx]) = __pyx_v_add_slot;
 49: 
 50:       #   print(f"DEBUG DeadIntervalTracker/add: trace {trace_idx} write slot {add_slot} fill level {self.fill[trace_idx]} entry {interval_start} {interval_stop} delta {interval_stop - interval_start} previous {self.interval_end[trace_idx][add_slot-1]}")
 51:       # else:
 52:       #   print(f"DEBUG DeadIntervalTracker/add: trace {trace_idx} write slot {add_slot+1} skip entry {interval_start} {interval_stop} delta {interval_stop - interval_start} previous {self.interval_end[trace_idx][add_slot]}")
 53: 
+54:   cdef is_before(self, long timestamp_ns, int trace_idx_start, int ntraces):
static PyObject *__pyx_f_4fcio_18DeadIntervalBuffer_is_before(struct __pyx_obj_4fcio_DeadIntervalBuffer *__pyx_v_self, long __pyx_v_timestamp_ns, int __pyx_v_trace_idx_start, int __pyx_v_ntraces) {
  int __pyx_v_read_slot;
  int __pyx_v_trace_idx;
  PyObject *__pyx_v_offset = NULL;
  PyObject *__pyx_r = NULL;
/* … */
  /* function exit code */
  __pyx_L1_error:;
  __Pyx_XDECREF(__pyx_t_1);
  __Pyx_XDECREF(__pyx_t_2);
  __Pyx_XDECREF(__pyx_t_5);
  __Pyx_AddTraceback("fcio.DeadIntervalBuffer.is_before", __pyx_clineno, __pyx_lineno, __pyx_filename);
  __pyx_r = 0;
  __pyx_L0:;
  __Pyx_XDECREF(__pyx_v_offset);
  __Pyx_XGIVEREF(__pyx_r);
  __Pyx_RefNannyFinishContext();
  return __pyx_r;
}
 55:     cdef int read_slot
 56:     cdef int trace_idx
+57:     for offset in range(ntraces):
  __pyx_t_1 = __Pyx_PyInt_From_int(__pyx_v_ntraces); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 57, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  __pyx_t_2 = __Pyx_PyObject_CallOneArg(__pyx_builtin_range, __pyx_t_1); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 57, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_2);
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
  if (likely(PyList_CheckExact(__pyx_t_2)) || PyTuple_CheckExact(__pyx_t_2)) {
    __pyx_t_1 = __pyx_t_2; __Pyx_INCREF(__pyx_t_1);
    __pyx_t_3 = 0;
    __pyx_t_4 = NULL;
  } else {
    __pyx_t_3 = -1; __pyx_t_1 = PyObject_GetIter(__pyx_t_2); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 57, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_1);
    __pyx_t_4 = __Pyx_PyObject_GetIterNextFunc(__pyx_t_1); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 57, __pyx_L1_error)
  }
  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
  for (;;) {
    if (likely(!__pyx_t_4)) {
      if (likely(PyList_CheckExact(__pyx_t_1))) {
        {
          Py_ssize_t __pyx_temp = __Pyx_PyList_GET_SIZE(__pyx_t_1);
          #if !CYTHON_ASSUME_SAFE_MACROS
          if (unlikely((__pyx_temp < 0))) __PYX_ERR(0, 57, __pyx_L1_error)
          #endif
          if (__pyx_t_3 >= __pyx_temp) break;
        }
        #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS
        __pyx_t_2 = PyList_GET_ITEM(__pyx_t_1, __pyx_t_3); __Pyx_INCREF(__pyx_t_2); __pyx_t_3++; if (unlikely((0 < 0))) __PYX_ERR(0, 57, __pyx_L1_error)
        #else
        __pyx_t_2 = __Pyx_PySequence_ITEM(__pyx_t_1, __pyx_t_3); __pyx_t_3++; if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 57, __pyx_L1_error)
        __Pyx_GOTREF(__pyx_t_2);
        #endif
      } else {
        {
          Py_ssize_t __pyx_temp = __Pyx_PyTuple_GET_SIZE(__pyx_t_1);
          #if !CYTHON_ASSUME_SAFE_MACROS
          if (unlikely((__pyx_temp < 0))) __PYX_ERR(0, 57, __pyx_L1_error)
          #endif
          if (__pyx_t_3 >= __pyx_temp) break;
        }
        #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS
        __pyx_t_2 = PyTuple_GET_ITEM(__pyx_t_1, __pyx_t_3); __Pyx_INCREF(__pyx_t_2); __pyx_t_3++; if (unlikely((0 < 0))) __PYX_ERR(0, 57, __pyx_L1_error)
        #else
        __pyx_t_2 = __Pyx_PySequence_ITEM(__pyx_t_1, __pyx_t_3); __pyx_t_3++; if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 57, __pyx_L1_error)
        __Pyx_GOTREF(__pyx_t_2);
        #endif
      }
    } else {
      __pyx_t_2 = __pyx_t_4(__pyx_t_1);
      if (unlikely(!__pyx_t_2)) {
        PyObject* exc_type = PyErr_Occurred();
        if (exc_type) {
          if (likely(__Pyx_PyErr_GivenExceptionMatches(exc_type, PyExc_StopIteration))) PyErr_Clear();
          else __PYX_ERR(0, 57, __pyx_L1_error)
        }
        break;
      }
      __Pyx_GOTREF(__pyx_t_2);
    }
    __Pyx_XDECREF_SET(__pyx_v_offset, __pyx_t_2);
    __pyx_t_2 = 0;
/* … */
  }
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+58:       trace_idx = trace_idx_start + offset
    __pyx_t_2 = __Pyx_PyInt_From_int(__pyx_v_trace_idx_start); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 58, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_2);
    __pyx_t_5 = PyNumber_Add(__pyx_t_2, __pyx_v_offset); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 58, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_5);
    __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
    __pyx_t_6 = __Pyx_PyInt_As_int(__pyx_t_5); if (unlikely((__pyx_t_6 == (int)-1) && PyErr_Occurred())) __PYX_ERR(0, 58, __pyx_L1_error)
    __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
    __pyx_v_trace_idx = __pyx_t_6;
+59:       if self.fill[trace_idx] == 0:
    __pyx_t_7 = ((__pyx_v_self->fill[__pyx_v_trace_idx]) == 0);
    if (__pyx_t_7) {
/* … */
    }
 60:         # print(f"DEBUG DeadIntervalTracker/is_before: trace {trace_idx} empty.")
+61:         return False
      __Pyx_XDECREF(__pyx_r);
      __Pyx_INCREF(Py_False);
      __pyx_r = Py_False;
      __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
      goto __pyx_L0;
+62:       read_slot = self.current_read[trace_idx]
    __pyx_v_read_slot = (__pyx_v_self->current_read[__pyx_v_trace_idx]);
 63:       # print(f"DEBUG DeadIntervalTracker/is_before: /trace {trace_idx} read slot {read_slot} fill level {self.fill[trace_idx]} {self.interval_end[trace_idx][read_slot]} <= {timestamp_ns} : {self.interval_end[trace_idx][read_slot] <= timestamp_ns}")
 64:       # if self.interval_end[trace_idx][read_slot] <= timestamp_ns:
+65:       if timestamp_ns - self.interval_end[trace_idx][read_slot] > -4:
    __pyx_t_7 = ((__pyx_v_timestamp_ns - ((__pyx_v_self->interval_end[__pyx_v_trace_idx])[__pyx_v_read_slot])) > -4L);
    if (__pyx_t_7) {
/* … */
    }
 66:       # an overlap of 3 nanoseconds is allowed, as the 16bit firmware might read the stamps during the sampling of a 16ns window. This should not affect the 12bit firmware.
+67:         return True
      __Pyx_XDECREF(__pyx_r);
      __Pyx_INCREF(Py_True);
      __pyx_r = Py_True;
      __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
      goto __pyx_L0;
+68:     return False
  __Pyx_XDECREF(__pyx_r);
  __Pyx_INCREF(Py_False);
  __pyx_r = Py_False;
  goto __pyx_L0;
 69: 
+70:   cdef read(self, int trace_idx_start, int ntraces):
static PyObject *__pyx_f_4fcio_18DeadIntervalBuffer_read(struct __pyx_obj_4fcio_DeadIntervalBuffer *__pyx_v_self, int __pyx_v_trace_idx_start, int __pyx_v_ntraces) {
  int __pyx_v_read_slot;
  int __pyx_v_trace_idx;
  PyObject *__pyx_v_offset = NULL;
  PyObject *__pyx_r = NULL;
/* … */
  /* function exit code */
  __pyx_L1_error:;
  __Pyx_XDECREF(__pyx_t_1);
  __Pyx_XDECREF(__pyx_t_2);
  __Pyx_XDECREF(__pyx_t_5);
  __Pyx_AddTraceback("fcio.DeadIntervalBuffer.read", __pyx_clineno, __pyx_lineno, __pyx_filename);
  __pyx_r = 0;
  __pyx_L0:;
  __Pyx_XDECREF(__pyx_v_offset);
  __Pyx_XGIVEREF(__pyx_r);
  __Pyx_RefNannyFinishContext();
  return __pyx_r;
}
 71:     cdef int read_slot
 72:     cdef int trace_idx
 73: 
+74:     for offset in range(ntraces):
  __pyx_t_1 = __Pyx_PyInt_From_int(__pyx_v_ntraces); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 74, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  __pyx_t_2 = __Pyx_PyObject_CallOneArg(__pyx_builtin_range, __pyx_t_1); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 74, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_2);
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
  if (likely(PyList_CheckExact(__pyx_t_2)) || PyTuple_CheckExact(__pyx_t_2)) {
    __pyx_t_1 = __pyx_t_2; __Pyx_INCREF(__pyx_t_1);
    __pyx_t_3 = 0;
    __pyx_t_4 = NULL;
  } else {
    __pyx_t_3 = -1; __pyx_t_1 = PyObject_GetIter(__pyx_t_2); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 74, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_1);
    __pyx_t_4 = __Pyx_PyObject_GetIterNextFunc(__pyx_t_1); if (unlikely(!__pyx_t_4)) __PYX_ERR(0, 74, __pyx_L1_error)
  }
  __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
  for (;;) {
    if (likely(!__pyx_t_4)) {
      if (likely(PyList_CheckExact(__pyx_t_1))) {
        {
          Py_ssize_t __pyx_temp = __Pyx_PyList_GET_SIZE(__pyx_t_1);
          #if !CYTHON_ASSUME_SAFE_MACROS
          if (unlikely((__pyx_temp < 0))) __PYX_ERR(0, 74, __pyx_L1_error)
          #endif
          if (__pyx_t_3 >= __pyx_temp) break;
        }
        #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS
        __pyx_t_2 = PyList_GET_ITEM(__pyx_t_1, __pyx_t_3); __Pyx_INCREF(__pyx_t_2); __pyx_t_3++; if (unlikely((0 < 0))) __PYX_ERR(0, 74, __pyx_L1_error)
        #else
        __pyx_t_2 = __Pyx_PySequence_ITEM(__pyx_t_1, __pyx_t_3); __pyx_t_3++; if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 74, __pyx_L1_error)
        __Pyx_GOTREF(__pyx_t_2);
        #endif
      } else {
        {
          Py_ssize_t __pyx_temp = __Pyx_PyTuple_GET_SIZE(__pyx_t_1);
          #if !CYTHON_ASSUME_SAFE_MACROS
          if (unlikely((__pyx_temp < 0))) __PYX_ERR(0, 74, __pyx_L1_error)
          #endif
          if (__pyx_t_3 >= __pyx_temp) break;
        }
        #if CYTHON_ASSUME_SAFE_MACROS && !CYTHON_AVOID_BORROWED_REFS
        __pyx_t_2 = PyTuple_GET_ITEM(__pyx_t_1, __pyx_t_3); __Pyx_INCREF(__pyx_t_2); __pyx_t_3++; if (unlikely((0 < 0))) __PYX_ERR(0, 74, __pyx_L1_error)
        #else
        __pyx_t_2 = __Pyx_PySequence_ITEM(__pyx_t_1, __pyx_t_3); __pyx_t_3++; if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 74, __pyx_L1_error)
        __Pyx_GOTREF(__pyx_t_2);
        #endif
      }
    } else {
      __pyx_t_2 = __pyx_t_4(__pyx_t_1);
      if (unlikely(!__pyx_t_2)) {
        PyObject* exc_type = PyErr_Occurred();
        if (exc_type) {
          if (likely(__Pyx_PyErr_GivenExceptionMatches(exc_type, PyExc_StopIteration))) PyErr_Clear();
          else __PYX_ERR(0, 74, __pyx_L1_error)
        }
        break;
      }
      __Pyx_GOTREF(__pyx_t_2);
    }
    __Pyx_XDECREF_SET(__pyx_v_offset, __pyx_t_2);
    __pyx_t_2 = 0;
/* … */
  }
  __Pyx_DECREF(__pyx_t_1); __pyx_t_1 = 0;
+75:       trace_idx = trace_idx_start + offset
    __pyx_t_2 = __Pyx_PyInt_From_int(__pyx_v_trace_idx_start); if (unlikely(!__pyx_t_2)) __PYX_ERR(0, 75, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_2);
    __pyx_t_5 = PyNumber_Add(__pyx_t_2, __pyx_v_offset); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 75, __pyx_L1_error)
    __Pyx_GOTREF(__pyx_t_5);
    __Pyx_DECREF(__pyx_t_2); __pyx_t_2 = 0;
    __pyx_t_6 = __Pyx_PyInt_As_int(__pyx_t_5); if (unlikely((__pyx_t_6 == (int)-1) && PyErr_Occurred())) __PYX_ERR(0, 75, __pyx_L1_error)
    __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
    __pyx_v_trace_idx = __pyx_t_6;
+76:       read_slot = self.current_read[trace_idx]
    __pyx_v_read_slot = (__pyx_v_self->current_read[__pyx_v_trace_idx]);
+77:       if self.fill[trace_idx] > 0:
    __pyx_t_7 = ((__pyx_v_self->fill[__pyx_v_trace_idx]) > 0);
    if (likely(__pyx_t_7)) {
/* … */
      goto __pyx_L5;
    }
+78:         self.current_interval[offset] = self.interval_end[trace_idx][read_slot] - self.interval_begin[trace_idx][read_slot]
      __pyx_t_5 = __Pyx_PyInt_From_long((((__pyx_v_self->interval_end[__pyx_v_trace_idx])[__pyx_v_read_slot]) - ((__pyx_v_self->interval_begin[__pyx_v_trace_idx])[__pyx_v_read_slot]))); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 78, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_5);
      if (unlikely((PyObject_SetItem(((PyObject *)__pyx_v_self->current_interval), __pyx_v_offset, __pyx_t_5) < 0))) __PYX_ERR(0, 78, __pyx_L1_error)
      __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
+79:         self.current_read[trace_idx] = (self.current_read[trace_idx] + 1 ) % FC_MAX_EVENTS
      (__pyx_v_self->current_read[__pyx_v_trace_idx]) = __Pyx_mod_long(((__pyx_v_self->current_read[__pyx_v_trace_idx]) + 1), 0x800);
+80:         self.fill[trace_idx] -= 1
      __pyx_t_6 = __pyx_v_trace_idx;
      (__pyx_v_self->fill[__pyx_t_6]) = ((__pyx_v_self->fill[__pyx_t_6]) - 1);
 81:         # print(f"DEBUG DeadIntervalTracker/read: trace {trace_idx} read slot {read_slot} fill level {self.fill[trace_idx]} entry {self.interval_begin[trace_idx][read_slot]} {self.interval_end[trace_idx][read_slot]} delta {self.interval_end[trace_idx][read_slot] -self.interval_begin[trace_idx][read_slot]}")
 82:       else:
+83:         raise ValueError(f"ERROR fcio-py: trying to read a dead-time interval from empty buffer.")
    /*else*/ {
      __pyx_t_5 = __Pyx_PyObject_Call(__pyx_builtin_ValueError, __pyx_tuple__19, NULL); if (unlikely(!__pyx_t_5)) __PYX_ERR(0, 83, __pyx_L1_error)
      __Pyx_GOTREF(__pyx_t_5);
      __Pyx_Raise(__pyx_t_5, 0, 0, 0);
      __Pyx_DECREF(__pyx_t_5); __pyx_t_5 = 0;
      __PYX_ERR(0, 83, __pyx_L1_error)
    }
    __pyx_L5:;
/* … */
  __pyx_tuple__19 = PyTuple_Pack(1, __pyx_kp_u_ERROR_fcio_py_trying_to_read_a_d); if (unlikely(!__pyx_tuple__19)) __PYX_ERR(0, 83, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_tuple__19);
  __Pyx_GIVEREF(__pyx_tuple__19);
 84: 
+85:     return self.current_interval[:ntraces]
  __Pyx_XDECREF(__pyx_r);
  __pyx_t_1 = __Pyx_PyObject_GetSlice(((PyObject *)__pyx_v_self->current_interval), 0, __pyx_v_ntraces, NULL, NULL, NULL, 0, 1, 1); if (unlikely(!__pyx_t_1)) __PYX_ERR(0, 85, __pyx_L1_error)
  __Pyx_GOTREF(__pyx_t_1);
  __pyx_r = __pyx_t_1;
  __pyx_t_1 = 0;
  goto __pyx_L0;