当前位置: 首页 > news >正文

【python】三元图绘制(详细注释)

结果

代码

import matplotlib.pyplot as plt
import matplotlib.patches as patches
import numpy as np
from scipy.spatial import ConvexHull
import matplotlib.font_manager as fm# --- 中文的 matplotlib 字体设置 ---
try:font_path = fm.findfont(fm.FontProperties(family='SimHei'))font_prop = fm.FontProperties(fname=font_path)plt.rcParams['font.family'] = font_prop.get_name()plt.rcParams['axes.unicode_minus'] = Falseprint("使用 'SimHei' 字体进行中文显示。")
except:try:font_path = fm.findfont(fm.FontProperties(family='Microsoft YaHei'))font_prop = fm.FontProperties(fname=font_path)plt.rcParams['font.family'] = font_prop.get_name()plt.rcParams['axes.unicode_minus'] = Falseprint("使用“Microsoft YaHei”字体进行中文显示。")except:print("警告:找不到“SimHei”或“Microsoft YaHei”字体。中文字符可能无法正确显示。")plt.rcParams['font.family'] = 'sans-serif'plt.rcParams['axes.unicode_minus'] = False# --- 字体设置结束 ---def ternary_to_cartesian(t, l, r, scale=1.0):"""将三元坐标 (上、左、右) 转换为笛卡尔坐标 (x, y)。在我们的例子中:t=水,l=乳化剂,r=油,scale = 1假设(0,0)时 乳化剂=1,(1, 0)时 油=1,(1/2, 1*sqrt(3)/2)时 水=1给定点(水,乳化剂、油),其中 乳化剂 + 油 + 水 = scale"""Emul, Oil, Water = l, r, tx = Oil * scale + Water * scale/2.0y = Water * scale * np.sqrt(3.0)/2.0return x, ydef parse_data(data_string):"""将数据字符串解析为 [Emul, Oil, Water] 列表。"""if "乳化剂:油:水" in data_string:data_string = data_string.split("乳化剂:油:水")[-1].strip()# 如果不提供分隔符参数,split() 方法会使用空白字符(包括空格、制表符 \t 和换行符 \n)作为默认分隔符。points_str = data_string.split()data_points = []for point_str in points_str:try:# map函数主要用于对一个或多个可迭代对象(如列表、元组等)应用一个函数,并返回一个迭代器。这个迭代器包含应用函数后的结果。emul, oil, water = map(float, point_str.split(':'))# 如果 sum 不是 1,则标准化,但打印警告current_sum = emul + oil + waterif not np.isclose(current_sum, 1.0, atol=1e-2):# np.isclose 函数用于比较两个数组元素是否在给定的容差范围内相等。 atol=1e-2 表示绝对容差为 0.01。print(f"警告:点 {point_str} 之和不等于 1(近似值)。总和 = {current_sum:.4f}. 规范化.")emul /= current_sumoil /= current_sumwater /= current_sumdata_points.append([emul, oil, water])except ValueError as e:print(f"解析点错误 '{point_str}': {e}")continuereturn data_points# 提供的数据字符串
data_string = "0.30:0.03:0.67 0.22:0.02:0.76 0.21:0.02:0.77 0.24:0.03:0.73 0.20:0.02:0.78 0.19:0.03:0.78 0.33:0.06:0.61 0.16:0.03:0.81 0.26:0.06:0.68 0.23:0.08:0.69"# 解析数据
data_points = parse_data(data_string)# --- 绘图 ---
scale = 1.0 # 用于绘图的三个分量之和
# 创建一个宽8英寸、高7英寸的图形。
fig, ax = plt.subplots(figsize=(8, 7))# 定义三角形的顶点(在三元坐标中 - Water、Emul、Oil
V_emul_ternary = (0, scale, 0)   # Emul=1
V_oil_ternary = (0, 0, scale)    # Oil=1
V_water_ternary = (scale, 0, 0)  # Water=1# 计算顶点的笛卡尔坐标
V_emul_cartesian = ternary_to_cartesian(V_emul_ternary[0], V_emul_ternary[1], V_emul_ternary[2], scale)
V_oil_cartesian = ternary_to_cartesian(V_oil_ternary[0], V_oil_ternary[1], V_oil_ternary[2], scale)
V_water_cartesian = ternary_to_cartesian(V_water_ternary[0], V_water_ternary[1], V_water_ternary[2], scale)# 将数据点映射到笛卡尔坐标
cartesian_points = np.array([ternary_to_cartesian(p[2], p[0], p[1], scale) for p in data_points]) # Pass as (Water, Emul, Oil)# 绘制三角形背景
# 绘制主三角形边界
triangle_vertices_cartesian = np.array([V_emul_cartesian, V_oil_cartesian, V_water_cartesian, V_emul_cartesian]) # Close the main triangle path
ax.plot(triangle_vertices_cartesian[:, 0], triangle_vertices_cartesian[:, 1], 'k-', linewidth=1.0)# 允许用户将 x 轴和 y 轴的数据以折线图的形式展示出来。# 添加网格线和刻度线(基于三元结构手动放置) np.arange用于生成等差数列
tick_values = np.arange(0.25, scale, 0.25)# 恒定水(平行于乳化剂-油)的网格线
for water_const in tick_values:# 乳化剂-水 边 (油=0) 和 油-水 边 (乳化剂=0) 上的点p1_cart = ternary_to_cartesian(water_const, scale - water_const, 0, scale) # (Water=water_const, Emul=scale-water_const, Oil=0)p2_cart = ternary_to_cartesian(water_const, 0, scale - water_const, scale) # (Water=water_const, Emul=0, Oil=scale-water_const)ax.plot([p1_cart[0], p2_cart[0]], [p1_cart[1], p2_cart[1]], 'k--', linewidth=0.5, alpha=0.7)# 左侧 (Water) 轴上的标签ax.text(p1_cart[0] - 0.02, p1_cart[1], f'{water_const:.2f}', ha='right', va='center', rotation=60)# 恒定水(平行于乳化剂-水)的网格线
for oil_const in tick_values:# 乳化剂-油 边 (水=0) 和 水-油 边 (乳化剂=0) 上的点p1_cart = ternary_to_cartesian(0, scale - oil_const, oil_const, scale) # (Water=0, Emul=scale-oil_const, Oil=oil_const)p2_cart = ternary_to_cartesian(scale - oil_const, 0, oil_const, scale) # (Water=scale-oil_const, Emul=0, Oil=oil_const)ax.plot([p1_cart[0], p2_cart[0]], [p1_cart[1], p2_cart[1]], 'k--', linewidth=0.5, alpha=0.7)# 右侧(油)轴上的标签ax.text(p2_cart[0] + 0.02, p2_cart[1], f'{oil_const:.2f}', ha='left', va='center', rotation=-60)# Grid lines for constant Emul (parallel to Oil-Water side)
for emul_const in tick_values:# Points on Emul-Water edge (Oil=0) and Emul-Oil edge (Water=0)p1_cart = ternary_to_cartesian(scale - emul_const, emul_const, 0, scale) # (Water=scale-emul_const, Emul=emul_const, Oil=0)p2_cart = ternary_to_cartesian(0, emul_const, scale - emul_const, scale) # (Water=0, Emul=emul_const, Oil=scale-emul_const)ax.plot([p1_cart[0], p2_cart[0]], [p1_cart[1], p2_cart[1]], 'k--', linewidth=0.5, alpha=0.7)# Label on the bottom (Emul) axisax.text(p2_cart[0], p2_cart[1] - 0.02, f'{emul_const:.2f}', ha='center', va='top')# 添加顶点标签(1.00 表示顶点处的组件,0.00 表示其他组件)
ax.text(V_emul_cartesian[0] - 0.05, V_emul_cartesian[1], '乳化剂\n1.00', ha='right', va='center')
#ax.text(V_emul_cartesian[0] + 0.02, V_emul_cartesian[1] - 0.02, '油相 0.00\n水相 0.00', ha='left', va='top', fontsize=8)ax.text(V_oil_cartesian[0] + 0.05, V_oil_cartesian[1], '油相\n1.00', ha='left', va='center')
#ax.text(V_oil_cartesian[0] - 0.02, V_oil_cartesian[1] - 0.02, '乳化剂 0.00\n水相 0.00', ha='right', va='top', fontsize=8)ax.text(V_water_cartesian[0], V_water_cartesian[1] + 0.03, '水相\n1.00', ha='center', va='bottom')
#ax.text(V_water_cartesian[0] - 0.04, V_water_cartesian[1] - 0.02, '乳化剂 0.00', ha='right', va='top', fontsize=8)
#ax.text(V_water_cartesian[0] + 0.04, V_water_cartesian[1] - 0.02, '油相 0.00', ha='left', va='top', fontsize=8)# 基于提供的图像简化的角标签
ax.text(V_emul_cartesian[0], V_emul_cartesian[1] - 0.02, '0.00', ha='left', va='top') # Oil=0, Water=0
ax.text(V_oil_cartesian[0], V_oil_cartesian[1] - 0.02, '0.00', ha='right', va='top') # Emul=0, Water=0
# ax.text(V_water_cartesian[0] - 0.04, V_water_cartesian[1] - 0.02, '0.00', ha='right', va='top') # Emul=0, Oil=0
ax.text(V_water_cartesian[0] + 0.04, V_water_cartesian[1] - 0.02, '0.00', ha='left', va='top') # Oil=0, Emul=0# 绘制数据点
ax.plot(cartesian_points[:, 0], cartesian_points[:, 1], 'o', color='red', markersize=5, zorder=5, label='数据点')# 创建包围点的多边形(使用 Convex Hull)
if len(cartesian_points) >= 3:try:hull = ConvexHull(cartesian_points)# 按顺序获取外壳的顶点hull_points = cartesian_points[hull.vertices]# 将第一个点附加到 hull_points 数组的末尾,以绘制闭合边界hull_points_closed = np.vstack((hull_points, hull_points[0]))# 绘制闭合的外壳边界ax.plot(hull_points_closed[:, 0], hull_points_closed[:, 1], linestyle='-', linewidth=1.5, label='围成的区域')# 填充外壳线包围的区域polygon = patches.Polygon(hull_points, closed=True, facecolor='gray', alpha=0.5)ax.add_patch(polygon)except Exception as e:print(f"无法计算凸包或绘制多边形。仅标绘点。错误: {e}")print("如果所有点都是共线的或唯一点少于 3 个,则可能会发生这种情况。")else:print("没有足够的点(少于 3 个)来形成多边形。")# 设置绘图限制和纵横比
# 这一行代码的作用是设置图表中x轴的显示范围
ax.set_xlim(-0.15, scale + 0.15)
ax.set_ylim(-0.05, scale * np.sqrt(3.0)/2.0 + 0.15)
# 设置坐标轴纵横比的函数。具体来说,这个函数确保 x 轴和 y 轴的单位长度相同,从而避免图形中的形状因轴比例不同而变形。
ax.set_aspect('equal', adjustable='box')
# 用于关闭指定子图(Axes)的所有坐标轴线、刻度标记和标签。这意味着在绘图时,不会显示任何坐标轴、刻度线或标签,从而使图形更加简洁和专注于数据本身
ax.axis('off')# 添加标题和标签
plt.title('乳化剂-油-水 三元相图', fontsize=14)
# plt.figtext(): 这是Matplotlib库中的一个函数,用于在图形的任意位置添加文本。与plt.text()不同,plt.figtext()使用的是整个图形的坐标系,而不是某个特定的轴(Axes)的坐标系。这意味着即使文本位于轴外,也可以正常显示。
plt.figtext(0.5, 0.01, '混合乳化剂', ha='center', fontsize=10)
#plt.figtext(0.5, -0.02, 'A. 油酸乙酯', ha='center', fontsize=10)plt.savefig("三元图.jpg",dpi=600)
plt.legend()
plt.show()

三元图怎么看

(1)确定含义:

    各边长为100 %

(2)确定顺序:

    依AB、BC、CA顺序,分别代表B、C、A三组元的含量

(3)S点成分:

    按照规定顺序方向,引平行线,相交于三边的a、b、c点,确定成分

参考文献

【干货】看了这个还不懂三元相图算我输

相关文章:

  • javascript 实战案例 二级联动下拉选框
  • 杭州白塔岭画室怎么样?和燕壹画室哪个好?
  • 6.RV1126-OPENCV 形态学基础膨胀及腐蚀
  • Spring Boot整合Druid与Dynamic-Datasource多数据源配置:从错误到完美解决
  • 1. 引言
  • SQL注入漏洞-上篇
  • Qwen2.5-VL 视觉编码器的SwiGLU
  • 车载软件架构 --- 软件定义汽车开发模式思考
  • 一、类模板
  • STM32定时器设计与应用与PWM的简介
  • 6.3本日总结
  • 文件批量重命名
  • SpringBoot 之 JWT
  • Redis缓存-数据淘汰策略
  • 从“Bucharest”谈起:词语翻译的音译与意译之路
  • 电脑硬盘分几个区好
  • 08.MySQL复合查询详解
  • STM32与GD32标准外设库深度对比
  • SoloSpeech - 高质量语音处理模型,一键提取指定说话人音频并提升提取音频清晰度和质量 本地一键整合包下载
  • TypeScript 定义同步方法
  • 专业做外贸网站建设/微信营销软件哪个好用
  • 冷饮店怎么做网站/百度收录申请入口
  • 查企业法人信息查询平台/seo优化工具哪个好
  • 怎么直接做免费网站吗/阿里关键词排名查询
  • 模板建站oem代理/软文代写接单平台
  • 有了域名如何做网站/获客渠道有哪些