first commit
This commit is contained in:
+15
@@ -0,0 +1,15 @@
|
||||
# white listで管理するため、一旦、全てを無視
|
||||
*
|
||||
!*/
|
||||
|
||||
# white listの定義
|
||||
!.git/*
|
||||
!.gitignore
|
||||
!Readme.html
|
||||
!Readme.org
|
||||
!xls2ternary.py
|
||||
!test.xlsx
|
||||
!a.png
|
||||
!b.png
|
||||
|
||||
|
||||
+475
@@ -0,0 +1,475 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
|
||||
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
||||
<html xmlns="http://www.w3.org/1999/xhtml" lang="ja" xml:lang="ja">
|
||||
<head>
|
||||
<!-- 2024-09-20 金 17:05 -->
|
||||
<meta http-equiv="Content-Type" content="text/html;charset=utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
<title>xls2ternary.py</title>
|
||||
<meta name="author" content="大窪 貴洋 (千葉大院工) ohkubo.takahiro@faculty.chiba-u.jp" />
|
||||
<meta name="generator" content="Org Mode" />
|
||||
<style>
|
||||
#content { max-width: 60em; margin: auto; }
|
||||
.title { text-align: center;
|
||||
margin-bottom: .2em; }
|
||||
.subtitle { text-align: center;
|
||||
font-size: medium;
|
||||
font-weight: bold;
|
||||
margin-top:0; }
|
||||
.todo { font-family: monospace; color: red; }
|
||||
.done { font-family: monospace; color: green; }
|
||||
.priority { font-family: monospace; color: orange; }
|
||||
.tag { background-color: #eee; font-family: monospace;
|
||||
padding: 2px; font-size: 80%; font-weight: normal; }
|
||||
.timestamp { color: #bebebe; }
|
||||
.timestamp-kwd { color: #5f9ea0; }
|
||||
.org-right { margin-left: auto; margin-right: 0px; text-align: right; }
|
||||
.org-left { margin-left: 0px; margin-right: auto; text-align: left; }
|
||||
.org-center { margin-left: auto; margin-right: auto; text-align: center; }
|
||||
.underline { text-decoration: underline; }
|
||||
#postamble p, #preamble p { font-size: 90%; margin: .2em; }
|
||||
p.verse { margin-left: 3%; }
|
||||
pre {
|
||||
border: 1px solid #e6e6e6;
|
||||
border-radius: 3px;
|
||||
background-color: #f2f2f2;
|
||||
padding: 8pt;
|
||||
font-family: monospace;
|
||||
overflow: auto;
|
||||
margin: 1.2em;
|
||||
}
|
||||
pre.src {
|
||||
position: relative;
|
||||
overflow: auto;
|
||||
}
|
||||
pre.src:before {
|
||||
display: none;
|
||||
position: absolute;
|
||||
top: -8px;
|
||||
right: 12px;
|
||||
padding: 3px;
|
||||
color: #555;
|
||||
background-color: #f2f2f299;
|
||||
}
|
||||
pre.src:hover:before { display: inline; margin-top: 14px;}
|
||||
/* Languages per Org manual */
|
||||
pre.src-asymptote:before { content: 'Asymptote'; }
|
||||
pre.src-awk:before { content: 'Awk'; }
|
||||
pre.src-authinfo::before { content: 'Authinfo'; }
|
||||
pre.src-C:before { content: 'C'; }
|
||||
/* pre.src-C++ doesn't work in CSS */
|
||||
pre.src-clojure:before { content: 'Clojure'; }
|
||||
pre.src-css:before { content: 'CSS'; }
|
||||
pre.src-D:before { content: 'D'; }
|
||||
pre.src-ditaa:before { content: 'ditaa'; }
|
||||
pre.src-dot:before { content: 'Graphviz'; }
|
||||
pre.src-calc:before { content: 'Emacs Calc'; }
|
||||
pre.src-emacs-lisp:before { content: 'Emacs Lisp'; }
|
||||
pre.src-fortran:before { content: 'Fortran'; }
|
||||
pre.src-gnuplot:before { content: 'gnuplot'; }
|
||||
pre.src-haskell:before { content: 'Haskell'; }
|
||||
pre.src-hledger:before { content: 'hledger'; }
|
||||
pre.src-java:before { content: 'Java'; }
|
||||
pre.src-js:before { content: 'Javascript'; }
|
||||
pre.src-latex:before { content: 'LaTeX'; }
|
||||
pre.src-ledger:before { content: 'Ledger'; }
|
||||
pre.src-lisp:before { content: 'Lisp'; }
|
||||
pre.src-lilypond:before { content: 'Lilypond'; }
|
||||
pre.src-lua:before { content: 'Lua'; }
|
||||
pre.src-matlab:before { content: 'MATLAB'; }
|
||||
pre.src-mscgen:before { content: 'Mscgen'; }
|
||||
pre.src-ocaml:before { content: 'Objective Caml'; }
|
||||
pre.src-octave:before { content: 'Octave'; }
|
||||
pre.src-org:before { content: 'Org mode'; }
|
||||
pre.src-oz:before { content: 'OZ'; }
|
||||
pre.src-plantuml:before { content: 'Plantuml'; }
|
||||
pre.src-processing:before { content: 'Processing.js'; }
|
||||
pre.src-python:before { content: 'Python'; }
|
||||
pre.src-R:before { content: 'R'; }
|
||||
pre.src-ruby:before { content: 'Ruby'; }
|
||||
pre.src-sass:before { content: 'Sass'; }
|
||||
pre.src-scheme:before { content: 'Scheme'; }
|
||||
pre.src-screen:before { content: 'Gnu Screen'; }
|
||||
pre.src-sed:before { content: 'Sed'; }
|
||||
pre.src-sh:before { content: 'shell'; }
|
||||
pre.src-sql:before { content: 'SQL'; }
|
||||
pre.src-sqlite:before { content: 'SQLite'; }
|
||||
/* additional languages in org.el's org-babel-load-languages alist */
|
||||
pre.src-forth:before { content: 'Forth'; }
|
||||
pre.src-io:before { content: 'IO'; }
|
||||
pre.src-J:before { content: 'J'; }
|
||||
pre.src-makefile:before { content: 'Makefile'; }
|
||||
pre.src-maxima:before { content: 'Maxima'; }
|
||||
pre.src-perl:before { content: 'Perl'; }
|
||||
pre.src-picolisp:before { content: 'Pico Lisp'; }
|
||||
pre.src-scala:before { content: 'Scala'; }
|
||||
pre.src-shell:before { content: 'Shell Script'; }
|
||||
pre.src-ebnf2ps:before { content: 'ebfn2ps'; }
|
||||
/* additional language identifiers per "defun org-babel-execute"
|
||||
in ob-*.el */
|
||||
pre.src-cpp:before { content: 'C++'; }
|
||||
pre.src-abc:before { content: 'ABC'; }
|
||||
pre.src-coq:before { content: 'Coq'; }
|
||||
pre.src-groovy:before { content: 'Groovy'; }
|
||||
/* additional language identifiers from org-babel-shell-names in
|
||||
ob-shell.el: ob-shell is the only babel language using a lambda to put
|
||||
the execution function name together. */
|
||||
pre.src-bash:before { content: 'bash'; }
|
||||
pre.src-csh:before { content: 'csh'; }
|
||||
pre.src-ash:before { content: 'ash'; }
|
||||
pre.src-dash:before { content: 'dash'; }
|
||||
pre.src-ksh:before { content: 'ksh'; }
|
||||
pre.src-mksh:before { content: 'mksh'; }
|
||||
pre.src-posh:before { content: 'posh'; }
|
||||
/* Additional Emacs modes also supported by the LaTeX listings package */
|
||||
pre.src-ada:before { content: 'Ada'; }
|
||||
pre.src-asm:before { content: 'Assembler'; }
|
||||
pre.src-caml:before { content: 'Caml'; }
|
||||
pre.src-delphi:before { content: 'Delphi'; }
|
||||
pre.src-html:before { content: 'HTML'; }
|
||||
pre.src-idl:before { content: 'IDL'; }
|
||||
pre.src-mercury:before { content: 'Mercury'; }
|
||||
pre.src-metapost:before { content: 'MetaPost'; }
|
||||
pre.src-modula-2:before { content: 'Modula-2'; }
|
||||
pre.src-pascal:before { content: 'Pascal'; }
|
||||
pre.src-ps:before { content: 'PostScript'; }
|
||||
pre.src-prolog:before { content: 'Prolog'; }
|
||||
pre.src-simula:before { content: 'Simula'; }
|
||||
pre.src-tcl:before { content: 'tcl'; }
|
||||
pre.src-tex:before { content: 'TeX'; }
|
||||
pre.src-plain-tex:before { content: 'Plain TeX'; }
|
||||
pre.src-verilog:before { content: 'Verilog'; }
|
||||
pre.src-vhdl:before { content: 'VHDL'; }
|
||||
pre.src-xml:before { content: 'XML'; }
|
||||
pre.src-nxml:before { content: 'XML'; }
|
||||
/* add a generic configuration mode; LaTeX export needs an additional
|
||||
(add-to-list 'org-latex-listings-langs '(conf " ")) in .emacs */
|
||||
pre.src-conf:before { content: 'Configuration File'; }
|
||||
|
||||
table { border-collapse:collapse; }
|
||||
caption.t-above { caption-side: top; }
|
||||
caption.t-bottom { caption-side: bottom; }
|
||||
td, th { vertical-align:top; }
|
||||
th.org-right { text-align: center; }
|
||||
th.org-left { text-align: center; }
|
||||
th.org-center { text-align: center; }
|
||||
td.org-right { text-align: right; }
|
||||
td.org-left { text-align: left; }
|
||||
td.org-center { text-align: center; }
|
||||
dt { font-weight: bold; }
|
||||
.footpara { display: inline; }
|
||||
.footdef { margin-bottom: 1em; }
|
||||
.figure { padding: 1em; }
|
||||
.figure p { text-align: center; }
|
||||
.equation-container {
|
||||
display: table;
|
||||
text-align: center;
|
||||
width: 100%;
|
||||
}
|
||||
.equation {
|
||||
vertical-align: middle;
|
||||
}
|
||||
.equation-label {
|
||||
display: table-cell;
|
||||
text-align: right;
|
||||
vertical-align: middle;
|
||||
}
|
||||
.inlinetask {
|
||||
padding: 10px;
|
||||
border: 2px solid gray;
|
||||
margin: 10px;
|
||||
background: #ffffcc;
|
||||
}
|
||||
#org-div-home-and-up
|
||||
{ text-align: right; font-size: 70%; white-space: nowrap; }
|
||||
textarea { overflow-x: auto; }
|
||||
.linenr { font-size: smaller }
|
||||
.code-highlighted { background-color: #ffff00; }
|
||||
.org-info-js_info-navigation { border-style: none; }
|
||||
#org-info-js_console-label
|
||||
{ font-size: 10px; font-weight: bold; white-space: nowrap; }
|
||||
.org-info-js_search-highlight
|
||||
{ background-color: #ffff00; color: #000000; font-weight: bold; }
|
||||
.org-svg { }
|
||||
</style>
|
||||
<link rel="stylesheet" type="text/css" href="https://amorphous.tf.chiba-u.jp/org-html-themes/org/lib/css/htmlize.css"/>
|
||||
<link rel="stylesheet" type="text/css" href="https://amorphous.tf.chiba-u.jp/org-html-themes/org/lib/readtheorg.css"/>
|
||||
<script src="https://amorphous.tf.chiba-u.jp/org-html-themes/org/lib/jquery.min.js"></script>
|
||||
<script src="https://amorphous.tf.chiba-u.jp/org-html-themes/org/lib/bootstrap.min.js"></script>
|
||||
<script type="text/javascript" src="https://amorphous.tf.chiba-u.jp/org-html-themes/org/lib/jquery.stickytableheaders.min.js"></script>
|
||||
<script type="text/javascript" src="https://amorphous.tf.chiba-u.jp/org-html-themes/org/lib/readtheorg.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<div id="content" class="content">
|
||||
<h1 class="title">xls2ternary.py</h1>
|
||||
<div id="table-of-contents" role="doc-toc">
|
||||
<h2>目次</h2>
|
||||
<div id="text-table-of-contents" role="doc-toc">
|
||||
<ul>
|
||||
<li><a href="#orga326fcb">更新履歴</a></li>
|
||||
<li><a href="#org09fdea8">はじめに</a></li>
|
||||
<li><a href="#orgb57ed52">プログラムのインストール</a></li>
|
||||
<li><a href="#org870c794">プログラムの実行</a></li>
|
||||
<li><a href="#org21f93b4">座標ピックアップ</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div id="outline-container-orga326fcb" class="outline-2">
|
||||
<h2 id="orga326fcb">更新履歴</h2>
|
||||
<div class="outline-text-2" id="text-orga326fcb">
|
||||
<ul class="org-ul">
|
||||
<li>pandasを使うようにした。<span class="timestamp-wrapper"><span class="timestamp"><2024-09-20 金></span></span></li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="outline-container-org09fdea8" class="outline-2">
|
||||
<h2 id="org09fdea8">はじめに</h2>
|
||||
<div class="outline-text-2" id="text-org09fdea8">
|
||||
<p>
|
||||
Excelファイルから三成分系の相図をプロットするプログラムです。3成分系でガラス化範囲をプロットするために作成しました。いくつか3元プロットのライブラリが公開(<a href="https://github.com/marcharper/python-ternary">python-ternary</a> や<a href="http://home.gna.org/veusz/examples/#ternary"> Veusz</a> )されているようですが、どれもイマイチ融通が効かないため、結局自作しました。
|
||||
</p>
|
||||
|
||||
<p>
|
||||
3成分の組成とガラス化の有無(0から1で判定)のデータから、相図を作成しコンタープロットを描きます。excelでファイルを作成し、引数でプログラムに渡します。3組成のそれぞれの成分名は、ファイル中のヘッダで指定します。入力するexcelファイルは、(<a href="test.xlsx">test.xlsx</a>)を参考にしてください。3行目がヘッダデータ、3組成の成分比とガラス化の有無G/C(0から1の範囲)を列としたデータを作成します。
|
||||
</p>
|
||||
|
||||
<p>
|
||||
成分名については、latex形式で上付き下付きも指定できます。以下はB<sub>2</sub>O<sub>3</sub>の例です。
|
||||
</p>
|
||||
<pre class="example" id="orge1815a7">
|
||||
${\rm B_{2}O_{3}}$
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
※G/Cの列が空欄の場合、データはスキップされプロットされません。
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="outline-container-orgb57ed52" class="outline-2">
|
||||
<h2 id="orgb57ed52">プログラムのインストール</h2>
|
||||
<div class="outline-text-2" id="text-orgb57ed52">
|
||||
<p>
|
||||
プログラムはpython3.xで作成しているのでpython3.xを実行できる環境が必要です。matplotlibは2.0.2です。プログラム本体は<a href="xls2ternary.py">xls2ternary.py</a>です。
|
||||
python3.xを<a href="https://docs.anaconda.com/miniconda/">miniconda</a>を使ってインストールしてください。numpy, matplotlib, pandasに加えてExcelファイルを読み込むためのopenpyxlが必要です。minicondaのインストールが完了したら以下のコマンドで必要なライブラリをインストールしてください。
|
||||
</p>
|
||||
<pre class="example" id="org371003c">
|
||||
conda install numpy matplotlib pandas openpyxl
|
||||
</pre>
|
||||
<p>
|
||||
後は、パスの通ったところに <a href="xls2ternary.py">xls2ternary.py</a> を配置すればインストールは完了です。
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="outline-container-org870c794" class="outline-2">
|
||||
<h2 id="org870c794">プログラムの実行</h2>
|
||||
<div class="outline-text-2" id="text-org870c794">
|
||||
<p>
|
||||
引数でexcelファイルを指定して実行します。テストデータ(<a href="test.xlsx">test.xlsx</a>)を試しにプロットしてみます。
|
||||
</p>
|
||||
<pre class="example" id="orgc6aa5f3">
|
||||
xls2ternary.py test.xlsx
|
||||
</pre>
|
||||
<p>
|
||||
次のような内容がターミナルに表示され、mol%で表示された図が得られれば正しくプログラムは動いています。
|
||||
</p>
|
||||
<pre class="example" id="org6613c16">
|
||||
Number of data : 59
|
||||
Plot header [row]: ['A' 'B' 'C'] [1, 2, 3]
|
||||
G/C data [row]: G/C [4]
|
||||
</pre>
|
||||
|
||||
|
||||
<div id="org9ef9659" class="figure">
|
||||
<p><a href="a.png" width="440px" alt="figure" title="titiel mame" align="center"><img src="a.png" alt="figure" width="440px" title="titiel mame" align="center" /></a>
|
||||
</p>
|
||||
<p><span class="figure-number">図1: </span>出力される図</p>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
<p>
|
||||
1列目のデータ範囲の最小値を指定できます。1列目のデータを70-100%にする場合です。また、コンタープロットの補完をlinearにしてラベルをwt%にしてみます。
|
||||
</p>
|
||||
<pre class="example" id="orgdbb2e05">
|
||||
xls2ternary.py -xmin 70 --interp linear -xl wt% test.xlsx
|
||||
</pre>
|
||||
|
||||
|
||||
<div id="org6127e2f" class="figure">
|
||||
<p><a href="b.png" width="450px" alt="figure" title="titiel mame" align="center"><img src="b.png" alt="figure" width="450px" title="titiel mame" align="center" /></a>
|
||||
</p>
|
||||
<p><span class="figure-number">図2: </span>1列目のデータを70から100%に拡大した図</p>
|
||||
</div>
|
||||
|
||||
<p>
|
||||
図をファイルとして保存したい場合は、画面のメニューから選んでも良いですが、-oで保存もできます。またexcelファイル中のヘッダーの行番号やデータの列番号をオプションで指定できます。
|
||||
-hで指定できるオプション一覧が表示されます。以下、オプションについてもう少し説明します。
|
||||
</p>
|
||||
|
||||
<table border="2" cellspacing="0" cellpadding="6" rules="groups" frame="hsides">
|
||||
|
||||
|
||||
<colgroup>
|
||||
<col class="org-left" />
|
||||
|
||||
<col class="org-left" />
|
||||
|
||||
<col class="org-right" />
|
||||
</colgroup>
|
||||
<thead>
|
||||
<tr>
|
||||
<th scope="col" class="org-left">オプション</th>
|
||||
<th scope="col" class="org-left">内容</th>
|
||||
<th scope="col" class="org-right">default</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td class="org-left">-h</td>
|
||||
<td class="org-left">ヘルプを表します。</td>
|
||||
<td class="org-right"> </td>
|
||||
</tr>
|
||||
</tbody>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td class="org-left">-si</td>
|
||||
<td class="org-left">xlsファイル中のシート番号(0からはじまる)を指定します。</td>
|
||||
<td class="org-right">0</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td class="org-left">-hl</td>
|
||||
<td class="org-left">xlsファイル中のヘッダが入っている行番号を指定します。</td>
|
||||
<td class="org-right">3</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td class="org-left">-m</td>
|
||||
<td class="org-left">組成データを含む3つの列番号を指定します。</td>
|
||||
<td class="org-right">1 2 3</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td class="org-left">-p</td>
|
||||
<td class="org-left">ガラス率(0から1の範囲)のデータを含む列を指定します。</td>
|
||||
<td class="org-right">4</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td class="org-left">-xmin</td>
|
||||
<td class="org-left">1列目のデータをxminから100の範囲に変更します。</td>
|
||||
<td class="org-right">0</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td class="org-left">-o</td>
|
||||
<td class="org-left">図を保存するファイル名前指定します。拡張子(pdfやpng等)で保存形式を自動判別します。</td>
|
||||
<td class="org-right">None</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td class="org-left">-xl</td>
|
||||
<td class="org-left">図の下のラベルを指定します。</td>
|
||||
<td class="org-right">mol%</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td class="org-left">-g</td>
|
||||
<td class="org-left">コンタープロットのために内挿するグリッドの数です。</td>
|
||||
<td class="org-right">400</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td class="org-left">-fs</td>
|
||||
<td class="org-left">保存する図の大きさです。</td>
|
||||
<td class="org-right">8</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td class="org-left">-ls</td>
|
||||
<td class="org-left">頂点のラベルのフォントの大きさです。</td>
|
||||
<td class="org-right">16</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td class="org-left">-ts</td>
|
||||
<td class="org-left">目盛の数字のフォントの大きさです。</td>
|
||||
<td class="org-right">12</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td class="org-left">–labeloffset</td>
|
||||
<td class="org-left">頂点のラベルの位置のオフセット位置です。</td>
|
||||
<td class="org-right">2</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td class="org-left">–tickoffset</td>
|
||||
<td class="org-left">目盛の数字の位置のオフセット位置です。</td>
|
||||
<td class="org-right">1</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td class="org-left">–colormap</td>
|
||||
<td class="org-left">コンタープロットのカラーマップです。<a href="https://matplotlib.org/examples/color/colormaps_reference.html">ここ</a> から好きなものを選べます。</td>
|
||||
<td class="org-right">bwr</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td class="org-left">–interp</td>
|
||||
<td class="org-left">コンタープロットする時の補完の方法です。[linear, cubic, nearest]から<a href="https://docs.scipy.org/doc/scipy-0.18.1/reference/generated/scipy.interpolate.griddata.html">選択</a> 。</td>
|
||||
<td class="org-right">linear</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td class="org-left">–nolegend</td>
|
||||
<td class="org-left">凡例を表示しません。</td>
|
||||
<td class="org-right"> </td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td class="org-left">–nocontour</td>
|
||||
<td class="org-left">コンタープロットを表示しません。</td>
|
||||
<td class="org-right"> </td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td class="org-left">–nocolorbar</td>
|
||||
<td class="org-left">カラーバーを表示しません。</td>
|
||||
<td class="org-right"> </td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div id="outline-container-org21f93b4" class="outline-2">
|
||||
<h2 id="org21f93b4">座標ピックアップ</h2>
|
||||
<div class="outline-text-2" id="text-org21f93b4">
|
||||
<p>
|
||||
表示された図中でマウスのボタン(左、中、右どれでも)をクリックすれば、3
|
||||
成分の割合が以下のようにターミナルに表示されます。
|
||||
</p>
|
||||
<pre class="example" id="orgcdc33f5">
|
||||
button=1 ['B' 'C' 'A']=(24.52 51.03 24.45)
|
||||
button=1 ['B' 'C' 'A']=(24.49 44.60 30.91)
|
||||
button=1 ['B' 'C' 'A']=(45.65 26.83 27.53)
|
||||
</pre>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="postamble" class="status">
|
||||
<p class="author">著者: 大窪 貴洋 (千葉大院工) ohkubo.takahiro@faculty.chiba-u.jp</p>
|
||||
<p class="date">Created: 2024-09-20 金 17:05</p>
|
||||
<p class="validation"><a href="https://validator.w3.org/check?uri=referer">Validate</a></p>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
+100
@@ -0,0 +1,100 @@
|
||||
#+TITLE: xls2ternary.py
|
||||
#+AUTHOR: 大窪 貴洋 (千葉大院工) ohkubo.takahiro@faculty.chiba-u.jp
|
||||
#+LANGUAGE: ja
|
||||
#+EMAIL: ohkubo.takahiro@faculty.chiba-u.jp
|
||||
#+OPTIONS: toc:2 num:nil author:t creator:nil LaTeX:nil \n:nil ^:{}
|
||||
#+SETUPFILE: https://amorphous.tf.chiba-u.jp/org-html-themes/org/theme-readtheorg.setup
|
||||
#+MACRO: color @@html:<font color="$1">$2</font>@@
|
||||
#+MACRO: kakomi @@html:<div style="margin: 1em auto; padding: 1em; width: 100%; border: 2px dotted #ff0000;background-color: #ff;border-radius: 1px">$1</div>@@
|
||||
|
||||
|
||||
* 更新履歴
|
||||
- pandasを使うようにした。<2024-09-20 金>
|
||||
|
||||
* はじめに
|
||||
Excelファイルから三成分系の相図をプロットするプログラムです。3成分系でガラス化範囲をプロットするために作成しました。いくつか3元プロットのライブラリが公開([[https://github.com/marcharper/python-ternary][python-ternary]] や[[http://home.gna.org/veusz/examples/#ternary][ Veusz]] )されているようですが、どれもイマイチ融通が効かないため、結局自作しました。
|
||||
|
||||
3成分の組成とガラス化の有無(0から1で判定)のデータから、相図を作成しコンタープロットを描きます。excelでファイルを作成し、引数でプログラムに渡します。3組成のそれぞれの成分名は、ファイル中のヘッダで指定します。入力するexcelファイルは、([[file:test.xlsx][test.xlsx]])を参考にしてください。3行目がヘッダデータ、3組成の成分比とガラス化の有無G/C(0から1の範囲)を列としたデータを作成します。
|
||||
|
||||
成分名については、latex形式で上付き下付きも指定できます。以下はB_{2}O_{3}の例です。
|
||||
#+BEGIN_EXAMPLE
|
||||
${\rm B_{2}O_{3}}$
|
||||
#+END_EXAMPLE
|
||||
|
||||
※G/Cの列が空欄の場合、データはスキップされプロットされません。
|
||||
|
||||
* プログラムのインストール
|
||||
プログラムはpython3.xで作成しているのでpython3.xを実行できる環境が必要です。matplotlibは2.0.2です。プログラム本体は[[file:xls2ternary.py][xls2ternary.py]]です。
|
||||
python3.xを[[https://docs.anaconda.com/miniconda/][miniconda]]を使ってインストールしてください。numpy, matplotlib, pandasに加えてExcelファイルを読み込むためのopenpyxlが必要です。minicondaのインストールが完了したら以下のコマンドで必要なライブラリをインストールしてください。
|
||||
#+BEGIN_EXAMPLE
|
||||
conda install numpy matplotlib pandas openpyxl
|
||||
#+END_EXAMPLE
|
||||
後は、パスの通ったところに [[file:xls2ternary.py][xls2ternary.py]] を配置すればインストールは完了です。
|
||||
|
||||
* プログラムの実行
|
||||
引数でexcelファイルを指定して実行します。テストデータ([[file:test.xlsx][test.xlsx]])を試しにプロットしてみます。
|
||||
#+BEGIN_EXAMPLE
|
||||
xls2ternary.py test.xlsx
|
||||
#+END_EXAMPLE
|
||||
次のような内容がターミナルに表示され、mol%で表示された図が得られれば正しくプログラムは動いています。
|
||||
#+BEGIN_EXAMPLE
|
||||
Number of data : 59
|
||||
Plot header [row]: ['A' 'B' 'C'] [1, 2, 3]
|
||||
G/C data [row]: G/C [4]
|
||||
#+END_EXAMPLE
|
||||
|
||||
#+CAPTION: 出力される図
|
||||
#+ATTR_HTML: :alt figure :title titiel mame :align center
|
||||
#+ATTR_HTML: :width 440px
|
||||
[[file:a.png][file:a.png]]
|
||||
|
||||
|
||||
|
||||
1列目のデータ範囲の最小値を指定できます。1列目のデータを70-100%にする場合です。また、コンタープロットの補完をlinearにしてラベルをwt%にしてみます。
|
||||
#+BEGIN_EXAMPLE
|
||||
xls2ternary.py -xmin 70 --interp linear -xl wt% test.xlsx
|
||||
#+END_EXAMPLE
|
||||
|
||||
#+CAPTION: 1列目のデータを70から100%に拡大した図
|
||||
#+ATTR_HTML: :alt figure :title titiel mame :align center
|
||||
#+ATTR_HTML: :width 450px
|
||||
[[file:b.png][file:b.png]]
|
||||
|
||||
図をファイルとして保存したい場合は、画面のメニューから選んでも良いですが、-oで保存もできます。またexcelファイル中のヘッダーの行番号やデータの列番号をオプションで指定できます。
|
||||
-hで指定できるオプション一覧が表示されます。以下、オプションについてもう少し説明します。
|
||||
|
||||
|---------------+------------------------------------------------------------------------------------+---------|
|
||||
| オプション | 内容 | default |
|
||||
|---------------+------------------------------------------------------------------------------------+---------|
|
||||
| -h | ヘルプを表します。 | |
|
||||
|---------------+------------------------------------------------------------------------------------+---------|
|
||||
| -si | xlsファイル中のシート番号(0からはじまる)を指定します。 | 0 |
|
||||
| -hl | xlsファイル中のヘッダが入っている行番号を指定します。 | 3 |
|
||||
| -m | 組成データを含む3つの列番号を指定します。 | 1 2 3 |
|
||||
| -p | ガラス率(0から1の範囲)のデータを含む列を指定します。 | 4 |
|
||||
| -xmin | 1列目のデータをxminから100の範囲に変更します。 | 0 |
|
||||
|---------------+------------------------------------------------------------------------------------+---------|
|
||||
| -o | 図を保存するファイル名前指定します。拡張子(pdfやpng等)で保存形式を自動判別します。 | None |
|
||||
| -xl | 図の下のラベルを指定します。 | mol% |
|
||||
| -g | コンタープロットのために内挿するグリッドの数です。 | 400 |
|
||||
| -fs | 保存する図の大きさです。 | 8 |
|
||||
| -ls | 頂点のラベルのフォントの大きさです。 | 16 |
|
||||
| -ts | 目盛の数字のフォントの大きさです。 | 12 |
|
||||
| --labeloffset | 頂点のラベルの位置のオフセット位置です。 | 2 |
|
||||
| --tickoffset | 目盛の数字の位置のオフセット位置です。 | 1 |
|
||||
| --colormap | コンタープロットのカラーマップです。[[https://matplotlib.org/examples/color/colormaps_reference.html][ここ]] から好きなものを選べます。 | bwr |
|
||||
| --interp | コンタープロットする時の補完の方法です。[linear, cubic, nearest]から[[https://docs.scipy.org/doc/scipy-0.18.1/reference/generated/scipy.interpolate.griddata.html][選択]] 。 | linear |
|
||||
| --nolegend | 凡例を表示しません。 | |
|
||||
| --nocontour | コンタープロットを表示しません。 | |
|
||||
| --nocolorbar | カラーバーを表示しません。 | |
|
||||
|---------------+------------------------------------------------------------------------------------+---------|
|
||||
|
||||
|
||||
* 座標ピックアップ
|
||||
表示された図中でマウスのボタン(左、中、右どれでも)をクリックすれば、3
|
||||
成分の割合が以下のようにターミナルに表示されます。
|
||||
#+BEGIN_EXAMPLE
|
||||
button=1 ['B' 'C' 'A']=(24.52 51.03 24.45)
|
||||
button=1 ['B' 'C' 'A']=(24.49 44.60 30.91)
|
||||
button=1 ['B' 'C' 'A']=(45.65 26.83 27.53)
|
||||
#+END_EXAMPLE
|
||||
Executable
+239
@@ -0,0 +1,239 @@
|
||||
#!/usr/bin/env python
|
||||
import argparse
|
||||
import os
|
||||
import pandas as pd
|
||||
import numpy as np
|
||||
import matplotlib as mpl
|
||||
import matplotlib.pyplot as plt
|
||||
from scipy.interpolate import griddata
|
||||
|
||||
plt.style.use('classic')
|
||||
plt.rcParams.update({'legend.fancybox': True, 'legend.labelspacing': 0.25,
|
||||
'legend.fontsize': 14, 'legend.scatterpoints': 1,
|
||||
'font.size': 10, 'font.family': 'sans-serif',
|
||||
'savefig.transparent': True, 'savefig.dpi': 300,
|
||||
'savefig.bbox': 'tight',
|
||||
'xtick.direction': 'in',
|
||||
'figure.dpi': 80,
|
||||
'axes.grid': True,
|
||||
'axes.xmargin': 0, 'axes.labelsize': 16,
|
||||
'xtick.major.size': 5, 'xtick.minor.size': 3,
|
||||
'ps.useafm': True,
|
||||
'pdf.use14corefonts': True})
|
||||
|
||||
|
||||
description = """describe"""
|
||||
par = argparse.ArgumentParser(description=description)
|
||||
par.add_argument('xlsfile', help="input excel file")
|
||||
par.add_argument('-si', '--sheet_index', default=0, type=int,
|
||||
help="sheet index in excel file [0]")
|
||||
par.add_argument('-hl', '--header', default=0, type=int,
|
||||
help="header line number in excel file[0]")
|
||||
par.add_argument('-m', '--mol_col', nargs=3, default=[0, 1, 2], type=int,
|
||||
help="row number for mol percent [0 1 2]")
|
||||
par.add_argument('-p', '--GC_col', default=3, type=int,
|
||||
help="row number for G/C ratio [3]")
|
||||
par.add_argument('-xmin', '--xmin', default=0, type=float,
|
||||
help="x minimum [0]")
|
||||
par.add_argument('-o', '--outfile', default=None,
|
||||
help="output file[None]")
|
||||
par.add_argument('-xl', '--xlabel', default="mol%",
|
||||
help='xlabel [mol%%]')
|
||||
par.add_argument('-g', '--grid', default=400, type=int,
|
||||
help="grid size [400]")
|
||||
par.add_argument('-fs', '--figsize', default=8, type=int,
|
||||
help="figure size [8]")
|
||||
par.add_argument('-ls', '--labelsize', default=16, type=float,
|
||||
help="label font size [16]")
|
||||
par.add_argument('-ts', '--ticksize', default=10, type=float,
|
||||
help="ticks font size [10]")
|
||||
par.add_argument('--labeloffset', default=6,
|
||||
help="lebel offset [6]")
|
||||
par.add_argument('--ticksoffset', default=4,
|
||||
help="ticks offset [1]")
|
||||
par.add_argument('--colormap', default='bwr',
|
||||
help="colour color map [bwr]")
|
||||
par.add_argument('--interp', default="linear",
|
||||
choices=['linear', 'nearest', 'cubic'], help="[linear]")
|
||||
par.add_argument('--nolegend', default=False,
|
||||
action='store_true', help='not show legend [False]')
|
||||
par.add_argument('--nocontour', default=False,
|
||||
action='store_true', help='not contour plot [False]')
|
||||
par.add_argument('--nocolorbar', default=False,
|
||||
action='store_true', help='not colorbar [False]')
|
||||
args = par.parse_args()
|
||||
|
||||
plt.rcParams.update({'font.size': args.labelsize})
|
||||
|
||||
|
||||
def tri2car(data, k=100):
|
||||
a = data[:, 0]
|
||||
b = data[:, 1]
|
||||
c = data[:, 2]
|
||||
x = k * 0.5 * (2. * b + c) / (a + b + c)
|
||||
y = k * 0.5 * np.sqrt(3) * c / (a + b + c)
|
||||
return x, y
|
||||
|
||||
|
||||
def tri2car_(data, k=100):
|
||||
a = data[:, 0]
|
||||
b = data[:, 1]
|
||||
c = data[:, 2]
|
||||
dx = 100 - args.xmin
|
||||
a = (a - 0)/dx * 100
|
||||
b = (b - 0)/dx * 100
|
||||
c = (c - args.xmin)/dx * 100
|
||||
x = k * 0.5 * (2. * b + c) / (a + b + c)
|
||||
y = k * 0.5 * np.sqrt(3) * c / (a + b + c)
|
||||
return x, y
|
||||
|
||||
|
||||
def car2tri(x, y):
|
||||
if x is None or y is None:
|
||||
return None, None, None
|
||||
x, y = 0.01 * x, 0.01 * y
|
||||
c = 2 / np.sqrt(3) * y
|
||||
b = x - y / np.sqrt(3)
|
||||
a = 1 - b - c
|
||||
a = a * (100 - args.xmin)
|
||||
b = b * (100 - args.xmin)
|
||||
c = c * (100 - args.xmin) + args.xmin
|
||||
return a, b, c
|
||||
|
||||
|
||||
def MakeFig(label, xlabel, psum):
|
||||
# 枠線の生成
|
||||
frame = np.array([[1, 0, 0], [0, 1, 0], [0, 0, 1], [1, 0, 0]])
|
||||
fig, ax = plt.subplots(figsize=(args.figsize, args.figsize))
|
||||
x, y = tri2car(frame)
|
||||
ax.plot(x, y, "k-", lw=1)
|
||||
# grid線の生成
|
||||
m = 100 * np.linspace(0.1, 0.9, 9)
|
||||
g1, g2, g3 = np.zeros((9, 3)), np.zeros((9, 3)), np.zeros((9, 3))
|
||||
# test
|
||||
m = 100 * np.linspace(0, 1.0, 11)
|
||||
mx = np.linspace(args.xmin, 100, 11)
|
||||
my = np.linspace(0, 100 - args.xmin, 11)
|
||||
mz = np.linspace(0, 100 - args.xmin, 11)
|
||||
g1, g2, g3 = np.zeros((11, 3)), np.zeros((11, 3)), np.zeros((11, 3))
|
||||
|
||||
g1[:, 0], g1[:, 1] = m, m[::-1]
|
||||
g2[:, 0], g2[:, 2] = m, m[::-1]
|
||||
g3[:, 1], g3[:, 2] = m, m[::-1]
|
||||
x1, y1 = tri2car(g1)
|
||||
x2, y2 = tri2car(g2)
|
||||
x3, y3 = tri2car(g3)
|
||||
x4, y4 = x1[::-1], y1[::-1]
|
||||
dashed = [2, 2]
|
||||
t1, t2 = args.ticksoffset, args.ticksoffset / np.sqrt(2)
|
||||
t1, t2 = args.ticksoffset * 0.5, args.ticksoffset * 0.5 * np.sqrt(3)
|
||||
props = {'ha': 'center', 'va': 'center', 'size': args.ticksize}
|
||||
for i, xi in enumerate(x1):
|
||||
ax.plot([x1[i], x2[i]], [y1[i], y2[i]], "k:", lw=0.2, dashes=dashed)
|
||||
ax.plot([x2[i], x3[i]], [y2[i], y3[i]], "k:", lw=0.2, dashes=dashed)
|
||||
ax.plot([x4[i], x3[i]], [y4[i], y3[i]], "k:", lw=0.2, dashes=dashed)
|
||||
v1, v2 = "%.1f" % (m[i]), "%.1f" % (m[-i - 1])
|
||||
# bottom, C
|
||||
v2 = "%.1f" % (mz[-i - 1] * 0.01 * psum)
|
||||
ax.text(x1[i] - t1, y1[i] - t2, v2, props, rotation=60)
|
||||
# left, B
|
||||
v1 = "%.1f" % (my[i] * 0.01 * psum)
|
||||
ax.text(x2[i] - t1, y2[i] + t2, v1, props, rotation=-60)
|
||||
# right, A
|
||||
v2 = "%.1f" % (mx[-i - 1] * 0.01 * psum)
|
||||
ax.text(x3[i] + args.ticksoffset, y3[i], v2, props)
|
||||
# ラベルの生成
|
||||
t1, t2 = args.labeloffset, args.labeloffset / np.sqrt(2)
|
||||
ax.text(-t2, -t2, label[0], ha="right")
|
||||
ax.text(100 + t2, -t2, label[1], ha="left")
|
||||
ax.text(50, 50 * np.sqrt(3) + t1, label[2], ha="center", va="bottom")
|
||||
ax.text(50, -12, xlabel, ha="center", va="bottom")
|
||||
ax.axis('off')
|
||||
offset = 1
|
||||
ax.set_xlim(-offset, 120)
|
||||
ax.set_ylim(-offset, 50 * np.sqrt(3) + offset)
|
||||
fig.gca().set_aspect('equal', adjustable='box')
|
||||
return fig, ax
|
||||
|
||||
|
||||
def ScatterPlot(header, data, xlabel, val, psum=100, order=[1, 2, 0]):
|
||||
# cmap = plt.cm.get_cmap(args.colormap)
|
||||
cmap = mpl.colormaps.get_cmap(args.colormap)
|
||||
fig, ax = MakeFig(header[order], xlabel, psum)
|
||||
x, y = tri2car_(data[:, order])
|
||||
# contour
|
||||
if args.nocontour is False:
|
||||
xi = np.linspace(0, 100, args.grid)
|
||||
yi = np.linspace(0, 100, args.grid)
|
||||
zi = griddata((x, y), val, (xi[None, :], yi[:, None]),
|
||||
method=args.interp)
|
||||
zi[zi == 0] = 1e-8
|
||||
alpha = 0.8
|
||||
level = np.linspace(0, 1, 20)
|
||||
plt.contourf(xi, yi, zi, level, cmap=cmap, alpha=alpha)
|
||||
# 内挿して得られる最大ポイントの表示
|
||||
# zi_ = np.nan_to_num(zi)
|
||||
# y_, x_ = divmod(np.argmax(zi_), args.grid)
|
||||
# a_, b_, c_ = car2tri(xi[x_], yi[y_])
|
||||
# s = ", ".join(header[order])
|
||||
# print("Maximum point: %s = %.2f %.2f %.2f " % (s, a_, b_, c_))
|
||||
|
||||
# scatter
|
||||
bounds = np.linspace(0, 1, 11)
|
||||
norm = mpl.colors.BoundaryNorm(bounds, cmap.N)
|
||||
# glassのプロット
|
||||
idx = (val == 1)
|
||||
if len(idx) != 0:
|
||||
ax.scatter(x[idx], y[idx], marker="o", label="glass",
|
||||
color=cmap(0.999), edgecolor="black")
|
||||
idx = ((0 < val) & (val < 1))
|
||||
# crystalとglassの混ざったもののプロット
|
||||
if len(idx) != 0:
|
||||
ax.scatter(x[idx], y[idx], marker="^", label="glass/crystal",
|
||||
color=cmap(0.5), edgecolor="black")
|
||||
cs = ax.scatter(x, y, c=val, cmap=cmap, norm=norm, s=0.0)
|
||||
# crystalのプロット
|
||||
idx = (val == 0)
|
||||
if len(idx) != 0:
|
||||
ax.scatter(x[idx], y[idx], marker="x", label="crystal", color=cmap(0))
|
||||
# colorbarのプロット
|
||||
if args.nocolorbar is False:
|
||||
cbar = fig.colorbar(cs, fraction=0.035, alpha=1.0)
|
||||
cbar.ax.set_ylabel('glass vol%', fontsize=14)
|
||||
cbar.ax.set_yticklabels(['%.0f' % (200 * x)
|
||||
for x in bounds], fontsize=12)
|
||||
if args.nolegend is False:
|
||||
ax.legend(loc="best")
|
||||
return fig
|
||||
|
||||
|
||||
# xlsデータの読み込み
|
||||
df = pd.read_excel(args.xlsfile, skiprows=args.header)
|
||||
df = df.dropna()
|
||||
# mol_data = mol_data/18.67*100
|
||||
mol_header = df.columns
|
||||
mol_data = df.iloc[:, args.mol_col].to_numpy()
|
||||
val = df.iloc[:, args.GC_col].to_numpy()
|
||||
print("Number of data : ", df.shape)
|
||||
print("Plot header [col]: ", mol_header[args.mol_col].to_list(), args.mol_col)
|
||||
print("G/C data [col]: {} [{}]".format(mol_header[args.GC_col], args.GC_col))
|
||||
|
||||
psum = np.sum(mol_data, axis=1)[0]
|
||||
# プロット
|
||||
fig_mol = ScatterPlot(mol_header, mol_data, args.xlabel, val, psum)
|
||||
|
||||
if args.outfile is not None:
|
||||
fig_mol.savefig(args.outfile)
|
||||
print(args.outfile, "was created.")
|
||||
|
||||
|
||||
def onclick(event):
|
||||
a, b, c = car2tri(event.xdata, event.ydata)
|
||||
if a is None:
|
||||
return
|
||||
s = mol_header[[1, 2, 0]].to_list()
|
||||
print('button=%d %s=(%.2f %.2f %.2f)' % (event.button, s, a, b, c))
|
||||
|
||||
|
||||
fig_mol.canvas.mpl_connect('button_press_event', onclick)
|
||||
plt.show()
|
||||
Reference in New Issue
Block a user