def _sal_detect_objects(precip, thr_factor, thr_quantile, tstorm_kwargs):
    """
    Detect coherent precipitation objects using a multi-threshold approach from
    :cite:`Feldmann2021`.

    Parameters
    ----------
    precip: array-like
        Array of shape (m,n) containing input data. Nan values are ignored.
    thr_factor: float
        Factor used to compute the detection threshold as in eq. 1 of :cite:`WHZ2009`.
        If not None, this is used to identify coherent objects enclosed by the
        threshold contour `thr_factor * thr_quantile(precip)`.
    thr_quantile: float
        The wet quantile between 0 and 1 used to define the detection threshold.
        Required if `thr_factor` is not None.
    tstorm_kwargs: dict
        Optional dictionary containing keyword arguments for the tstorm feature
        detection algorithm. If None, default values are used.
        See the documentation of :py:func:`pysteps.feature.tstorm.detection`.

    Returns
    -------
    precip_objects: pd.DataFrame
        Dataframe containing all detected cells and their respective properties.
    """
    if not PANDAS_IMPORTED:
        raise MissingOptionalDependency(
            "The pandas package is required for the SAL "
            "verification method but it is not installed"
        )
    if not SKIMAGE_IMPORTED:
        raise MissingOptionalDependency(
            "The scikit-image package is required for the SAL "
            "verification method but it is not installed"
        )
    if thr_factor is not None and thr_quantile is None:
        raise ValueError("You must pass thr_quantile, too")
    if tstorm_kwargs is None:
        tstorm_kwargs = dict()
    if thr_factor is not None:
        zero_value = np.nanmin(precip)
        threshold = thr_factor * np.nanquantile(
            precip[precip > zero_value], thr_quantile
        )
        tstorm_kwargs = {
            "minmax": tstorm_kwargs.get("minmax", threshold),
            "maxref": tstorm_kwargs.get("maxref", threshold + 1e-5),
            "mindiff": tstorm_kwargs.get("mindiff", 1e-5),
            "minref": tstorm_kwargs.get("minref", threshold),
        }
    _, labels = tstorm_detect.detection(precip, **tstorm_kwargs)
    labels = labels.astype(int)
    precip_objects = pd.DataFrame(
        regionprops_table(labels, intensity_image=precip, properties=REGIONPROPS)
    )
    return precip_objects
Detect coherent precipitation objects using a multi-threshold approach from
:cite:`Feldmann2021`.

Parameters
----------
precip: array-like
Array of shape (m,n) containing input data. Nan values are ignored.
thr_factor: float
Factor used to compute the detection threshold as in eq. 1 of :cite:`WHZ2009`.
If not None, this is used to identify coherent objects enclosed by the
threshold contour `thr_factor * thr_quantile(precip)`.
thr_quantile: float
The wet quantile between 0 and 1 used to define the detection threshold.
Required if `thr_factor` is not None.
tstorm_kwargs: dict
Optional dictionary containing keyword arguments for the tstorm feature
detection algorithm. If None, default values are used.
See the documentation of :py:func:`pysteps.feature.tstorm.detection`.

Returns
-------
precip_objects: pd.DataFrame
Dataframe containing all detected cells and their respective properties.
pysteps/verification/salscores.py