3步掌握MZmine 3质谱分析:从原始数据到可视化结果的完整工作流
2026/7/18 14:42:05
分形(Fractal)是具有自相似性的几何图形,小尺度下的形态与整体形态高度相似,典型代表有曼德博集合(Mandelbrot Set)、朱利亚集合(Julia Set)、科赫雪花、分形树等。Python结合matplotlib、numpy(高效数值计算)和numba(加速循环)可以轻松绘制出视觉效果惊艳的分形图,本文从基础原理到代码实战,教你画出高质量的分形图形。
需要的核心库:
numpy:数值计算(矩阵运算、复数处理)matplotlib:绘图与色彩渲染numba:JIT编译加速(分形计算涉及大量循环,纯Python速度慢)PIL(可选):保存高清图片执行安装命令:
pipinstallnumpy matplotlib numba pillow分形计算的核心是迭代判断点是否属于分形集合,循环次数多且计算密集:
numpy向量化运算替代纯Python循环;numba.jit装饰器编译核心函数,提速10~100倍;曼德博集合是最经典的分形,定义为复平面上满足 ( z_{n+1} = z_n^2 + c )(初始 ( z_0=0 ))迭代不发散的点 ( c=x+yi ) 的集合。
importnumpyasnpimportmatplotlib.pyplotaspltfromnumbaimportjitfrommatplotlib.colorsimportLinearSegmentedColormap# ===================== 1. 核心计算函数(Numba加速) =====================@jit(nopython=True)# JIT编译,大幅提速defmandelbrot(c,max_iter):"""判断单个点c是否属于曼德博集合,返回迭代次数(用于上色)"""z=0n=0whileabs(z)<=2andn<max_iter:z=z*z+c n+=1# 平滑上色:避免迭代次数突变导致的色块ifn==max_iter:returnmax_iter# 属于集合,设为最大迭代次数returnn+1-np.log(np.log2(abs(z)))# 平滑后的迭代次数@jit(nopython=True)defmandelbrot_set(x_min,x_max,y_min,y_max,width,height,max_iter):"""生成曼德博集合的迭代次数矩阵"""x=np.linspace(x_min,x_max,width)y=np.linspace(y_min,y_max,height)img=np.zeros((height,width))foriinrange(height):forjinrange(width):c=complex(x[j],y[i])img[i,j]=mandelbrot(c,max_iter)returnimg# ===================== 2. 自定义色彩映射(更美观) =====================defcreate_fractal_cmap():"""创建自定义分形配色(深蓝→紫色→粉色→黄色→白色)"""colors=[(0.0,0.0,0.1),# 深蓝(集合内部)(0.2,0.0,0.5),# 深紫(0.5,0.1,0.8),# 粉紫(0.8,0.2,1.0),# 亮粉(1.0,0.8,0.2),# 黄色(1.0,1.0,1.0)# 白色(迭代次数最多)]returnLinearSegmentedColormap.from_list("fractal",colors,N=1024)# ===================== 3. 绘制曼德博集合 =====================defplot_mandelbrot():# 1. 配置参数(可调整视角,比如放大局部细节)# 全局视图:x∈[-2.0, 1.0], y∈[-1.5, 1.5]# 局部细节(比如“海马谷”):x∈[-0.8, -0.7], y∈[0.0, 0.1]x_min,x_max=-2.0,1.0y_min,y_max=-1.5,1.5width,height=2000,2000# 分辨率(越高越清晰,计算越久)max_iter=1000# 迭代次数(越高细节越多)# 2. 计算分形数据print("开始计算曼德博集合...")img=mandelbrot_set(x_min,x_max,y_min,y_max,width,height,max_iter)print("计算完成!")# 3. 绘图配置plt.figure(figsize=(10,10),dpi=200)# dpi越高,图片越清晰cmap=create_fractal_cmap()# 自定义配色# 绘制(用log缩放让色彩过渡更自然)plt.imshow(img,cmap=cmap,extent=(x_min,x_max,y_min,y_max),aspect="equal")# 4. 美化设置(无坐标轴、标题等)plt.axis("off")# 隐藏坐标轴plt.tight_layout(pad=0)# 去除边距plt.title("Mandelbrot Set",fontsize=16,color="white",pad=10)# 可选标题# 5. 保存高清图片plt.savefig("mandelbrot_set.png",dpi=300,# 保存分辨率bbox_inches="tight",# 去除白边facecolor="black"# 背景色(分形背景用黑色更美观))plt.show()if__name__=="__main__":plot_mandelbrot()@jit(nopython=True)编译核心迭代函数,2000×2000分辨率的计算时间从几十分钟缩短到几十秒;n + 1 - np.log(np.log2(abs(z)))让色彩过渡更自然;dpi=300保存,无坐标轴、无白边,符合壁纸级视觉效果。x_min/x_max/y_min/y_max,比如聚焦“海马谷”(x∈[-0.8, -0.7], y∈[0.0, 0.1]),能看到更精细的分形结构;max_iter越大,细节越多(但计算越久),局部放大时建议设为2000+;create_fractal_cmap中的颜色值,比如换成“青→绿→橙”的暖色调。朱利亚集合与曼德博集合同源,区别是迭代公式中 ( c ) 为固定常数,( z_0 ) 为复平面上的点(( z_{n+1}=z_n^2 + c ))。不同的 ( c ) 会生成完全不同的分形形态,视觉效果同样惊艳。
importnumpyasnpimportmatplotlib.pyplotaspltfromnumbaimportjitfrommatplotlib.colorsimportLinearSegmentedColormap# ===================== 1. 核心计算函数 =====================@jit(nopython=True)defjulia(z,c,max_iter):"""判断点z是否属于朱利亚集合"""n=0whileabs(z)<=2andn<max_iter:z=z*z+c n+=1ifn==max_iter:returnmax_iterreturnn+1-np.log(np.log2(abs(z)))@jit(nopython=True)defjulia_set(c,x_min,x_max,y_min,y_max,width,height,max_iter):"""生成朱利亚集合数据"""x=np.linspace(x_min,x_max,width)y=np.linspace(y_min,y_max,height)img=np.zeros((height,width))foriinrange(height):forjinrange(width):z=complex(x[j],y[i])img[i,j]=julia(z,c,max_iter)returnimg# ===================== 2. 自定义配色(冷色调) =====================defcreate_julia_cmap():colors=[(0.0,0.1,0.2),# 深蓝黑(0.1,0.3,0.8),# 蓝(0.2,0.8,1.0),# 青(0.5,1.0,0.8),# 浅青(1.0,1.0,1.0)# 白]returnLinearSegmentedColormap.from_list("julia",colors,N=1024)# ===================== 3. 绘制朱利亚集合 =====================defplot_julia():# 1. 核心参数(不同的c对应不同形态,推荐几个经典值)# c = -0.8 + 0.156j (经典螺旋)# c = 0.285 + 0.01j (羽毛状)# c = -0.7269 + 0.1889j (蝴蝶状)c=complex(-0.8,0.156)x_min,x_max=-1.5,1.5y_min,y_max=-1.5,1.5width,height=2000,2000max_iter=1000# 2. 计算数据print("开始计算朱利亚集合...")img=julia_set(c,x_min,x_max,y_min,y_max,width,height,max_iter)print("计算完成!")# 3. 绘图plt.figure(figsize=(10,10),dpi=200)cmap=create_julia_cmap()plt.imshow(img,cmap=cmap,extent=(x_min,x_max,y_min,y_max),aspect="equal")plt.axis("off")plt.tight_layout(pad=0)plt.savefig("julia_set.png",dpi=300,bbox_inches="tight",facecolor="black")plt.show()if__name__=="__main__":plot_julia()不同的复数 ( c ) 会生成完全不同的朱利亚集合:
c = -0.8 + 0.156j:螺旋状结构,视觉冲击力强;c = 0.285 + 0.01j:羽毛状分形,细节丰富;c = -0.7269 + 0.1889j:蝴蝶状分形,对称美感;c = 0.45 + 0.1428j:类似星系的结构。分形树是递归分形的经典案例,通过“主干→分支→子分支”的自相似递归生成,代码更简单,适合入门。
importmatplotlib.pyplotaspltimportnumpyasnp# ===================== 1. 递归绘制分形树 =====================defdraw_fractal_tree(x,y,angle,length,depth,ax):""" 递归绘制分形树 :param x/y: 当前起点坐标 :param angle: 当前分支角度(弧度) :param length: 当前分支长度 :param depth: 递归深度 :param ax: 绘图轴 """ifdepth==0:return# 计算分支终点坐标dx=length*np.cos(angle)dy=length*np.sin(angle)x2=x+dx y2=y+dy# 绘制当前分支(深度越浅,颜色越绿,线条越粗)color=(0.1,0.6+0.3*(depth/10),0.1)# 从深绿到浅绿ax.plot([x,x2],[y,y2],color=color,linewidth=depth/2,solid_capstyle="round")# 递归绘制左分支(角度偏转30°,长度缩短)draw_fractal_tree(x2,y2,angle+np.pi/6,length*0.7,depth-1,ax)# 递归绘制右分支(角度偏转30°,长度缩短)draw_fractal_tree(x2,y2,angle-np.pi/6,length*0.7,depth-1,ax)# ===================== 2. 绘制分形树 =====================defplot_fractal_tree():# 1. 初始化画布fig,ax=plt.subplots(figsize=(10,12),dpi=200)ax.set_aspect("equal")ax.set_xlim(-20,20)ax.set_ylim(0,30)ax.axis("off")# 隐藏坐标轴ax.set_facecolor("#f0f0f0")# 浅灰色背景# 2. 绘制分形树(起点在底部中间,初始角度向上,递归深度10)draw_fractal_tree(0,0,np.pi/2,10,10,ax)# 3. 保存图片plt.tight_layout(pad=0)plt.savefig("fractal_tree.png",dpi=300,bbox_inches="tight",facecolor="#f0f0f0")plt.show()if__name__=="__main__":plot_fractal_tree()depth越大,树枝越多(建议10~12,太大易卡顿);np.pi/6(30°),角度越大,树越“蓬松”;0.7,值越小,分支越短,树越紧凑;color的RGB值,比如换成“红→橙”的秋色调。#101010)或浅灰(#f8f8f8)作为背景,更柔和;LinearSegmentedColormap自定义渐变,贴合分形的层次;np.log(img + 1)让低迭代次数的色彩过渡更自然。dpi=300(打印级分辨率),bbox_inches="tight"去除白边;结合matplotlib.animation制作分形演化动画(比如曼德博集合放大过程):
# 示例:简单动画框架(需结合曼德博代码)importmatplotlib.animationasanimation fig,ax=plt.subplots(figsize=(10,10))defupdate(frame):# 每次帧调整x/y范围(放大局部)x_min=-2.0+frame*0.01x_max=1.0-frame*0.01img=mandelbrot_set(x_min,x_max,y_min,y_max,width,height,max_iter)ax.imshow(img,cmap=cmap,extent=(x_min,x_max,y_min,y_max))ax.axis("off")return[ax]ani=animation.FuncAnimation(fig,update,frames=100,interval=50)ani.save("mandelbrot_animation.mp4",writer="ffmpeg",dpi=150)numpy(数值)+matplotlib(绘图)+numba(加速)是绘制分形的黄金组合;通过以上代码和技巧,你可以轻松画出壁纸级的分形图,无论是用于学习、可视化还是艺术创作,都能达到专业级效果。