code: def _find_events(
      data,
      first_samp,
      *,
      verbose=None,
      output="onset",
      consecutive="increasing",
      min_samples=0,
      mask=None,
      uint_cast=False,
      mask_type="and",
      initial_event=False,
      ch_name=None,
  ):
      """Help find events."""
      assert data.shape[0] == 1  # data should be only a row vector
  
      if min_samples > 0:
          merge = int(min_samples // 1)
          if merge == min_samples:
              merge -= 1
      else:
          merge = 0
  
      data = data.astype(np.int64)
      if uint_cast:
          data = data.astype(np.uint16).astype(np.int64)
      if data.min() < 0:
          warn(
              "Trigger channel contains negative values, using absolute "
              "value. If data were acquired on a Neuromag system with "
              "STI016 active, consider using uint_cast=True to work around "
              "an acquisition bug"
          )
          data = np.abs(data)  # make sure trig channel is positive
  
      events = _find_stim_steps(
          data, first_samp, pad_stop=0, merge=merge
      )
      initial_value = data[0, 0]
      if initial_value != 0:
          if initial_event:
              events = np.insert(
                  events, 0, [first_samp, 0, initial_value], axis=0
              )
          else:
              logger.info(
                  f"Trigger channel {ch_name} has a non-zero initial value of "
                  "{initial_value} (consider using initial_event=True to detect this "
                  "event)"
              )
  
      events = _mask_trigs(events, mask, mask_type)
  
      # Determine event onsets and offsets
      if consecutive == "increasing":
          onsets = events[:, 2] > events[:, 1]
          offsets = np.logical_and(
              np.logical_or(onsets, (events[:, 2] == 0)),
              (events[:, 1] > 0),
          )
      elif consecutive:
          onsets = events[:, 2] > 0
          offsets = events[:, 1] > 0
      else:
          onsets = events[:, 1] == 0
          offsets = events[:, 2] == 0
  
      onset_idx = np.where(onsets)[0]
      offset_idx = np.where(offsets)[0]
  
      if len(onset_idx) == 0 or len(offset_idx) == 0:
          return np.empty((0, 3), dtype="int32")
  
      # delete orphaned onsets/offsets
      if onset_idx[0] > offset_idx[0]:
          logger.info(
              "Removing orphaned offset at the beginning of the file."
          )
          offset_idx = np.delete(offset_idx, 0)
  
      if onset_idx[-1] > offset_idx[-1]:
          logger.info("Removing orphaned onset at the end of the file.")
          onset_idx = np.delete(onset_idx, -1)
  
      _check_option("output", output, ("onset", "step", "offset"))
      if output == "onset":
          events = events[onset_idx]
      elif output == "step":
          idx = np.union1d(onset_idx, offset_idx)
          events = events[idx]
      else:
          assert output == "offset"
          event_id = events[onset_idx, 2]
          events = events[offset_idx]
          events[:, 1] = events[:, 2]
          events[:, 2] = event_id
          events[:, 0] -= 1
  
      logger.info(
          f"{len(events)} event{_pl(events)} found on stim channel {ch_name}"
      )
      logger.info(f"Event IDs: {np.unique(events[:, 2])}")
  
      return events
  
imports: from collections.abc import Sequence
  from pathlib import Path
  import numpy
  from ._fiff.constants import FIFF
  from ._fiff.open import fiff_open
  from ._fiff.pick import pick_channels
  from ._fiff.tag import read_tag
  from ._fiff.tree import dir_tree_find
  from ._fiff.write import end_block, start_and_end_file, start_block, write_int
  from .utils import _check_fname, _check_integer_or_list, _check_on_missing, _check_option, _get_stim_channel, _on_missing, _pl, _validate_type, check_fname, fill_doc, logger, verbose, warn
label_desc: Use image node_id 8 for calling a global function with example usage: _find_events(data, first_samp) and returns: events, np