Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationEventAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
13
Help us understand the problem. What are the problem?

More than 1 year has passed since last update.

@M_Kumagai

JupyterLab上で周期表を用いた可視化、分析をする方法

 
 マテリアルズインフォマティクスを進めている中で、元素毎の特性を可視化して比較したくなりました。なので今回は、JupyterLab上で周期表を用いた傾向表示ができるサンプルコードを記しておきます。Pythonで周期表を描く場合、可視化ライブラリbokehを利用することになるかと思います。bokehで描かれる周期表は美しいので、論文や学会発表などにそのまま利用できそうです。

環境構築

jupyterlabのインストール

 まずはjupyterlabのインストールを行います。現在の最新のバージョンは0.35.3でした。もしすでにインストールしている際には、使用しているjupyterlabのバージョン情報を確認しておいてください。jupyterlabのバージョンは、メニューバーにあるhelpの「About JupyterLab Beta」から簡単に確認できます。

conda install -c conda-forge jupyterlab

bokeh拡張のインストール

 続いて、bokehをjupyterlab上で動作させるための拡張をインストールします。jupyterlabとのバージョンの整合性が取れていないと、インストールに失敗しますので、https://github.com/bokeh/jupyterlab_bokeh で確認して、インストールしてください。

jupyter labextension install jupyterlab_bokeh@0.6.3

実装

元素表の描画

 早速、以下に周期表による傾向表示をするサンプルコードを示します。bokehには元素表表示が用意されていますが、それを用いて元素の傾向まで表示するようにしたコード(https://github.com/arosen93/ptable_trends )を挙げている方がおられました。今回はそれを参考にして、jupyterLab上でも表示するように微修正しました。

from __future__ import absolute_import
from bokeh.models import (ColumnDataSource, LinearColorMapper, LogColorMapper, ColorBar, BasicTicker)
from bokeh.plotting import figure
from bokeh.io import output_file, show
from bokeh.sampledata.periodic_table import elements
from bokeh.transform import dodge
from matplotlib.colors import Normalize, LogNorm, to_hex
from matplotlib.cm import plasma, inferno, magma, viridis, ScalarMappable
from pandas import options
import bokeh.plotting as bp
import numpy as np
import math 
bp.output_notebook()
options.mode.chained_assignment = None

output_file('ptable_trends.html')

width = 1050
cmap_choice = 0
alpha = 0.65
log_scale = 0
cbar_height = 550
cbar_standoff =5
cbar_fontsize = 12

#描画したいトレンドデータ選択(列選択)
label = "electronegativity"

if cmap_choice == 0:
    cmap = plasma
    bokeh_palette = 'Plasma256'
elif cmap_choice == 1:
    cmap = inferno
    bokeh_palette = 'Inferno256'
elif cmap_choice == 2:
    cmap = magma
    bokeh_palette = 'Magma256'
elif cmap_choice == 3:
    cmap = viridis
    bokeh_palette = 'Viridis256'

#族および周期の定義
period_label = ['1', '2', '3', '4', '5', '6', '7']
group_range = [str(x) for x in range(1, 19)]

#データの取得
df = elements.copy()

data_elements = []
data = []
for idx, d in df.iterrows():
    if d[label] != "-" and not math.isnan(float(d[label])):
        data_elements.append(d["symbol"])
        data.append(float(d[label]))

period_label.append('blank')
period_label.append('La')
period_label.append('Ac')

count = 0
for i in range(56,71):
    df.period[i] = 'La'
    df.group[i] = str(count+4)
    count += 1

count = 0
for i in range(88,103):
    df.period[i] = 'Ac'
    df.group[i] = str(count+4)
    count += 1

#matplotlibとbokehのカラーマップの定義
if log_scale == 0:
    color_mapper = LinearColorMapper(palette = bokeh_palette, low=min(data), 
        high=max(data))
    norm = Normalize(vmin = min(data), vmax = max(data))
elif log_scale == 1:
    for datum in data:
        if datum < 0:
            raise ValueError('Entry for element '+datum+' is negative but log-scale is selected')
    color_mapper = LogColorMapper(palette = bokeh_palette, low=min(data), high=max(data))
    norm = LogNorm(vmin = min(data), vmax = max(data))
color_scale = ScalarMappable(norm=norm, cmap=cmap).to_rgba(data,alpha=None)

#空の場合のカラー定義
blank_color = '#c4c4c4'
color_list = []
for i in range(len(df)):
    color_list.append(blank_color)

#データが空でない場合の色設定
for i, data_element in enumerate(data_elements):
    element_entry = df.symbol[df.symbol.str.lower() == data_element.lower()]
    if element_entry.empty == False:
        element_index = element_entry.index[0]
    else:
        print('WARNING: Invalid chemical symbol: '+data_element)

    if color_list[element_index] != blank_color:
        print('WARNING: Multiple entries for element '+data_element)
    color_list[element_index] = to_hex(color_scale[i])

#データを可視化するための図の設定
source = ColumnDataSource(
    data=dict(
        group=[str(x) for x in df['group']],
        period=[str(y) for y in df['period']],
        sym=df['symbol'],
        atomic_number=df['atomic number'],
        name=df['name'],
        label=df[label],
        type_color=color_list
    )
)

#周期表の描画
p = figure(x_range=group_range, y_range=list(reversed(period_label)), tools='save')
p.plot_width = width
p.outline_line_color = None
p.toolbar_location='above'
p.rect('group', 'period', 0.9, 0.9, source=source,alpha=alpha, color='type_color')
p.axis.visible = False
text_props = {
    'source': source,
    'angle': 0,
    'color': 'black',
    'text_align': 'left',
    'text_baseline': 'middle'
}
x = dodge("group", -0.4, range=p.x_range)
p.text(x=x, y='period', text='sym',text_font_style='bold', text_font_size='16pt', **text_props)
p.text(x=x, y=dodge("period", 0.3, range=p.y_range), text='atomic_number',text_font_size='8pt', **text_props)
p.text(x=x, y=dodge("period", -0.35, range=p.y_range), text="name",text_font_size="5pt", **text_props)
p.text(x=x, y=dodge("period", -0.2, range=p.y_range), text="label",text_font_size="5pt", **text_props)
p.text(x=["3", "3"], y=["6", "7"], text=["57-71", "89-103"], text_align="center", text_baseline="middle")


color_bar = ColorBar(color_mapper=color_mapper,
    ticker=BasicTicker(desired_num_ticks=10),border_line_color=None,
    label_standoff=cbar_standoff,location=(0,0),orientation='vertical',
    scale_alpha=alpha,major_label_text_font_size=str(cbar_fontsize)+'pt')

if cbar_height is not None:
    color_bar.height = cbar_height

p.add_layout(color_bar,'right')
p.grid.grid_line_color = None
show(p)

以上のコードを実行した結果、以下のような図を得ることができます。
bokeh_plot (2).png

 今回は、"電気陰性度(electronegativity)"の描画を例に挙げましたが、bokehが標準で提供しているelementsには以下のような情報(数字のカラムのみ表示しています)が提供されているので、他の情報で描画することも可能です。表示を変える場合は、上記コードにおける変数labelの値を変更してください。また、すでにある情報から計算して新しいカラムを作ったり、pymatgenのAPIを利用してさらに高度な情報を得るなどをすることで、詳細な傾向分析も可能です。

atomic number atomic mass electronegativity atomic radius van der Waals radius IE-1 EA melting point boiling point density year discovered group period
1 1.00794 2.20 37.0 120.0 1312.0 -73.0 14.0 20.0 0.00009 1766 1 1
2 4.002602 NaN 32.0 140.0 2372.0 0.0 NaN 4.0 0.00000 1868 18 1
3 6.941 0.98 134.0 182.0 520.0 -60.0 454.0 1615.0 0.54000 1817 1 2
4 9.012182 1.57 90.0 NaN 900.0 0.0 1560.0 2743.0 1.85000 1798 2 2
5 10.811 2.04 82.0 NaN 801.0 -27.0 2348.0 4273.0 2.46000 1807 13 2

※本ドキュメントのコードは、arosen93さんのコードを微修正して、JupyterLab上で実装したものです。

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
13
Help us understand the problem. What are the problem?