Example #1
0
def plot_scatter_4D(data, x_key, y_key, size_key=None, color_key=None, 
                    x_label=None, y_label=None, size_label=None, color_fn=None,
                    add_marker_text=False, ax=None):
    """y_key can be a list..."""
    colors = np.asarray(['b','r','g','y'])

    # Massage inputs
    if isinstance(y_key, string_types):
        y_key = [y_key]
    if isinstance(size_key, string_types):
        size_key = [size_key]
    if isinstance(color_key, string_types):
        color_key = [color_key]
    if x_label is None:
        x_label = compute_scatter_label(x_key)
    if y_label is None:
        y_label = compute_scatter_label(y_key)
    if size_label is None:
        size_label = compute_scatter_label(s_key)
    if ax is None:
        ax = plt.figure(figsize=(11, 10.5)).gca()

    # Now get all the data, and manipulate as needed
    kwargs = {
        'x': compute_key_data(data.data_dict, x_key),
        'y': [compute_key_data(data.data_dict, k) for k in y_key]}

    if size_key is not None:
        kwargs['s'] = np.asarray([compute_key_data(data.data_dict, k)
                                  for k in size_key])

    if color_key is not None:
        kwargs['c'] = np.asarray([compute_key_data(data.data_dict, k) 
                                  for k in color_key])
    elif color_fn is not None:
        kwargs['c'] = np.asarray([{k: color_fn(k, v) for k, v in kwargs['x'].items()}])

    # Make sure everybody has the same keys
    common_keys = [get_nonhemi_key(k) 
                   for k in kwargs['x'].keys()
                   if not is_bad_key(k) and ~np.all(np.isnan(kwargs['x'][k]))]
    if len(common_keys) == 0:
        raise ValueError('Your x key has an issue.')
    for key in list(set(kwargs.keys()) - set(['x'])):
        # Loop over 
        cur_keys = [get_nonhemi_key(k)
                    for ddata in kwargs[key]
                    for k in ddata.keys()
                    if ~np.all(np.isnan(ddata[k]))]
        common_keys = [k for k in common_keys if k in cur_keys]
    if len(common_keys) == 0:
        raise ValueError('Your x and y keys have no overlap.')

    # Finally, we're safe to convert all of the data to numpy arrays,
    #   then massage the data.
    # NOTE: Loop over common keys, so all are ordered similarly
    #  BUT the actual keys in each dict is NOT the common_key,
    #  but some measure-specific version of it.
    #
    gmc = get_measure_key
    kwargs['x'] = np.asarray([kwargs['x'][gmc(ck, kwargs['x'].keys())]
                              for ck in common_keys])
    for key in list(set(kwargs.keys()) - set(['x'])):
        kwargs[key] = np.asarray([sdata[gmc(ck, sdata.keys())]
                                  for sdata in kwargs[key]
                                  for ck in common_keys])

    if 's' in kwargs:
        kwargs['s'] = 1000  * kwargs['s'] / np.abs(kwargs['s']).mean()
    if 'c' in kwargs:
        kwargs['c'] = colors[kwargs['c']].ravel()

    # Now plot it, and annotate it!
    ax.scatter(**kwargs)
    ax.tick_params(labelsize=16)
    if x_label:
        ax.set_xlabel(x_label, fontsize=18)
    if y_label:
        ax.set_ylabel(y_label, fontsize=18)
    if size_label:
        if 'thickness' in size_label:  # hack
            loc='upper left'
        else:
            loc='upper right'
        ax.legend([size_label], loc=loc)

    if add_marker_text:
        # Interesting if it's outside of some range of values
        is_interesting = lambda v, varr, dist: np.abs(varr.mean() - v) >= dist * varr.std()

        for label, x, y, s, c in zip(common_keys, kwargs['x'], kwargs['y'], kwargs['s'], kwargs['c']):
            annotations = [key for key, sval in zip(['x', 'y', 's'], [1.35, 1.5, 2])
                           if is_interesting(locals()[key], kwargs[key], sval)]
            if len(annotations) > 0:
                plt.annotate(
                    '%s (%s)' % (get_anatomical_name(get_nonhemi_key(label)), ', '.join(annotations)),
                    xy = (x, y), xytext = (25, 25),
                    textcoords = 'offset points', ha = 'right', va = 'bottom',
                    bbox = dict(boxstyle = 'round,pad=0.5', fc = 'yellow', alpha = 0.5),
                    arrowprops = dict(arrowstyle = '->', connectionstyle = 'arc3,rad=0'),
                    fontsize=16)

    plt.axis('equal') #ax.set_aspect('equal')
    if np.any(kwargs['x'] <= 0) and np.any(kwargs['x'] >= 0):
        ax.plot([0, 0], ax.get_ylim(), 'k--')  # y-axis
    if np.any(kwargs['y'] <= 0) and np.any(kwargs['y'] >= 0):
       ax.plot(ax.get_xlim(), [0, 0], 'k--')  # x-axis
    plt.axis('tight')
    return ax