Python으로 Sigmaplot의 rectangular hyperbola 그래프의 모수를 찾고 그래프 그리기 - Ethan

Python으로 Sigmaplot의 rectangular hyperbola 그래프의 모수를 찾고 그래프 그리기

Github: https://github.com/EthanSeok/SigmaPlot_Python


Sigmaplot.py

소개

sigmaplot.py는 시그마 플롯의 rectangular hyperbola를 파이썬으로 그릴 수 있는 프로그램입니다. 이 프로그램은 pandas, scipy, matplotlib, seaborn 라이브러리를 사용하여 데이터를 처리하고 그래프를 그립니다.


설치

sigmaplot.py를 사용하기 위해서는, pandas, scipy, matplotlib, seaborn 라이브러리가 설치되어 있어야 합니다. 이 라이브러리들은 일반적으로 pip 명령어를 통해 설치할 수 있습니다.

1
2
3
4
pip install pandas
pip install scipy
pip install matplotlib
pip install seaborn

사용법

sigmaplot.py는 input 폴더에 있는 xlsx 또는 csv 파일을 읽어와 그래프를 그립니다. 개별 파일을 입력하거나, input 폴더에 있는 모든 파일을 처리할 수 있습니다.

입력자료 포맷

image

입력자료는 4반복, 3반복 지원.

개별 파일 입력

개별 파일 입력(yes)을 선택하면, 파일 이름을 입력하라는 메시지가 출력됩니다. 이때, 파일 이름은 input 폴더에 있는 파일 이름과 동일해야 합니다.

모든 파일 입력

모든 파일 입력(no)을 선택하면, input 폴더에 있는 모든 xlsx 또는 csv 파일을 자동으로 처리합니다.

코드 실행

sigmaplot.py를 실행하면, 파일 입력 방식을 선택하는 메시지가 출력됩니다. 파일 입력 방식을 선택하면, 처리 중인 파일 이름과 결과가 출력됩니다. 결과 그래프는 output 폴더에 파일 이름.png 형식으로 저장됩니다.


함수 설명

func

func 함수는 데이터를 입력받아 y0, a, b 값을 최적화합니다. 최적화는 scipy.optimize.differential_evolution 함수를 사용합니다.

cal

cal 함수는 입력 파일과 S 값(Ca-S 데이터)을 입력 받습니다. 이 함수는 func 함수를 호출하여 최적화된 y0, a, b 값을 반환합니다.

plot

plot 함수는 입력 파일, 결과를 저장할 폴더 이름, 파일 이름을 입력 받습니다. 이 함수는 cal 함수를 호출하여 최적화된 y0, a, b 값을 사용하여 그래프를 그립니다.

main

main 함수는 프로그램의 메인 함수입니다. 파일 입력 방식을 선택하는 메시지를 출력하고, 선택한 방식에 따라 input 폴더의 파일들을 처리합니다.


sigmaplot.py

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
import pandas as pd
from scipy.optimize import differential_evolution
import matplotlib.pyplot as plt
import seaborn as sns
import os
from tqdm import tqdm


def func(parameters, *data):
y0, a, b = parameters
x, y = data
result = 0
for i in range(len(x)):
result += ((y0 + a * x[i] / (b + x[i])) - y[i])**2

return result ** 0.5


def cal(infile, s):
s_df = pd.melt(infile, id_vars=['Ca'], value_vars=[f"{s}-1", f"{s}-2", f"{s}-3", f"{s}-4"], var_name='S', value_name=f'{s}')
bounds = [(-10, -1), (10, 100), (200, 1000)]
x = s_df['Ca'].values
y = s_df[f'{s}'].values
args = (x, y)

results = differential_evolution(func, bounds, args=args)
# print(f"{s} results:", results.x)
return results, s, s_df


def plot(infile, output_dir, filename):
fig, ax = plt.subplots(figsize=(9.4,6))
x = infile['Ca'].sort_values(ascending=True).values
s_values = ['S1', 'S2', 'S3', 'S4'] if 'S4-1' in infile.columns else ['S1', 'S2', 'S3']
An_dict = {}
color_list = ['#7f0000', '#006837', '#feb24c', '#253494']

with tqdm(total=len(s_values), desc=f'{filename}', unit='image') as pbar:
for i, (s, label) in enumerate(zip(s_values, ['Ca vs 1-1 - 1-4 \n', 'Ca vs 2-1 - 2-4 \n', 'Ca vs 3-1 - 3-4 \n', 'Ca vs 4-1 - 4-4 \n'] if 'S4-1' in infile.columns else ['Ca vs 1-1 - 1-4 \n', 'Ca vs 2-1 - 2-4 \n', 'Ca vs 3-1 - 3-4 \n'])):
An = []
results, s , s_df = cal(infile, s)
y0 = results.x[0]
a = results.x[1]
b = results.x[2]
for j in range(len(x)):
An.append((y0 + a * x[j] / (b + x[j])))
An_dict[s] = An
grouped = s_df.groupby('Ca').agg({s: ['mean', 'sem']})
grouped.columns = ['S1_mean', 'S1_std']
grouped.reset_index(inplace=True)
x = grouped['Ca']
y = grouped['S1_mean']
yerr = grouped['S1_std']
sns.lineplot(x=x, y=An, color=color_list[i], legend=False, linewidth=1.5, alpha=0.84)
ax.errorbar(x=x, y=y, yerr=yerr, label=f"{label} {y0:.3f}+{a:.3f}*x/({b:.4f}+x)", color=color_list[i], fmt='o', capsize=6, markersize=7.5)
pbar.update(1)
ax.set(ylim=(-10, 40))
ax.set_ylabel('$A(μmol/m^2/s)$')
ax.set(xlim=(-100, 1600))
ax.set_xlabel('$Ca(μmol/mol)$')
ax.legend(bbox_to_anchor=(1.02, 1), loc='upper left')
fig.subplots_adjust(right=0.68)
fig.savefig(os.path.join(f'{output_dir}/{filename}.png'), dpi=300)


def main():
output_dir = "output/"
if not os.path.exists(output_dir):
os.makedirs(output_dir)

method = input('파일을 개별 입력하겠습니까? ex) yes or no : ')

if method == 'yes':
filename = input('파일 이름을 입력하시오: ')
infile = pd.read_excel(f'input/{filename}')
plot(infile, output_dir, filename)

elif method == 'no':
file_paths = [f'input/{x}' for x in os.listdir("input/") if x.endswith(".xlsx") or x.endswith(".csv")]
for file_path in file_paths:
if file_path.endswith(".xlsx"):
infile = pd.read_excel(file_path)
elif file_path.endswith(".csv"):
infile = pd.read_csv(file_path)
filename = os.path.splitext(os.path.basename(file_path))[0]
plot(infile, output_dir, filename)


if __name__ == '__main__':
main()

결과

SigmaPlot-Original

image


SigmaPlot-Python

9월100동

공유하기