Fix multi-GPU with lazy CuPy init + rendering improvements
GPU fix: - Revert to CUDA_VISIBLE_DEVICES approach but with lazy CuPy init - gpu.py: CuPy is no longer imported at module level; _init_gpu() imports it lazily on first to_gpu() call. This allows workers to set CUDA_VISIBLE_DEVICES before CuPy creates a CUDA context. - gpu.py: detect GPU count via nvidia-smi (no CUDA context needed) - pipeline.py: each worker sets CUDA_VISIBLE_DEVICES=N before CuPy init, so each process uses only its assigned GPU Rendering improvements: - Title: split into bold title (14pt) + italic description (10pt) instead of single 15pt bold block - North arrow: moved inside data area (top-right corner) with semi-transparent white background for readability over data - Colorbar: full height (no gap for compass rose), added ScalarFormatter(useOffset=False) to avoid scientific notation - Colorbar compass rose gap removed since north arrow is now inside the data area
This commit is contained in:
@ -30,6 +30,7 @@ import matplotlib.pyplot as plt
|
||||
from matplotlib import rcParams
|
||||
from matplotlib.patches import Polygon as MplPolygon, Rectangle as RectPatch, FancyBboxPatch
|
||||
from matplotlib.colors import ListedColormap
|
||||
from matplotlib.ticker import ScalarFormatter
|
||||
|
||||
try:
|
||||
from cmcrameri import cm as cmc
|
||||
@ -495,15 +496,16 @@ def tif_to_png(tif_file, vis_dir, resolution, keep_tif=False, source_info=None,
|
||||
im = ax.imshow(data, cmap=cmap, aspect='equal', origin='upper',
|
||||
interpolation='bilinear')
|
||||
|
||||
ax.set_title(f"{title}\n{description}", fontsize=15, fontweight='bold', pad=10)
|
||||
ax.set_title(f"{title}", fontsize=14, fontweight='bold', pad=8)
|
||||
ax.text(0.5, 1.01, description, transform=ax.transAxes,
|
||||
fontsize=10, fontstyle='italic', color='#555555',
|
||||
ha='center', va='bottom')
|
||||
|
||||
# Colorbar/legend area — reduced height to leave room for compass rose above
|
||||
# Colorbar/legend area — full height alongside data
|
||||
cbar_left = data_left + data_width_frac + 0.02
|
||||
cbar_width = 0.04
|
||||
compass_height = 0.07
|
||||
compass_gap = 0.02
|
||||
cbar_bottom = data_bottom
|
||||
cbar_height = data_height_frac - compass_height - compass_gap
|
||||
cbar_height = data_height_frac
|
||||
if is_rgb:
|
||||
# RGB: descriptive text label instead of gradient colorbar
|
||||
cbar_ax = fig.add_axes([cbar_left, cbar_bottom, cbar_width, cbar_height])
|
||||
@ -521,12 +523,14 @@ def tif_to_png(tif_file, vis_dir, resolution, keep_tif=False, source_info=None,
|
||||
sm.set_array([])
|
||||
cbar = plt.colorbar(sm, cax=cbar_ax)
|
||||
cbar.ax.tick_params(labelsize=9, width=1.5)
|
||||
cbar.ax.yaxis.set_major_formatter(ScalarFormatter(useOffset=False))
|
||||
cbar.outline.set_linewidth(1.5)
|
||||
cbar.set_label(legend_label, fontsize=10, fontweight='bold')
|
||||
else:
|
||||
cbar_ax = fig.add_axes([cbar_left, cbar_bottom, cbar_width, cbar_height])
|
||||
cbar = plt.colorbar(im, cax=cbar_ax)
|
||||
cbar.ax.tick_params(labelsize=9, width=1.5)
|
||||
cbar.ax.yaxis.set_major_formatter(ScalarFormatter(useOffset=False))
|
||||
cbar.outline.set_linewidth(1.5)
|
||||
cbar.set_label(legend_label, fontsize=10, fontweight='bold')
|
||||
|
||||
@ -565,32 +569,35 @@ def tif_to_png(tif_file, vis_dir, resolution, keep_tif=False, source_info=None,
|
||||
spine.set_color('black')
|
||||
spine.set_linewidth(0.8)
|
||||
|
||||
# North arrow — compass rose style, positioned above the colorbar
|
||||
compass_bottom = data_bottom + data_height_frac + 0.02
|
||||
compass_height = 0.07
|
||||
compass_width = cbar_width + 0.03
|
||||
north_ax = fig.add_axes([cbar_left, compass_bottom, compass_width, compass_height])
|
||||
# North arrow — compass rose style, inside the data area (top-right corner)
|
||||
# Semi-transparent background for readability over any data
|
||||
north_ax = fig.add_axes([data_left + data_width_frac - 0.06,
|
||||
data_bottom + data_height_frac - 0.12,
|
||||
0.05, 0.10],
|
||||
facecolor='none')
|
||||
north_ax.set_xlim(-1.2, 1.2)
|
||||
north_ax.set_ylim(-0.5, 1.5)
|
||||
north_ax.set_ylim(-0.3, 1.5)
|
||||
north_ax.axis('off')
|
||||
north_ax.set_aspect('equal')
|
||||
north_ax.set_facecolor('white')
|
||||
# Semi-transparent white background circle
|
||||
circle_bg = plt.Circle((0, 0.5), 0.85, facecolor='white', edgecolor='#888888',
|
||||
linewidth=0.5, alpha=0.7, zorder=1)
|
||||
north_ax.add_patch(circle_bg)
|
||||
# N arrow
|
||||
north_ax.annotate('N', xy=(0, 1.3), fontsize=11, fontweight='bold',
|
||||
ha='center', va='bottom', color='#b22222')
|
||||
north_ax.annotate('N', xy=(0, 1.3), fontsize=9, fontweight='bold',
|
||||
ha='center', va='bottom', color='#b22222', zorder=10)
|
||||
north_ax.plot([0, 0], [0.0, 1.0], color='#b22222', linewidth=2.0, zorder=10)
|
||||
north_ax.add_patch(MplPolygon([[0, 0.3], [-0.2, 0.7], [0, 1.0], [0.2, 0.7]],
|
||||
closed=True, facecolor='#b22222', edgecolor='#b22222', zorder=9))
|
||||
# Cardinal ticks
|
||||
for angle, label in [(90, ''), (0, 'E'), (180, 'O'), (270, 'S')]:
|
||||
rad = np.radians(angle)
|
||||
r_text = 1.25
|
||||
north_ax.plot([0.85*np.cos(rad), 1.05*np.cos(rad)],
|
||||
[0.85*np.sin(rad), 1.05*np.sin(rad)],
|
||||
color='#555555', linewidth=0.8, zorder=5)
|
||||
if label:
|
||||
north_ax.text(r_text*np.cos(rad), r_text*np.sin(rad), label,
|
||||
fontsize=7, ha='center', va='center', color='#555555')
|
||||
north_ax.text(1.15*np.cos(rad), 1.15*np.sin(rad), label,
|
||||
fontsize=6, ha='center', va='center', color='#555555', zorder=5)
|
||||
|
||||
# Bottom info bar — enriched with source, method, date
|
||||
info_ax = fig.add_axes([data_left, 0.015, data_width_frac + cbar_width + 0.02, 0.09])
|
||||
|
||||
Reference in New Issue
Block a user