def sal_structure(
    prediction, observation, thr_factor=None, thr_quantile=None, tstorm_kwargs=None
):
    """
    Compute the structure component for SAL based on :cite:`WPHF2008`.

    Parameters
    ----------
    prediction: array-like
        Array of shape (m,n) with prediction data. NaNs are ignored.
    observation: array-like
        Array of shape (m,n) with observation data. NaNs are ignored.
    thr_factor: float, optional
        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, optional
        The wet quantile between 0 and 1 used to define the detection threshold.
        Required if `thr_factor` is not None.
    tstorm_kwargs: dict, optional
        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
    -------
    structure: float
        The structure component with value between -2 to 2 and 0 denotes perfect
        forecast in terms of structure. The returned value is NaN if no objects are
        detected in neither the prediction nor the observation.

    See also
    --------
    :py:func:`pysteps.verification.salscores.sal`,
    :py:func:`pysteps.verification.salscores.sal_amplitude`,
    :py:func:`pysteps.verification.salscores.sal_location`,
    :py:mod:`pysteps.feature.tstorm`
    """
    prediction_objects = _sal_detect_objects(
        prediction, thr_factor, thr_quantile, tstorm_kwargs
    )
    observation_objects = _sal_detect_objects(
        observation, thr_factor, thr_quantile, tstorm_kwargs
    )
    prediction_volume = _sal_scaled_volume(prediction_objects)
    observation_volume = _sal_scaled_volume(observation_objects)
    nom = prediction_volume - observation_volume
    denom = prediction_volume + observation_volume
    return np.divide(nom, (0.5 * denom))
Compute the structure component for SAL based on :cite:`WPHF2008`.

Parameters
----------
prediction: array-like
Array of shape (m,n) with prediction data. NaNs are ignored.
observation: array-like
Array of shape (m,n) with observation data. NaNs are ignored.
thr_factor: float, optional
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, optional
The wet quantile between 0 and 1 used to define the detection threshold.
Required if `thr_factor` is not None.
tstorm_kwargs: dict, optional
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
-------
structure: float
The structure component with value between -2 to 2 and 0 denotes perfect
forecast in terms of structure. The returned value is NaN if no objects are
detected in neither the prediction nor the observation.

See also
--------
:py:func:`pysteps.verification.salscores.sal`,
:py:func:`pysteps.verification.salscores.sal_amplitude`,
:py:func:`pysteps.verification.salscores.sal_location`,
:py:mod:`pysteps.feature.tstorm`
pysteps/verification/salscores.py