|
29 | 29 | import matplotlib.pyplot as plt |
30 | 30 | import sys |
31 | 31 | import os |
| 32 | +import re |
32 | 33 |
|
33 | 34 |
|
34 | 35 | # In[ ]: |
|
183 | 184 |
|
184 | 185 | # In[ ]: |
185 | 186 |
|
| 187 | +def safe_path_noext(path_noext: str) -> str: |
| 188 | + """ |
| 189 | + Takes a path WITHOUT extension, returns a Windows-safe path (still without extension). |
| 190 | + Ensures parent directory exists. Replaces illegal filename chars with '_'. |
| 191 | + """ |
| 192 | + dir_name, base = os.path.split(path_noext) |
| 193 | + if dir_name and not os.path.exists(dir_name): |
| 194 | + os.makedirs(dir_name, exist_ok=True) |
| 195 | + safe_base = re.sub(r'[\\/:*?"<>|]+', '_', base) |
| 196 | + return os.path.join(dir_name, safe_base) if dir_name else safe_base |
186 | 197 |
|
187 | 198 | def plot_CAM_map(heatmap_interpolated_list, output_dir, name_list, save_pdf, colorblind=False): |
188 | 199 | """ |
@@ -226,7 +237,8 @@ def plot_CAM_map(heatmap_interpolated_list, output_dir, name_list, save_pdf, col |
226 | 237 |
|
227 | 238 | # Only save the figure if save_pdf is True |
228 | 239 | if save_pdf: |
229 | | - plt.savefig(f'{output_dir}.pdf') # Save the plot as a PDF |
| 240 | + safe_noext = safe_path_noext(output_dir) |
| 241 | + plt.savefig(f'{safe_noext}.pdf') # Save the plot as a PDF |
230 | 242 |
|
231 | 243 | plt.close(fig) |
232 | 244 |
|
@@ -255,7 +267,8 @@ def plot_CAM_lines_only(heatmap_interpolated_list, output_path, name_list): |
255 | 267 | axs[i].grid(alpha=0.3, linewidth=0.5) |
256 | 268 | axs[-1].set_xlabel('Nucleotide position', fontsize=11) |
257 | 269 | plt.tight_layout() |
258 | | - fig.savefig(f'{output_path}.pdf') |
| 270 | + safe_noext = safe_path_noext(output_path) |
| 271 | + fig.savefig(f'{safe_noext}.pdf') |
259 | 272 | plt.close(fig) |
260 | 273 |
|
261 | 274 | # In[ ]: |
@@ -375,27 +388,31 @@ def get_sequence(triplet_index): |
375 | 388 | if lines_only and not output_cam_pdf: |
376 | 389 | plot_CAM_lines_only( |
377 | 390 | heatmap_interpolated_list, |
378 | | - f'{output_dir}/{name_list[2]}_LINES', |
| 391 | + safe_path_noext(os.path.join(output_dir, f'{name_list[2]}_LINES')), |
379 | 392 | name_list |
380 | 393 | ) |
| 394 | + |
| 395 | + # When saving heatmaps |
381 | 396 | elif output_cam_pdf and not lines_only: |
382 | 397 | plot_CAM_map( |
383 | 398 | heatmap_interpolated_list, |
384 | | - f'{output_dir}/{name_list[2]}_CAM', |
| 399 | + safe_path_noext(os.path.join(output_dir, f'{name_list[2]}_CAM')), |
385 | 400 | name_list, |
386 | 401 | True, |
387 | 402 | colorblind_friendly |
388 | 403 | ) |
389 | | - else: # both flags present |
| 404 | + |
| 405 | + # Both |
| 406 | + else: |
390 | 407 | plot_CAM_map( |
391 | 408 | heatmap_interpolated_list, |
392 | | - f'{output_dir}/{name_list[2]}_CAM', |
| 409 | + safe_path_noext(os.path.join(output_dir, f'{name_list[2]}_CAM')), |
393 | 410 | name_list, |
394 | 411 | True, |
395 | 412 | colorblind_friendly |
396 | 413 | ) |
397 | 414 | plot_CAM_lines_only( |
398 | 415 | heatmap_interpolated_list, |
399 | | - f'{output_dir}/{name_list[2]}_LINES', |
| 416 | + safe_path_noext(os.path.join(output_dir, f'{name_list[2]}_LINES')), |
400 | 417 | name_list |
401 | | - ) |
| 418 | + ) |
0 commit comments