latools/helpers/plot.py
def crossplot(dat, keys=None, lognorm=True, bins=25, figsize=(12, 12),
              colourful=True, focus_stage=None, denominator=None,
              mode='hist2d', cmap=None, **kwargs):
    """
    Plot analytes against each other.

    The number of plots is n**2 - n, where n = len(keys).

    Parameters
    ----------
    dat : dict
        A dictionary of key: data pairs, where data is the same
        length in each entry.
    keys : optional, array_like or str
        The keys of dat to plot. Defaults to all keys.
    lognorm : bool
        Whether or not to log normalise the colour scale
        of the 2D histogram.
    bins : int
        The number of bins in the 2D histogram.
    figsize : tuple
    colourful : bool

    Returns
    -------
    (fig, axes)
    """
    if keys is None:
        keys = list(dat.keys())

    numvar = len(keys)
    if figsize[0] < 1.5 * numvar:
        figsize = [1.5 * numvar] * 2
    
    fig, axes = plt.subplots(nrows=numvar, ncols=numvar,
                             figsize=(12, 12))
    fig.subplots_adjust(hspace=0.05, wspace=0.05)

    for ax in axes.flat:
        ax.xaxis.set_visible(False)
        ax.yaxis.set_visible(False)

        if ax.is_first_col():
            ax.yaxis.set_ticks_position('left')
        if ax.is_last_col():
            ax.yaxis.set_ticks_position('right')
        if ax.is_first_row():
            ax.xaxis.set_ticks_position('top')
        if ax.is_last_row():
            ax.xaxis.set_ticks_position('bottom')

    # set up colour scales
    if colourful:
        cmlist = ['Blues', 'BuGn', 'BuPu', 'GnBu',
                  'Greens', 'Greys', 'Oranges', 'OrRd',
                  'PuBu', 'PuBuGn', 'PuRd', 'Purples',
                  'RdPu', 'Reds', 'YlGn', 'YlGnBu', 'YlOrBr', 'YlOrRd']
    else:
        cmlist = ['Greys']

    if cmap is None and mode == 'scatter':
        cmap = {k: 'k' for k in dat.keys()}

    while len(cmlist) < len(keys):
        cmlist *= 2

    # isolate nominal_values for all keys
    focus = {k: nominal_values(dat[k]) for k in keys}
    # determine units for all keys
    udict = {a: unitpicker(np.nanmean(focus[a]),
                           focus_stage=focus_stage,
                           denominator=denominator) for a in keys}
    # determine ranges for all analytes
    rdict = {a: (np.nanmin(focus[a] * udict[a][0]),
                 np.nanmax(focus[a] * udict[a][0])) for a in keys}

    for i, j in tqdm(zip(*np.triu_indices_from(axes, k=1)), desc='Drawing Plots',
                     total=sum(range(len(keys)))):
        # get analytes
        ai = keys[i]
        aj = keys[j]

        # remove nan, apply multipliers
        pi = focus[ai] * udict[ai][0]
        pj = focus[aj] * udict[aj][0]

        # determine normalisation shceme
        if lognorm:
            norm = mpl.colors.LogNorm()
        else:
            norm = None

        # draw plots
        if mode == 'hist2d':
            # remove nan
            pi = pi[~np.isnan(pi)]
            pj = pj[~np.isnan(pj)]

            axes[i, j].hist2d(pj, pi, bins,
                              norm=norm,
                              cmap=plt.get_cmap(cmlist[i]))
            axes[j, i].hist2d(pi, pj, bins,
                              norm=norm,
                              cmap=plt.get_cmap(cmlist[j]))
        elif mode == 'scatter':
            axes[i, j].scatter(pj, pi, s=10,
                               color=cmap[ai], lw=0.5, edgecolor='k',
                               alpha=0.4)
            axes[j, i].scatter(pi, pj, s=10,
                               color=cmap[aj], lw=0.5, edgecolor='k',
                               alpha=0.4)
        else:
            raise ValueError("invalid mode. Must be 'hist2d' or 'scatter'.")

        axes[i, j].set_ylim(*rdict[ai])
        axes[i, j].set_xlim(*rdict[aj])

        axes[j, i].set_ylim(*rdict[aj])
        axes[j, i].set_xlim(*rdict[ai])

    # diagonal labels
    for a, n in zip(keys, np.arange(len(keys))):
        axes[n, n].annotate(a + '\n' + udict[a][1], (0.5, 0.5),
                            xycoords='axes fraction',
                            ha='center', va='center', fontsize=8)
        axes[n, n].set_xlim(*rdict[a])
        axes[n, n].set_ylim(*rdict[a])
    # switch on alternating axes
    for i, j in zip(range(numvar), itertools.cycle((-1, 0))):
        axes[j, i].xaxis.set_visible(True)
        for label in axes[j, i].get_xticklabels():
            label.set_rotation(90)
        axes[i, j].yaxis.set_visible(True)

    return fig, axes
def crossplot(dat, keys=None, lognorm=True, bins=25, figsize=(12, 12),
              colourful=True, focus_stage=None, denominator=None,
              mode='hist2d', cmap=None, **kwargs):
    """
    Plot analytes against each other.

    The number of plots is n**2 - n, where n = len(keys).

    Parameters
    ----------
    dat : dict
        A dictionary of key: data pairs, where data is the same
        length in each entry.
    keys : optional, array_like or str
        The keys of dat to plot. Defaults to all keys.
    lognorm : bool
        Whether or not to log normalise the colour scale
        of the 2D histogram.
    bins : int
        The number of bins in the 2D histogram.
    figsize : tuple
    colourful : bool

    Returns
    -------
    (fig, axes)
    """
    if keys is None:
        keys = list(dat.keys())

    numvar = len(keys)
    if figsize[0] < 1.5 * numvar:
        figsize = [1.5 * numvar] * 2
    
    fig, axes = plt.subplots(nrows=numvar, ncols=numvar,
                             figsize=(12, 12))
    fig.subplots_adjust(hspace=0.05, wspace=0.05)

    for ax in axes.flat:
        ax.xaxis.set_visible(False)
        ax.yaxis.set_visible(False)

        if ax.is_first_col():
            ax.yaxis.set_ticks_position('left')
        if ax.is_last_col():
            ax.yaxis.set_ticks_position('right')
        if ax.is_first_row():
            ax.xaxis.set_ticks_position('top')
        if ax.is_last_row():
            ax.xaxis.set_ticks_position('bottom')

    # set up colour scales
    if colourful:
        cmlist = ['Blues', 'BuGn', 'BuPu', 'GnBu',
                  'Greens', 'Greys', 'Oranges', 'OrRd',
                  'PuBu', 'PuBuGn', 'PuRd', 'Purples',
                  'RdPu', 'Reds', 'YlGn', 'YlGnBu', 'YlOrBr', 'YlOrRd']
    else:
        cmlist = ['Greys']

    if cmap is None and mode == 'scatter':
        cmap = {k: 'k' for k in dat.keys()}

    while len(cmlist) < len(keys):
        cmlist *= 2

    # isolate nominal_values for all keys
    focus = {k: nominal_values(dat[k]) for k in keys}
    # determine units for all keys
    udict = {a: unitpicker(np.nanmean(focus[a]),
                           focus_stage=focus_stage,
                           denominator=denominator) for a in keys}
    # determine ranges for all analytes
    rdict = {a: (np.nanmin(focus[a] * udict[a][0]),
                 np.nanmax(focus[a] * udict[a][0])) for a in keys}

    for i, j in tqdm(zip(*np.triu_indices_from(axes, k=1)), desc='Drawing Plots',
                     total=sum(range(len(keys)))):
        # get analytes
        ai = keys[i]
        aj = keys[j]

        # remove nan, apply multipliers
        pi = focus[ai] * udict[ai][0]
        pj = focus[aj] * udict[aj][0]

        # determine normalisation shceme
        if lognorm:
            norm = mpl.colors.LogNorm()
        else:
            norm = None

        # draw plots
        if mode == 'hist2d':
            # remove nan
            pi = pi[~np.isnan(pi)]
            pj = pj[~np.isnan(pj)]

            axes[i, j].hist2d(pj, pi, bins,
                              norm=norm,
                              cmap=plt.get_cmap(cmlist[i]))
            axes[j, i].hist2d(pi, pj, bins,
                              norm=norm,
                              cmap=plt.get_cmap(cmlist[j]))
        elif mode == 'scatter':
            axes[i, j].scatter(pj, pi, s=10,
                               color=cmap[ai], lw=0.5, edgecolor='k',
                               alpha=0.4)
            axes[j, i].scatter(pi, pj, s=10,
                               color=cmap[aj], lw=0.5, edgecolor='k',
                               alpha=0.4)
        else:
            raise ValueError("invalid mode. Must be 'hist2d' or 'scatter'.")

        axes[i, j].set_ylim(*rdict[ai])
        axes[i, j].set_xlim(*rdict[aj])

        axes[j, i].set_ylim(*rdict[aj])
        axes[j, i].set_xlim(*rdict[ai])

    # diagonal labels
    for a, n in zip(keys, np.arange(len(keys))):
        axes[n, n].annotate(a + '\n' + udict[a][1], (0.5, 0.5),
                            xycoords='axes fraction',
                            ha='center', va='center', fontsize=8)
        axes[n, n].set_xlim(*rdict[a])
        axes[n, n].set_ylim(*rdict[a])
    # switch on alternating axes
    for i, j in zip(range(numvar), itertools.cycle((-1, 0))):
        axes[j, i].xaxis.set_visible(True)
        for label in axes[j, i].get_xticklabels():
            label.set_rotation(90)
        axes[i, j].yaxis.set_visible(True)

    return fig, axes
Plot analytes against each other.

    The number of plots is n**2 - n, where n = len(keys).

    Parameters
    ----------
    dat : dict
        A dictionary of key: data pairs, where data is the same
        length in each entry.
    keys : optional, array_like or str
        The keys of dat to plot. Defaults to all keys.
    lognorm : bool
        Whether or not to log normalise the colour scale
        of the 2D histogram.
    bins : int
        The number of bins in the 2D histogram.
    figsize : tuple
    colourful : bool

    Returns
    -------
    (fig, axes)