Filter Schlumberger configurations

    Schlumberger configurations are selected using the following criteria:

    * For a given voltage dipole, there need to be at least two current
      injections with electrodes located on the left and the right of the
      voltage dipole.
    * The distance between the current electrodes and the next voltage
      electrode is the same on both sides.

    Parameters
    ----------
    configs: numpy.ndarray
        Nx4 array with N measurement configurations

    Returns
    -------
    configs: numpy.ndarray
        Remaining configurations, all Schlumberger configurations are set to
        numpy.nan
    schl_indices: dict with one entry: numpy.ndarray
        indices of Schlumberger configurations

def _filter_schlumberger(configs):
    """Filter Schlumberger configurations

    Schlumberger configurations are selected using the following criteria:

    * For a given voltage dipole, there need to be at least two current
      injections with electrodes located on the left and the right of the
      voltage dipole.
    * The distance between the current electrodes and the next voltage
      electrode is the same on both sides.

    Parameters
    ----------
    configs: numpy.ndarray
        Nx4 array with N measurement configurations

    Returns
    -------
    configs: numpy.ndarray
        Remaining configurations, all Schlumberger configurations are set to
        numpy.nan
    schl_indices: dict with one entry: numpy.ndarray
        indices of Schlumberger configurations
    """
    # sort configs
    configs_sorted = np.hstack((
        np.sort(configs[:, 0:2], axis=1),
        np.sort(configs[:, 2:4], axis=1),
    )).astype(int)

    # determine unique voltage dipoles
    MN = configs_sorted[:, 2:4].copy()
    MN_unique = np.unique(
        MN.view(
            MN.dtype.descr * 2
        )
    )
    MN_unique_reshape = MN_unique.view(
        MN.dtype
    ).reshape(-1, 2)

    schl_indices_list = []
    for mn in MN_unique_reshape:
        # check if there are more than one associated current injections
        nr_current_binary = (
            (configs_sorted[:, 2] == mn[0]) &
            (configs_sorted[:, 3] == mn[1])
        )
        if len(np.where(nr_current_binary)[0]) < 2:
            continue

        # now which of these configurations have current electrodes on both
        # sides of the voltage dipole
        nr_left_right = (
            (configs_sorted[:, 0] < mn[0]) &
            (configs_sorted[:, 1] > mn[0]) &
            nr_current_binary
        )

        # now check that the left/right distances are equal
        distance_left = np.abs(
            configs_sorted[nr_left_right, 0] - mn[0]
        ).squeeze()
        distance_right = np.abs(
            configs_sorted[nr_left_right, 1] - mn[1]
        ).squeeze()

        nr_equal_distances = np.where(distance_left == distance_right)[0]

        indices = np.where(nr_left_right)[0][nr_equal_distances]

        if indices.size > 2:
            schl_indices_list.append(indices)

    # set Schlumberger configs to nan
    if len(schl_indices_list) == 0:
        return configs, {0: np.array([])}
    else:
        schl_indices = np.hstack(schl_indices_list).squeeze()
        configs[schl_indices, :] = np.nan
        return configs, {0: schl_indices}