def gb_simulation(n_trials,
                  n_blocks,
                  sigma,
                  agent,
                  beta,
                  task_agent_analysis=False,
                  eval_ana=True):
    """ This function runs the simulations for model demonstration

    :param n_trials: Number of trials
    :param n_blocks: Number of blocks
    :param sigma: Perceptual sensitivity
    :param agent: Agent-based computational model
    :param beta: Inverse temperature parameter
    :param task_agent_analysis: Indicates if use for data analysis or not
    :param eval_ana: Evaluate agent analytically
    :return: df_subj: Data frame containing simulated data
    """

    # Parameter definition
    # --------------------

    # Task parameters in GbTaskVars.py object
    task_vars = TaskVars()
    task_vars.T = n_trials
    task_vars.B = n_blocks
    task_vars.experiment = 3

    # Agent parameters in GbAgentVars.py object
    agent_vars = AgentVars()
    agent_vars.sigma = sigma
    agent_vars.beta = beta
    agent_vars.c0 = np.array([1])
    agent_vars.kappa = task_vars.kappa
    agent_vars.agent = agent
    agent_vars.lambda_param = np.nan
    agent_vars.task_agent_analysis = task_agent_analysis
    agent_vars.eval_ana = eval_ana

    # Simulation parameters in GbSimVars.py object
    sim_vars = SimVars()

    # Initialize data frame for simulation
    df_subj = pd.DataFrame()

    sleep(0.1)
    print('\nSimulating data for agent demonstration:')
    sleep(0.1)
    pbar = tqdm(total=task_vars.B)

    # Cycle over task blocks
    for b in range(0, task_vars.B):

        # Update progress bar
        pbar.update(1)

        # Block number definition
        sim_vars.block = b
        sim_vars.take_pd = 0

        # Single block task-agent-interaction simulation
        df_block = gb_task_agent_int(task_vars, agent_vars, sim_vars)

        # Add data to data frame
        df_subj = df_subj.append(df_block, ignore_index=True)

    # Close progress bar
    pbar.close()

    return df_subj
kappa = 0.08  # Maximal contrast difference value
sigma = 0.04  # Perceptual sensitivity

# Initialize task and agent objects
# ---------------------------------

# Task parameters in TaskVars object
task_vars = TaskVars()
task_vars.T = T
task_vars.B = 1
task = Task(task_vars)

# Agent parameters in AgentVars object
agent_vars = AgentVars()
agent_vars.agent = 1
agent_vars.sigma = sigma
agent_vars.task_agent_analysis = False
agent = Agent(agent_vars)
agent.d_t = 0  # Fix perceptual decision to d_t = 0
agent.a_t = 0  # Fix action to a_t = 0

# Sampling-based approximation object
p_hat = PHat(n_bins)

# Number of variables x number of samples x number of time points sample matrix
S = np.full([5, n_samples, T], np.nan)

# Simulation scenarios / observed random variable values
# ------------------------------------------------------

O_list = list()
def recovsim(task_vars, sim_vars, exp_data, **kwargs):
    """ This function runs the simulations for parameter and model recovery

    :param task_vars: Variables to initialize the task object
    :param sim_vars: Variables to initialize the simulation object
    :param exp_data: Experimental data
    :param kwargs: Optionally; participant parameters
    :return: df_recov: Data-frame with simulated data
    """

    # Extract the optionally provided parameters
    opt_params = kwargs.get('opt_params', None)

    # Agent parameters
    agent_vars = AgentVars()
    agent_vars.agent = sim_vars.agent

    # Initialize data frame for data that will be recovered
    df_recov = pd.DataFrame()

    # Initialize counter for simulation order
    sleep(0.1)
    print('\nSimulating data for recovery | Agent A%s:' % sim_vars.agent)
    sleep(0.1)
    pbar = tqdm(total=len(opt_params))

    # Initialize array that indicates the ID of data set used for simulations
    which_id = np.full(len(opt_params), np.nan)

    # Cycle over parameters
    for m in range(0, len(opt_params)):

        # Randomly determine current data set
        which_id[m] = randint(0, sim_vars.N - 1)

        # For experiment 2 and 3 we additionally use participant parameters
        if task_vars.experiment == 2:
            agent_vars.sigma = opt_params['sigma'][m]
        elif task_vars.experiment == 3:
            agent_vars.sigma = opt_params['sigma'][m]
            if sim_vars.agent == 1:
                agent_vars.beta = opt_params['beta_A1'][m]
            elif sim_vars.agent == 2:
                agent_vars.beta = opt_params['beta_A2'][m]
            elif sim_vars.agent == 3:
                agent_vars.beta = opt_params['beta_A3'][m]
                agent_vars.lambda_param = opt_params['lambda_A3'][m]
            elif sim_vars.agent == 4:
                agent_vars.beta = opt_params['beta_A4'][m]
                agent_vars.alpha = opt_params['alpha_A4'][m]
            elif sim_vars.agent == 5:
                agent_vars.beta = opt_params['beta_A5'][m]
                agent_vars.alpha = opt_params['alpha_A5'][m]
            elif sim_vars.agent == 6:
                agent_vars.beta = opt_params['beta_A6'][m]
                agent_vars.alpha = opt_params['alpha_A6'][m]
                agent_vars.lambda_param = opt_params['lambda_A6'][m]

        # Cycle over task blocks
        for b in range(0, task_vars.B):

            # Extract data of current block
            exp_data_block = exp_data[(exp_data['id'] == which_id[m])
                                      & (exp_data['b_t'] == b)].copy()

            # Add trial as index
            exp_data_block.loc[:,
                               'trial'] = np.linspace(0,
                                                      len(exp_data_block) - 1,
                                                      len(exp_data_block))
            exp_data_block = exp_data_block.set_index('trial')

            # Block number definition
            sim_vars.block = b

            # Single block task-agent-interaction simulation
            df_block = gb_task_agent_int(task_vars,
                                         agent_vars,
                                         sim_vars,
                                         real_outc=exp_data_block)
            df_block['id'] = m
            df_block['blockNumber'] = b
            df_block['agent'] = sim_vars.agent

            # Add data to data frame
            df_recov = df_recov.append(df_block, ignore_index=True)

        # Update progress bar
        pbar.update(1)

    if task_vars.experiment == 2 or task_vars.experiment == 3:

        # Check if this is consistent across scripts
        # This could be adjusted at the global level
        df_recov = df_recov.rename(index=str,
                                   columns={"corr": "decision2.corr"})
        df_recov['a_t'] = df_recov['a_t'] + 1

    # Close progress par
    pbar.close()

    return df_recov