code: def previous_event_indexer(
      data_query_cutoff_times,
      all_sids,
      event_dates,
      event_timestamps,
      event_sids,
  ):
      """
      Construct an index array that, when applied to an array of values, produces
      a 2D array containing the values associated with the previous event for
      each sid at each moment in time.
  
      Locations where no previous event was known will be filled with -1.
  
      Parameters
      ----------
      data_query_cutoff : pd.DatetimeIndex
          The boundaries for the given trading sessions.
      all_dates : ndarray[datetime64[ns], ndim=1]
          Row labels for the target output.
      all_sids : ndarray[int, ndim=1]
          Column labels for the target output.
      event_dates : ndarray[datetime64[ns], ndim=1]
          Dates on which each input events occurred/will occur.  ``event_dates``
          must be in sorted order, and may not contain any NaT values.
      event_timestamps : ndarray[datetime64[ns], ndim=1]
          Dates on which we learned about each input event.
      event_sids : ndarray[int, ndim=1]
          Sids assocated with each input event.
  
      Returns
      -------
      indexer : ndarray[int, ndim=2]
          An array of shape (len(all_dates), len(all_sids)) of indices into
          ``event_{dates,timestamps,sids}``.
      """
      validate_event_metadata(event_dates, event_timestamps, event_sids)
      out = np.full(
          (len(data_query_cutoff_times), len(all_sids)),
          -1,
          dtype=np.int64,
      )
  
      eff_dts = np.maximum(event_dates, event_timestamps)
      sid_ixs = all_sids.searchsorted(event_sids)
      dt_ixs = data_query_cutoff_times.searchsorted(
          eff_dts, side="right"
      )
  
      # Walk backwards through the events, writing the index of the event into
      # slots ranging from max(event_date, event_timestamp) to the start of the
      # previously-written event.  This depends for correctness on the fact that
      # event_dates is sorted in ascending order, because we need to have written
      # later events so we know where to stop forward-filling earlier events.
      last_written = {}
      for i in range(len(event_dates) - 1, -1, -1):
          sid_ix = sid_ixs[i]
          dt_ix = dt_ixs[i]
          out[dt_ix : last_written.get(sid_ix, None), sid_ix] = i
          last_written[sid_ix] = dt_ix
      return out
  
file_path: zipline/zipline/pipeline/loaders/utils.py
imports: import numpy
  import pandas
  from zipline.errors import NoFurtherDataError
  from zipline.pipeline.common import TS_FIELD_NAME, SID_FIELD_NAME
  from zipline.utils.numpy_utils import categorical_dtype
label_desc: Use image node_id 4 for calling a global function with example usage: previous_event_indexer(data_query_cutoff_times, all_sids, event_dates, event_timestamps, event_sids) and returns: out