From 575c9bccba93aa6791ce7e354cb6bbb85013a218 Mon Sep 17 00:00:00 2001 From: Ricardo_T8 Date: Thu, 6 Nov 2025 13:29:39 +0800 Subject: [PATCH 1/2] style(correlation): change the default dot size From 1 to 10. Show the dots clearly. --- src/plotfig/correlation.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/plotfig/correlation.py b/src/plotfig/correlation.py index 8f840f1..9528574 100644 --- a/src/plotfig/correlation.py +++ b/src/plotfig/correlation.py @@ -24,7 +24,7 @@ def plot_correlation_figure( stats_method: str = "spearman", ci: bool = False, dots_color: str = "steelblue", - dots_size: int | float = 1, + dots_size: int | float = 10, line_color: str = "r", title_name: str = "", title_fontsize: int = 12, From b9bc5f68eeb3c8d118698ca06a95dc558f48696f Mon Sep 17 00:00:00 2001 From: Ricardo_T8 Date: Wed, 12 Nov 2025 19:10:41 +0800 Subject: [PATCH 2/2] feat(connection): add batch image cropping and GIF creation utilities - Add batch_crop_images function to crop multiple images with configurable margins - Add create_gif_from_images function to generate GIFs from image sequences --- src/plotfig/__init__.py | 9 ++- src/plotfig/brain_connection.py | 100 ++++++++++++++++++++++++++++++++ 2 files changed, 108 insertions(+), 1 deletion(-) diff --git a/src/plotfig/__init__.py b/src/plotfig/__init__.py index 9003ffd..d15c875 100644 --- a/src/plotfig/__init__.py +++ b/src/plotfig/__init__.py @@ -9,7 +9,12 @@ from .matrix import plot_matrix_figure from .brain_surface import plot_brain_surface_figure from .circos import plot_circos_figure -from .brain_connection import plot_brain_connection_figure, save_brain_connection_frames +from .brain_connection import ( + plot_brain_connection_figure, + save_brain_connection_frames, + batch_crop_images, + create_gif_from_images, +) from .utils import ( gen_hex_colors, gen_symmetric_matrix, @@ -35,6 +40,8 @@ # brain_connection "plot_brain_connection_figure", "save_brain_connection_frames", + "batch_crop_images", + "create_gif_from_images", # utils "gen_hex_colors", "gen_symmetric_matrix", diff --git a/src/plotfig/brain_connection.py b/src/plotfig/brain_connection.py index 83b2d92..3631b53 100644 --- a/src/plotfig/brain_connection.py +++ b/src/plotfig/brain_connection.py @@ -2,6 +2,8 @@ from pathlib import Path from typing import Literal from collections.abc import Sequence +from PIL import Image +import imageio import numpy as np import numpy.typing as npt @@ -19,6 +21,8 @@ __all__ = [ "plot_brain_connection_figure", "save_brain_connection_frames", + "batch_crop_images", + "create_gif_from_images", ] @@ -314,3 +318,99 @@ def save_brain_connection_frames( fig.update_layout(scene_camera=camera) pio.write_image(fig, f"{output_dir}/frame_{i:03d}.png", width=800, height=800) logger.info(f"保存了 {n_frames} 张图片在 {output_dir}") + + +def batch_crop_images( + directory_path: Path, + suffix: str = "_cropped", + left_frac: float = 0.25, + top_frac: float = 0.25, + right_frac: float = 0.25, + bottom_frac: float = 0.25, +): + """ + 批量裁剪指定目录下的图像文件。 + + Args: + directory_path (Path): 图像文件所在的目录路径。 + suffix (str, optional): 新文件名后缀。默认为 "_cropped"。 + left_frac (float, optional): 左侧裁剪比例(0-1)。默认为 0.2。 + top_frac (float, optional): 上侧裁剪比例(0-1)。默认为 0.15。 + right_frac (float, optional): 右侧裁剪比例(0-1)。默认为 0.2。 + bottom_frac (float, optional): 下侧裁剪比例(0-1)。默认为 0.15。 + + Notes: + 支持常见图像格式 (PNG, JPG, JPEG, BMP, TIFF)。 + 裁剪后的图像将保存在原目录中,并添加指定后缀,原图像保持不变。 + 所有裁剪均基于图像尺寸的百分比计算,无绝对像素值。 + """ + supported_extensions = {".png", ".jpg", ".jpeg", ".bmp", ".tiff", ".tif"} + + for image_path in directory_path.rglob("*"): + if ( + not image_path.is_file() + or image_path.suffix.lower() not in supported_extensions + ): + continue + + new_file_name = image_path.stem + suffix + image_path.suffix + + try: + figure = Image.open(image_path) + width, height = figure.size + print(f"图像宽度:{width},高度:{height}") + + left = int(width * left_frac) + right = int(width * (1 - right_frac)) + top = int(height * top_frac) + bottom = int(height * (1 - bottom_frac)) + + # 裁切图像 + cropped_fig = figure.crop((left, top, right, bottom)) + # 保存裁切后的图像 + cropped_fig.save(image_path.parent / new_file_name) + + figure.close() + cropped_fig.close() + except Exception as e: + print(f"处理文件 {image_path.name} 时出错: {e}") + + +def create_gif_from_images( + folder_path: str | Path, + output_name: str = "output.gif", + fps: int = 10, + extensions: Sequence[str] = (".png", ".jpg", ".jpeg"), +) -> None: + """ + 从指定文件夹中的图片生成 GIF 文件。 + + Args: + folder_path (str | Path): 图片所在文件夹路径 + output_name (str, optional): 输出 GIF 文件名,默认为 "output.gif" + fps (int, optional): GIF 帧率,默认为 10 + extensions (Sequence[str], optional): 图片文件扩展名过滤,默认为 ('.png', '.jpg', '.jpeg') + """ + folder = Path(folder_path) + if not folder.exists() or not folder.is_dir(): + raise ValueError(f"{folder} 不是有效的文件夹路径。") + + # 获取文件夹下指定扩展名的文件,并排序 + figures_path = sorted( + [f for f in folder.iterdir() if f.suffix.lower() in extensions] + ) + + if not figures_path: + raise ValueError(f"文件夹 {folder} 中没有找到符合 {extensions} 的图片文件。") + + figures = [Image.open(f) for f in figures_path] + + # 输出 GIF 路径 + output_path = folder / output_name + + # 创建 GIF + with imageio.get_writer(output_path, mode='I', fps=fps, loop=0) as writer: + for figure in figures: + writer.append_data(figure.convert('RGB')) + + print(f"GIF 已保存到: {output_path}")