    def __check_inputs(self):
        """
        Validates the inputs and determines if the user provided raw forecasts or decomposed forecasts.
        """
        # Check dimensions of precip
        if self.__precip.ndim != 3:
            raise ValueError(
                "precip must be a three-dimensional array of shape (ar_order + 1, m, n)"
            )
        if self.__precip.shape[0] < self.__config.ar_order + 1:
            raise ValueError(
                f"precip must have at least {self.__config.ar_order + 1} time steps in the first dimension "
                f"to match the autoregressive order (ar_order={self.__config.ar_order})"
            )

        # Check dimensions of velocity
        if self.__velocity.ndim != 3:
            raise ValueError(
                "velocity must be a three-dimensional array of shape (2, m, n)"
            )
        if self.__velocity_models.ndim != 5:
            raise ValueError(
                "velocity_models must be a five-dimensional array of shape (n_models, timestep, 2, m, n)"
            )
        if self.__velocity.shape[0] != 2 or self.__velocity_models.shape[2] != 2:
            raise ValueError(
                "velocity and velocity_models must have an x- and y-component, check the shape"
            )

        # Check that spatial dimensions match between precip and velocity
        if self.__precip.shape[1:3] != self.__velocity.shape[1:3]:
            raise ValueError(
                f"Spatial dimensions of precip and velocity do not match: "
                f"{self.__precip.shape[1:3]} vs {self.__velocity.shape[1:3]}"
            )
        # Check if the number of members in the precipitation models and velocity models match
        if self.__precip_models.shape[0] != self.__velocity_models.shape[0]:
            raise ValueError(
                "The number of members in the precipitation models and velocity models must match"
            )

        if isinstance(self.__timesteps, list):
            self.__params.time_steps_is_list = True
            if not sorted(self.__timesteps) == self.__timesteps:
                raise ValueError(
                    "timesteps is not in ascending order", self.__timesteps
                )
            if self.__precip_models.shape[1] != math.ceil(self.__timesteps[-1]) + 1:
                raise ValueError(
                    "precip_models does not contain sufficient lead times for this forecast"
                )
            self.__params.original_timesteps = [0] + list(self.__timesteps)
            self.__timesteps = nowcast_utils.binned_timesteps(
                self.__params.original_timesteps
            )
        else:
            self.__params.time_steps_is_list = False
            if self.__precip_models.shape[1] != self.__timesteps + 1:
                raise ValueError(
                    "precip_models does not contain sufficient lead times for this forecast"
                )
            self.__timesteps = list(range(self.__timesteps + 1))

        precip_nwp_dim = self.__precip_models.ndim
        if precip_nwp_dim == 2:
            if isinstance(self.__precip_models[0][0], dict):
                # It's a 2D array of dictionaries with decomposed cascades
                self.__params.precip_models_provided_is_cascade = True
            else:
                raise ValueError(
                    "When precip_models has ndim == 2, it must contain dictionaries with decomposed cascades."
                )
        elif precip_nwp_dim == 4:
            self.__params.precip_models_provided_is_cascade = False
        else:
            raise ValueError(
                "precip_models must be either a two-dimensional array containing dictionaries with decomposed model fields"
                "or a four-dimensional array containing the original (NWP) model forecasts"
            )

        if self.__config.extrapolation_kwargs is None:
            self.__state.extrapolation_kwargs = dict()
        else:
            self.__state.extrapolation_kwargs = deepcopy(
                self.__config.extrapolation_kwargs
            )

        if self.__config.filter_kwargs is None:
            self.__params.filter_kwargs = dict()
        else:
            self.__params.filter_kwargs = deepcopy(self.__config.filter_kwargs)

        if self.__config.noise_kwargs is None:
            self.__params.noise_kwargs = {"win_fun": "tukey"}
        else:
            self.__params.noise_kwargs = deepcopy(self.__config.noise_kwargs)

        if self.__config.velocity_perturbation_kwargs is None:
            self.__params.velocity_perturbation_kwargs = dict()
        else:
            self.__params.velocity_perturbation_kwargs = deepcopy(
                self.__config.velocity_perturbation_kwargs
            )

        if self.__config.climatology_kwargs is None:
            # Make sure clim_kwargs at least contains the number of models
            self.__params.climatology_kwargs = dict(
                {"n_models": self.__precip_models.shape[0]}
            )
        else:
            self.__params.climatology_kwargs = deepcopy(
                self.__config.climatology_kwargs
            )

        if self.__config.mask_kwargs is None:
            self.__params.mask_kwargs = dict()
        else:
            self.__params.mask_kwargs = deepcopy(self.__config.mask_kwargs)

        if np.any(~np.isfinite(self.__velocity)):
            raise ValueError("velocity contains non-finite values")

        if self.__config.mask_method not in ["obs", "incremental", None]:
            raise ValueError(
                "unknown mask method %s: must be 'obs', 'incremental' or None"
                % self.__config.mask_method
            )

        if self.__config.conditional and self.__config.precip_threshold is None:
            raise ValueError("conditional=True but precip_thr is not set")

        if (
            self.__config.mask_method is not None
            and self.__config.precip_threshold is None
        ):
            raise ValueError("mask_method!=None but precip_thr=None")

        if self.__config.noise_stddev_adj not in ["auto", "fixed", None]:
            raise ValueError(
                "unknown noise_std_dev_adj method %s: must be 'auto', 'fixed', or None"
                % self.__config.noise_stddev_adj
            )

        if self.__config.kmperpixel is None:
            if self.__config.velocity_perturbation_method is not None:
                raise ValueError(
                    "velocity_perturbation_method is set but kmperpixel=None"
                )
            if self.__config.mask_method == "incremental":
                raise ValueError("mask_method='incremental' but kmperpixel=None")

        if self.__config.timestep is None:
            if self.__config.velocity_perturbation_method is not None:
                raise ValueError(
                    "velocity_perturbation_method is set but timestep=None"
                )
            if self.__config.mask_method == "incremental":
                raise ValueError("mask_method='incremental' but timestep=None")
Validates the inputs and determines if the user provided raw forecasts or decomposed forecasts.
pysteps/blending/steps.py