def reconstruct_ancestral_states(tree, character, states, prediction_method=MPPA, model=F81,
                                 params=None, avg_br_len=None, num_nodes=None, num_tips=None,
                                 force_joint=True):
    logging.getLogger('pastml').debug('ACR settings for {}:\n\tMethod:\t{}{}.'
                                      .format(character, prediction_method,
                                              '\n\tModel:\t{}'.format(model)
                                              if model and is_ml(prediction_method) else ''))
    if COPY == prediction_method:
        return {CHARACTER: character, STATES: states, METHOD: prediction_method}
    if not num_nodes:
        num_nodes = sum(1 for _ in tree.traverse())
    if not num_tips:
        num_tips = len(tree)
    if is_ml(prediction_method):
        if avg_br_len is None:
            avg_br_len = np.mean(n.dist for n in tree.traverse() if n.dist)
        freqs, sf, kappa = None, None, None
        if params is not None:
            freqs, sf, kappa = _parse_pastml_parameters(params, states)
        return ml_acr(tree=tree, character=character, prediction_method=prediction_method, model=model, states=states,
                      avg_br_len=avg_br_len, num_nodes=num_nodes, num_tips=num_tips, freqs=freqs, sf=sf, kappa=kappa,
                      force_joint=force_joint)
    if is_parsimonious(prediction_method):
        return parsimonious_acr(tree, character, prediction_method, states, num_nodes, num_tips)
    raise ValueError('Method {} is unknown, should be one of ML ({}), one of MP ({}) or {}'
                     .format(prediction_method, ', '.join(ML_METHODS), ', '.join(MP_METHODS), COPY))