def gradient(window_size, states_path, states_list):
    ctx = click.get_current_context()
    properties = ctx.meta['properties']

    if states_path:
        states = ctx.meta['files_manager'].read_csv(states_path)
    else:
        bins = [-inf] + [float(x) for x in states_list.split(' ')] + [inf]
        bins_lows_per_property = bins[:-1]
        bins_highs_per_property = bins[1:]

        bins_lows = np.tile(bins_lows_per_property, len(properties))
        bins_highs = np.tile(bins_highs_per_property, len(properties))

        states = DataframesGenerator.generate_states(
            np.arange(1,
                      len(bins_lows) + 1),
            np.repeat(properties, len(bins_lows_per_property)),
            np.tile(np.arange(len(bins_lows_per_property)), len(properties)),
            bins_lows, bins_highs, np.full(len(bins_lows), np.nan))

    params_df = DataframesGenerator.generate_temporal_abstraction_params(
        properties, ['gradient'] * len(properties),
        np.full(len(properties), nan), np.full(len(properties), window_size))

    system_flow(ctx.meta['files_manager'],
                ctx.meta['preprocessing_params_df'],
                params_df,
                states,
                kfold=ctx.meta['kfold'])
    def create_prop_states(prop_id, cutpoints, scores=None):
        """
        Creates a states dataframe for a single property, containing the cutpoints and scores given as parameter
        :param prop_id: int, the property id
        :param cutpoints: List, a list of cutpoints
        :param scores: List, a list of scores, one for each cut-point
        :return: Dataframe, a states dataframe
        """
        nb_states = len(cutpoints) + 1
        bin_low = [-inf] + cutpoints
        bin_high = cutpoints + [inf]

        if scores is None:
            scores = np.full(nb_states - 1, np.nan)

        states = DataframesGenerator.generate_states(
            np.arange(1, nb_states + 1),
            np.full(nb_states, prop_id),
            np.arange(nb_states),
            bin_low,
            bin_high,
            np.append([nan], scores)
        )
        return states