Python论文多图绘制+代码+代码解读+绘图经验分享(2)


前言

重新看了自己写的上一篇文章,上一篇给出的代码解决的主要论文多图绘制中的小图拼接,且被拼接的小图是已知分布的图线。这里说明,如果我们要解决的问题是对于多个小图进行拼接操作,该如何在上一篇代码的基础上做出改动。


概念补充

  1. lambda函数(匿名函数)
    它是一种快速定义简单函数的方法。其语法是:
lambda arguments: expression

给个简单例子:

add = lambda x, y: x + y
print(add(5, 3))  # 输出8

代码更改部分及原因

  1. 对于图像文件不直接保存在同一个文件夹下的情况
    使用os.list方法查询搜索文件夹,使用。endwidth()方法搜索特定后缀的文件夹。因为我的图像文件是层层嵌套的,图像被放在每个文件下名为.out的文件下,因此之后的完整代码我的循环还要检查一边文件夹内的文件夹,这里可按需删改。
 image_dirs = [d for d in os.listdir(directory) if d.endswith('.out')]

  1. 对于图像文件保存在同一个文件夹下的情况
    首先我们将图像文件保存在一个文件夹下,然后使用一个循环读取文件夹下的文件。这里注意,代码在读文件顺序的时候,不是按照我们以为的1,2,3这样的阿拉伯数字递增的图像名去排列,所以直接默认让代码排列图的顺序的时候会出现乱序。为了解决这个问题,我们使用以下这段代码,这是一段比较通用的排序代码:
def sorted_numeric(data):
    convert = lambda text: int(text) if text.isdigit() else text.lower()
    numeric_key = lambda key: [ convert(c) for c in re.split('([0-9]+)', key) ]
    return sorted(data, key=numeric_key)

这个函数中,convert和numeric_key首先处理图像文件的名称,转换为能够使用sorted(排序内置函数)函数的形式。
convert 是一个将文本转换为数字的函数,如果文本可以转换为整数(isdigit()返回True),那么它就会转换;否则,它会将文本转换为小写。numeric_key 是一个函数,它使用正则表达式将键(字符串)中的数字和非数字字符分开,并对这些分开的部分应用convert函数。这意味着如果你有一个混合了数字和字母的字符串,它将被拆分成单独的数字和字母部分,然后数字将被转换为整数,字母将被转换为小写。
sorted(data, key=numeric_key):这是Python的内置排序函数,使用numeric_key函数作为关键字排序。
因此我们的图像得以按顺序排列。

完整代码

完整代码如下:

import numpy as np
import os
import re
import matplotlib.pyplot as plt
from matplotlib.gridspec import GridSpec
from matplotlib.image import imread

plt.style.use('classic')

def sorted_numeric(data):
    convert = lambda text: int(text) if text.isdigit() else text.lower()
    numeric_key = lambda key: [ convert(c) for c in re.split('([0-9]+)', key) ]
    return sorted(data, key=numeric_key)

def create_subplots(directory, figure_size=(10,10), filename='my_figure.svg'):
    '''创建子图,每个子图显示一个图像'''

    # 获取文件夹中的所有图像文件夹
    image_dirs = [d for d in os.listdir(directory) if d.endswith('.out')]
    image_dirs = sorted_numeric(image_dirs)  # 确保文件夹按照数字顺序排序

    # 创建图形和子图
    fig = plt.figure(figsize=figure_size)
    n = len(image_dirs)
    num_rows = int(np.ceil(np.sqrt(n)))
    num_cols = int(np.ceil(n / num_rows))
    gs = GridSpec(num_rows, num_cols, figure=fig)

    for i, image_dir in enumerate(image_dirs):
        # Assume that each directory contains exactly one image file
        image_file = os.path.join(directory, image_dir, f"{i}.png")

        ax = fig.add_subplot(gs[i // num_cols, i % num_cols])

        # Load and display the image
        img = imread(image_file)
        ax.imshow(img)
        
        # Adding information to each plot
        ax.set_title(f'figure {i+1}') # 小标题
        ax.axis('off')  # 隐藏坐标轴

    # Remove unused subplots
    for j in range(n, num_rows*num_cols):
        fig.delaxes(fig.add_subplot(gs[j // num_cols, j % num_cols]))

    # 保存图形,使用SVG格式和300 dpi的分辨率
    plt.savefig(filename, format='svg', dpi=300)

    # 显示图形
    plt.show()

调用方式:

create_subplots(' 存图的文件路径', figure_size=(10,10), filename='名字.svg')

代码评估

接下来思考一下这段代码是否足够灵活。以下是其功能及可以更改的部分:

  1. 合并上一篇文章的代码,这段代码能够处理特定分布的小图拼接的多图绘制情况,也能够处理多个嵌套文件夹下的图的读取绘制。
  2. 关于画图,我们将画图的代码封装成函数,因此,我们只需输入文件夹的路径,和我们需要画的画布的大小,以及要保存的格式,推荐拉伸不会变形的svg格式,不然png格式会在拉伸后清晰度发生变化。这种封装的形式会使得代码简洁,调用方便。
  3. 关于图的细节,则需要进入函数内部更改,如标题,小标题,是否隐藏坐标轴,风格,字体等等。后期的话会再出一些折线图等的绘图,按照本人的审美来设计绘制,这样的话,每次写论文我们就将数据保存,然后直接运行代码来绘图即可。

综上,这部分代码可以重复使用,觉得总结没白费!!耶斯!

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值