'Rerun a tool to produce a new output dataset that corresponds to a
dataset that a user is currently viewing.'

def _rerun_tool(self, trans, payload, **kwargs):

    run_on_regions = False
    regions = payload.get('regions', None)
    if regions:
        if isinstance(regions, dict):
            regions = [GenomeRegion.from_dict(regions)]
        elif isinstance(regions, list):
            regions = [GenomeRegion.from_dict(r) for r in regions]
            if (len(regions) > 1):
                regions = sorted(regions, key=(lambda r: (r.chrom.lower(), r.start)))
                prev = regions[0]
                cur = regions[1]
                index = 1
                while True:
                    if ((cur.chrom == prev.chrom) and (cur.start <= prev.end)):
                        prev.end = cur.end
                        del regions[index]
                    else:
                        prev = cur
                        index += 1
                    if (index == len(regions)):
                        break
                    else:
                        cur = regions[index]
        run_on_regions = True
    decoded_dataset_id = self.decode_id(payload.get('target_dataset_id'))
    original_dataset = self.hda_manager.get_accessible(decoded_dataset_id, user=trans.user)
    original_dataset = self.hda_manager.error_if_uploading(original_dataset)
    msg = self.hda_manager.data_conversion_status(original_dataset)
    if msg:
        return msg
    original_job = self.hda_manager.creating_job(original_dataset)
    tool = trans.app.toolbox.get_tool(original_job.tool_id)
    if ((not tool) or (not tool.allow_user_access(trans.user))):
        return trans.app.model.Dataset.conversion_messages.NO_TOOL
    tool_params = dict([(p.name, p.value) for p in original_job.parameters])
    new_inputs = payload['inputs']
    tool_params.update(dict([(key, dumps(value)) for (key, value) in new_inputs.items() if ((key in tool.inputs) and (new_inputs[key] is not None))]))
    tool_params = tool.params_from_strings(tool_params, self.app)
    data_provider_registry = trans.app.data_provider_registry
    messages_list = []
    if run_on_regions:
        for jida in original_job.input_datasets:
            input_dataset = jida.dataset
            data_provider = data_provider_registry.get_data_provider(trans, original_dataset=input_dataset, source='data')
            if (data_provider and ((not data_provider.converted_dataset) or (data_provider.converted_dataset.state != trans.app.model.Dataset.states.OK))):
                data_sources = input_dataset.datatype.data_sources
                msg = input_dataset.convert_dataset(trans, data_sources['data'])
                if (msg is not None):
                    messages_list.append(msg)
    return_message = self._get_highest_priority_msg(messages_list)
    if return_message:
        return return_message
    if (original_dataset.history.user == trans.user):
        target_history = original_dataset.history
    else:
        target_history = trans.get_history(create=True)
    hda_permissions = trans.app.security_agent.history_get_default_permissions(target_history)
    def set_param_value(param_dict, param_name, param_value):
        "\n                                                Set    new    parameter    value    in    a    tool's    parameter    dictionary.\n                                                "
        def set_value(param_dict, group_name, group_index, param_name, param_value):
            if (group_name in param_dict):
                param_dict[group_name][group_index][param_name] = param_value
                return True
            elif (param_name in param_dict):
                param_dict[param_name] = param_value
                return True
            else:
                return_val = False
                for value in param_dict.values():
                    if isinstance(value, dict):
                        return_val = set_value(value, group_name, group_index, param_name, param_value)
                        if return_val:
                            return return_val
                return False
        if (param_name.find('|') == (-1)):
            group_name = group_index = None
        else:
            (group, param_name) = param_name.split('|')
            index = group.rfind('_')
            group_name = group[:index]
            group_index = int(group[(index + 1):])
        return set_value(param_dict, group_name, group_index, param_name, param_value)
    params_set = {}
    for action in tool.trackster_conf.actions:
        success = False
        for joda in original_job.output_datasets:
            if (joda.name == action.output_name):
                set_param_value(tool_params, action.name, joda.dataset)
                params_set[action.name] = True
                success = True
                break
        if (not success):
            return trans.app.model.Dataset.conversion_messages.ERROR
    if run_on_regions:
        regions_str = ','.join([str(r) for r in regions])
    for jida in original_job.input_datasets:
        if (jida.name in params_set):
            continue
        input_dataset = jida.dataset
        if (input_dataset is None):
            tool_params[jida.name] = None
        elif (run_on_regions and ('data' in input_dataset.datatype.data_sources)):
            subset_dataset_association = trans.sa_session.query(trans.app.model.HistoryDatasetAssociationSubset).filter_by(hda=input_dataset, location=regions_str).first()
            if subset_dataset_association:
                subset_dataset = subset_dataset_association.subset
            else:
                data_source = input_dataset.datatype.data_sources['data']
                input_dataset.get_converted_dataset(trans, data_source)
                input_dataset.get_converted_dataset_deps(trans, data_source)
                new_dataset = trans.app.model.HistoryDatasetAssociation(extension=input_dataset.ext, dbkey=input_dataset.dbkey, create_dataset=True, sa_session=trans.sa_session, name=('Subset    [%s]    of    data    %i' % (regions_str, input_dataset.hid)), visible=False)
                target_history.add_dataset(new_dataset)
                trans.sa_session.add(new_dataset)
                trans.app.security_agent.set_all_dataset_permissions(new_dataset.dataset, hda_permissions)
                data_provider = data_provider_registry.get_data_provider(trans, original_dataset=input_dataset, source='data')
                trans.app.object_store.create(new_dataset.dataset)
                data_provider.write_data_to_file(regions, new_dataset.file_name)
                new_dataset.set_size()
                new_dataset.info = 'Data    subset    for    trackster'
                new_dataset.set_dataset_state(trans.app.model.Dataset.states.OK)
                trans.app.datatypes_registry.set_external_metadata_tool.tool_action.execute(trans.app.datatypes_registry.set_external_metadata_tool, trans, incoming={'input1': new_dataset}, overwrite=False, job_params={'source': 'trackster'})
                subset_association = trans.app.model.HistoryDatasetAssociationSubset(hda=input_dataset, subset=new_dataset, location=regions_str)
                trans.sa_session.add(subset_association)
                subset_dataset = new_dataset
            trans.sa_session.flush()
            if (not set_param_value(tool_params, jida.name, subset_dataset)):
                return {'error': True, 'message': ('error    setting    parameter    %s' % jida.name)}
    try:
        (subset_job, subset_job_outputs) = tool.execute(trans, incoming=tool_params, history=target_history, job_params={'source': 'trackster'})
    except Exception as e:
        return {'error': True, 'message': ((e.__class__.__name__ + ':    ') + str(e))}
    if run_on_regions:
        for output in subset_job_outputs.values():
            output.visible = False
        trans.sa_session.flush()
    output_name = None
    for joda in original_job.output_datasets:
        if (joda.dataset == original_dataset):
            output_name = joda.name
            break
    for joda in subset_job.output_datasets:
        if (joda.name == output_name):
            output_dataset = joda.dataset
    dataset_dict = output_dataset.to_dict()
    dataset_dict['id'] = trans.security.encode_id(dataset_dict['id'])
    dataset_dict['track_config'] = self.get_new_track_config(trans, output_dataset)
    return dataset_dict
