Пример #1
0
def periodic_table_heatmap(elemental_data,
                           cbar_label="",
                           show_plot=False,
                           cmap="YlOrRd",
                           blank_color="grey",
                           value_format=None,
                           max_row=9):
    """
    A static method that generates a heat map overlapped on a periodic table.

    Args:
         elemental_data (dict): A dictionary with the element as a key and a
            value assigned to it, e.g. surface energy and frequency, etc.
            Elements missing in the elemental_data will be grey by default
            in the final table elemental_data={"Fe": 4.2, "O": 5.0}.
         cbar_label (string): Label of the colorbar. Default is "".
         figure_name (string): Name of the plot (absolute path) being saved
            if not None.
         show_plot (bool): Whether to show the heatmap. Default is False.
         value_format (str): Formatting string to show values. If None, no value
            is shown. Example: "%.4f" shows float to four decimals.
         cmap (string): Color scheme of the heatmap. Default is 'coolwarm'.
         blank_color (string): Color assigned for the missing elements in
            elemental_data. Default is "grey".
         max_row (integer): Maximum number of rows of the periodic table to be
            shown. Default is 9, which means the periodic table heat map covers
            the first 9 rows of elements.
    """

    # Convert primitive_elemental data in the form of numpy array for plotting.
    max_val = max(elemental_data.values())
    min_val = min(elemental_data.values())
    max_row = min(max_row, 9)

    if max_row <= 0:
        raise ValueError("The input argument 'max_row' must be positive!")

    value_table = np.empty((max_row, 18)) * np.nan
    blank_value = min_val - 0.01

    for el in Element:
        if el.row > max_row: continue
        value = elemental_data.get(el.symbol, blank_value)
        value_table[el.row - 1, el.group - 1] = value

    # Initialize the plt object
    import matplotlib.pyplot as plt
    fig, ax = plt.subplots()
    plt.gcf().set_size_inches(12, 8)

    # We set nan type values to masked values (ie blank spaces)
    data_mask = np.ma.masked_invalid(value_table.tolist())
    heatmap = ax.pcolor(data_mask,
                        cmap=cmap,
                        edgecolors='w',
                        linewidths=1,
                        vmin=min_val - 0.001,
                        vmax=max_val + 0.001)
    cbar = fig.colorbar(heatmap)

    # Grey out missing elements in input data
    cbar.cmap.set_under(blank_color)
    cbar.set_label(cbar_label, rotation=270, labelpad=15)
    cbar.ax.tick_params(labelsize=14)

    # Refine and make the table look nice
    ax.axis('off')
    ax.invert_yaxis()

    # Label each block with corresponding element and value
    for i, row in enumerate(value_table):
        for j, el in enumerate(row):
            if not np.isnan(el):
                symbol = Element.from_row_and_group(i + 1, j + 1).symbol
                plt.text(j + 0.5,
                         i + 0.25,
                         symbol,
                         horizontalalignment='center',
                         verticalalignment='center',
                         fontsize=14)
                if el != blank_value and value_format is not None:
                    plt.text(j + 0.5,
                             i + 0.5,
                             value_format % el,
                             horizontalalignment='center',
                             verticalalignment='center',
                             fontsize=10)

    plt.tight_layout()

    if show_plot:
        plt.show()

    return plt
Пример #2
0
def periodic_table_heatmap(elemental_data, cbar_label="",
                           show_plot=False, cmap="YlOrRd", blank_color="grey",
                           value_format=None, max_row=9):
    """
    A static method that generates a heat map overlapped on a periodic table.

    Args:
         elemental_data (dict): A dictionary with the element as a key and a
            value assigned to it, e.g. surface energy and frequency, etc.
            Elements missing in the elemental_data will be grey by default
            in the final table elemental_data={"Fe": 4.2, "O": 5.0}.
         cbar_label (string): Label of the colorbar. Default is "".
         figure_name (string): Name of the plot (absolute path) being saved
            if not None.
         show_plot (bool): Whether to show the heatmap. Default is False.
         value_format (str): Formatting string to show values. If None, no value
            is shown. Example: "%.4f" shows float to four decimals.
         cmap (string): Color scheme of the heatmap. Default is 'coolwarm'.
         blank_color (string): Color assigned for the missing elements in
            elemental_data. Default is "grey".
         max_row (integer): Maximum number of rows of the periodic table to be
            shown. Default is 9, which means the periodic table heat map covers
            the first 9 rows of elements.
    """

    # Convert elemental data in the form of numpy array for plotting.
    max_val = max(elemental_data.values())
    min_val = min(elemental_data.values())
    max_row = min(max_row, 9)

    if max_row <= 0:
        raise ValueError("The input argument 'max_row' must be positive!")

    value_table = np.empty((max_row, 18)) * np.nan
    blank_value = min_val - 0.01

    for el in Element:
        if el.row > max_row: continue
        value = elemental_data.get(el.symbol, blank_value)
        value_table[el.row - 1, el.group - 1] = value

    # Initialize the plt object
    import matplotlib.pyplot as plt
    fig, ax = plt.subplots()
    plt.gcf().set_size_inches(12, 8)

    # We set nan type values to masked values (ie blank spaces)
    data_mask = np.ma.masked_invalid(value_table.tolist())
    heatmap = ax.pcolor(data_mask, cmap=cmap, edgecolors='w', linewidths=1,
                        vmin=min_val-0.001, vmax=max_val+0.001)
    cbar = fig.colorbar(heatmap)

    # Grey out missing elements in input data
    cbar.cmap.set_under(blank_color)
    cbar.set_label(cbar_label, rotation=270, labelpad=15)
    cbar.ax.tick_params(labelsize=14)

    # Refine and make the table look nice
    ax.axis('off')
    ax.invert_yaxis()

    # Label each block with corresponding element and value
    for i, row in enumerate(value_table):
        for j, el in enumerate(row):
            if not np.isnan(el):
                symbol = Element.from_row_and_group(i+1, j+1).symbol
                plt.text(j + 0.5, i + 0.25, symbol,
                         horizontalalignment='center',
                         verticalalignment='center', fontsize=14)
                if el != blank_value and value_format is not None:
                    plt.text(j + 0.5, i + 0.5, value_format % el,
                             horizontalalignment='center',
                             verticalalignment='center', fontsize=10)

    plt.tight_layout()

    if show_plot:
        plt.show()

    return plt
Пример #3
0
def periodic_table_heatmap(
    elemental_data,
    cbar_label="",
    cbar_label_size=14,
    show_plot=False,
    cmap="YlOrRd",
    cmap_range=None,
    blank_color="grey",
    edge_color="white",
    value_format=None,
    value_fontsize=10,
    symbol_fontsize=14,
    max_row=9,
    readable_fontcolor=False,
):
    """
    A static method that generates a heat map overlaid on a periodic table.

    Args:
         elemental_data (dict): A dictionary with the element as a key and a
            value assigned to it, e.g. surface energy and frequency, etc.
            Elements missing in the elemental_data will be grey by default
            in the final table elemental_data={"Fe": 4.2, "O": 5.0}.
         cbar_label (string): Label of the colorbar. Default is "".
         cbar_label_size (float): Font size for the colorbar label. Default is 14.
         cmap_range (tuple): Minimum and maximum value of the colormap scale.
            If None, the colormap will automatically scale to the range of the
            data.
         show_plot (bool): Whether to show the heatmap. Default is False.
         value_format (str): Formatting string to show values. If None, no value
            is shown. Example: "%.4f" shows float to four decimals.
         value_fontsize (float): Font size for values. Default is 10.
         symbol_fontsize (float): Font size for element symbols. Default is 14.
         cmap (string): Color scheme of the heatmap. Default is 'YlOrRd'.
            Refer to the matplotlib documentation for other options.
         blank_color (string): Color assigned for the missing elements in
            elemental_data. Default is "grey".
         edge_color (string): Color assigned for the edge of elements in the
            periodic table. Default is "white".
         max_row (integer): Maximum number of rows of the periodic table to be
            shown. Default is 9, which means the periodic table heat map covers
            the first 9 rows of elements.
         readable_fontcolor (bool): Whether to use readable fontcolor depending
            on background color. Default is False.
    """

    # Convert primitive_elemental data in the form of numpy array for plotting.
    if cmap_range is not None:
        max_val = cmap_range[1]
        min_val = cmap_range[0]
    else:
        max_val = max(elemental_data.values())
        min_val = min(elemental_data.values())

    max_row = min(max_row, 9)

    if max_row <= 0:
        raise ValueError("The input argument 'max_row' must be positive!")

    value_table = np.empty((max_row, 18)) * np.nan
    blank_value = min_val - 0.01

    for el in Element:
        if el.row > max_row:
            continue
        value = elemental_data.get(el.symbol, blank_value)
        value_table[el.row - 1, el.group - 1] = value

    # Initialize the plt object
    import matplotlib.pyplot as plt

    fig, ax = plt.subplots()
    plt.gcf().set_size_inches(12, 8)

    # We set nan type values to masked values (ie blank spaces)
    data_mask = np.ma.masked_invalid(value_table.tolist())
    heatmap = ax.pcolor(
        data_mask,
        cmap=cmap,
        edgecolors=edge_color,
        linewidths=1,
        vmin=min_val - 0.001,
        vmax=max_val + 0.001,
    )
    cbar = fig.colorbar(heatmap)

    # Grey out missing elements in input data
    cbar.cmap.set_under(blank_color)

    # Set the colorbar label and tick marks
    cbar.set_label(cbar_label, rotation=270, labelpad=25, size=cbar_label_size)
    cbar.ax.tick_params(labelsize=cbar_label_size)

    # Refine and make the table look nice
    ax.axis("off")
    ax.invert_yaxis()

    # Set the scalermap for fontcolor
    norm = colors.Normalize(vmin=min_val, vmax=max_val)
    scalar_cmap = cm.ScalarMappable(norm=norm, cmap=cmap)

    # Label each block with corresponding element and value
    for i, row in enumerate(value_table):
        for j, el in enumerate(row):
            if not np.isnan(el):
                symbol = Element.from_row_and_group(i + 1, j + 1).symbol
                rgba = scalar_cmap.to_rgba(el)
                fontcolor = _decide_fontcolor(
                    rgba) if readable_fontcolor else "black"
                plt.text(
                    j + 0.5,
                    i + 0.25,
                    symbol,
                    horizontalalignment="center",
                    verticalalignment="center",
                    fontsize=symbol_fontsize,
                    color=fontcolor,
                )
                if el != blank_value and value_format is not None:
                    plt.text(
                        j + 0.5,
                        i + 0.5,
                        value_format % el,
                        horizontalalignment="center",
                        verticalalignment="center",
                        fontsize=value_fontsize,
                        color=fontcolor,
                    )

    plt.tight_layout()

    if show_plot:
        plt.show()

    return plt