def merge_intervals_strandaware(ranges_dict):
    """
    Perform in-silico mutagenesis on what the dataloader has returned.

    This function has to convert the DNA regions in the model input according to ref, alt, fwd, rc and
    return a dictionary of which the keys are compliant with evaluation_function arguments

    DataLoaders that implement fwd and rc sequence output *__at once__* are not treated in any special way.
    Perform in-silico mutagenesis on what the dataloader has returned.

    This function has to convert the DNA regions in the model input according to ref, alt, fwd, rc and
    return a dictionary of which the keys are compliant with evaluation_function arguments

    DataLoaders that implement fwd and rc sequence output *__at once__* are not treated in any special way.
    `ranges_dict`: dictionary of GenomicsRanges
    Returns unified ranges
    """
    from intervaltree import IntervalTree
    chrom_trees = {}
    for k in ranges_dict:
        assert len(ranges_dict[k]['chr']) == 1
        chr_str = [ranges_dict[k]['chr'][0], ranges_dict[k]['strand'][0]]
        start = ranges_dict[k]['start'][0]
        end = ranges_dict[k]['end'][0]
        if chr_str not in chrom_trees:
            chrom_trees[chr_str] = IntervalTree()
        chrom_trees[chr_str][start:end] = [k]
    [chrom_trees[chr_str].merge_overlaps(lambda x, y: x + y) for chr_str in
        chrom_trees]
    out_regions = {k: [] for k in ['chr', 'start', 'end', 'strand']}
    ranges_ks = []
    for chr_str in chrom_trees:
        for interval in chrom_trees[chr_str]:
            out_regions['chr'].append(chr_str[0])
            out_regions['strand'].append(chr_str[1])
            out_regions['start'].append(interval.begin)
            out_regions['end'].append(interval.end)
            ranges_ks.append(interval.data)
    return out_regions, ranges_ks
