Source code for mendeleev.vis.utils
import pandas as pd
import matplotlib.pyplot as plt
import matplotlib.colors as colors
import matplotlib.cm as cmx
from mendeleev.fetch import fetch_table
[docs]
def add_tile_coordinates(
df: pd.DataFrame,
x_coord: str = "group_id",
y_coord: str = "period",
include_f_block: bool = True,
wide_layout: bool = False,
) -> pd.DataFrame:
"""
Calculate coordinates for the tile centers
Args:
df: dataframe
x_coord: attribute to use as x coordinate
y_coord: attribute to use as y coordinate
wide_layout : Show the long version of the periodic table with the f block between
the s and d blocks
include_f_block : Show the elements from the f block
"""
elements = df.copy().sort_values("atomic_number")
# calculate x and y coordinates of the main group/row elements
elements.loc[elements[x_coord].notnull(), "x"] = elements.loc[
elements[x_coord].notnull(), x_coord
].astype(int)
elements.loc[elements[y_coord].notnull(), "y"] = elements.loc[
elements[y_coord].notnull(), y_coord
].astype(int)
if include_f_block:
f_mask = elements["block"] == "f"
elements.loc[f_mask, "x"] = (
elements[f_mask]
.groupby("period")
.apply(lambda x: x["atomic_number"] - x["atomic_number"].min())
.to_numpy()
+ 3
)
if wide_layout:
mask = (
(elements["x"] > 2)
& (elements["block"] != "f")
& (~elements["symbol"].isin(["La", "Ac"]))
)
elements.loc[f_mask, "x"] += 1
elements.loc[mask, "x"] = elements.loc[mask, "x"] + 14
elements.loc[f_mask, "y"] = elements.loc[f_mask, "period"]
else:
elements.loc[f_mask, "y"] = elements.loc[f_mask, "period"] + 2.5
return elements
[docs]
def create_vis_dataframe(
x_coord: str = "group_id",
y_coord: str = "period",
include_f_block: bool = True,
wide_layout: bool = False,
):
"""
Base DataFrame for visualizations
Args:
x_coord: attribute to use as x coordinate
y_coord: attribute to use as y coordinate
include_f_block : show the elements from the f block
wide_layout : show the long version of the periodic table with the f block between
the s and d blocks
"""
elements = fetch_table("elements")
series = fetch_table("series")
df = pd.merge(
elements,
series,
left_on="series_id",
right_on="id",
suffixes=("", "_series"),
).sort_values(by="atomic_number")
return add_tile_coordinates(
df,
x_coord=x_coord,
y_coord=y_coord,
include_f_block=include_f_block,
wide_layout=wide_layout,
)
[docs]
def colormap_column(
elements: pd.DataFrame, column: str, cmap: str = "RdBu_r", missing: str = "#ffffff"
):
"""
Return a new DataFrame with the same size (and index) as `elements` with a column
`cmap` containing HEX color mapping from `cmap` colormap.
Args:
elements : DataFrame with the data
column : Name of the column to be color mapped
cmap : Name of the colormap, see matplotlib.org
missing : HEX color for the missing values (NaN or None)
"""
colormap = plt.get_cmap(cmap)
cnorm = colors.Normalize(vmin=elements[column].min(), vmax=elements[column].max())
scalarmap = cmx.ScalarMappable(norm=cnorm, cmap=colormap)
rgba = scalarmap.to_rgba(elements[column])
colored = pd.Series(
index=elements.index, data=[colors.rgb2hex(row) for row in rgba]
)
mask = elements[column].isnull()
colored.loc[mask] = missing
return colored