def run_synthesis(synthesis_args):
    """
    A parallel run of the synthesis step

    :param synthesis_args: 
        n = name of the synthesizer, 
        s = synthesizer object,
        synth_args = dictionary of hyperparams for the synthesizer
        d = name of dataset
        e = epsilon value 
        datasets = dataset dictionary 
        cat_cols = list of categorical columns in dataset d
    :type synthesis_args: tuple
    :return: (n, d, str(e), sampled = synthesized data of size len(d))
    :rtype: tuple
    """
    n, s, synth_args, d, e, datasets, cat_cols = synthesis_args
    synth = s(epsilon=float(e), **synth_args)
    d_copy = datasets[d]["data"].copy()
    sampled = synth.fit_sample(d_copy,categorical_columns=cat_cols.split(','))
    print(datasets[d]["name"] + ' finished. Epsilon: ' + str(e))
    datasets[d][n][str(e)] = sampled
    return (n, d, str(e), sampled)