figrecipe 0.5.0__py3-none-any.whl → 0.6.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (90) hide show
  1. figrecipe/__init__.py +361 -93
  2. figrecipe/_dev/__init__.py +120 -0
  3. figrecipe/_dev/demo_plotters/__init__.py +195 -0
  4. figrecipe/_dev/demo_plotters/plot_acorr.py +24 -0
  5. figrecipe/_dev/demo_plotters/plot_angle_spectrum.py +28 -0
  6. figrecipe/_dev/demo_plotters/plot_bar.py +25 -0
  7. figrecipe/_dev/demo_plotters/plot_barbs.py +30 -0
  8. figrecipe/_dev/demo_plotters/plot_barh.py +25 -0
  9. figrecipe/_dev/demo_plotters/plot_boxplot.py +24 -0
  10. figrecipe/_dev/demo_plotters/plot_cohere.py +29 -0
  11. figrecipe/_dev/demo_plotters/plot_contour.py +30 -0
  12. figrecipe/_dev/demo_plotters/plot_contourf.py +29 -0
  13. figrecipe/_dev/demo_plotters/plot_csd.py +29 -0
  14. figrecipe/_dev/demo_plotters/plot_ecdf.py +24 -0
  15. figrecipe/_dev/demo_plotters/plot_errorbar.py +28 -0
  16. figrecipe/_dev/demo_plotters/plot_eventplot.py +25 -0
  17. figrecipe/_dev/demo_plotters/plot_fill.py +29 -0
  18. figrecipe/_dev/demo_plotters/plot_fill_between.py +30 -0
  19. figrecipe/_dev/demo_plotters/plot_fill_betweenx.py +28 -0
  20. figrecipe/_dev/demo_plotters/plot_hexbin.py +25 -0
  21. figrecipe/_dev/demo_plotters/plot_hist.py +24 -0
  22. figrecipe/_dev/demo_plotters/plot_hist2d.py +25 -0
  23. figrecipe/_dev/demo_plotters/plot_imshow.py +23 -0
  24. figrecipe/_dev/demo_plotters/plot_loglog.py +27 -0
  25. figrecipe/_dev/demo_plotters/plot_magnitude_spectrum.py +28 -0
  26. figrecipe/_dev/demo_plotters/plot_matshow.py +23 -0
  27. figrecipe/_dev/demo_plotters/plot_pcolor.py +29 -0
  28. figrecipe/_dev/demo_plotters/plot_pcolormesh.py +29 -0
  29. figrecipe/_dev/demo_plotters/plot_phase_spectrum.py +28 -0
  30. figrecipe/_dev/demo_plotters/plot_pie.py +23 -0
  31. figrecipe/_dev/demo_plotters/plot_plot.py +27 -0
  32. figrecipe/_dev/demo_plotters/plot_psd.py +29 -0
  33. figrecipe/_dev/demo_plotters/plot_quiver.py +30 -0
  34. figrecipe/_dev/demo_plotters/plot_scatter.py +24 -0
  35. figrecipe/_dev/demo_plotters/plot_semilogx.py +27 -0
  36. figrecipe/_dev/demo_plotters/plot_semilogy.py +27 -0
  37. figrecipe/_dev/demo_plotters/plot_specgram.py +30 -0
  38. figrecipe/_dev/demo_plotters/plot_spy.py +29 -0
  39. figrecipe/_dev/demo_plotters/plot_stackplot.py +29 -0
  40. figrecipe/_dev/demo_plotters/plot_stairs.py +27 -0
  41. figrecipe/_dev/demo_plotters/plot_stem.py +27 -0
  42. figrecipe/_dev/demo_plotters/plot_step.py +27 -0
  43. figrecipe/_dev/demo_plotters/plot_streamplot.py +30 -0
  44. figrecipe/_dev/demo_plotters/plot_tricontour.py +28 -0
  45. figrecipe/_dev/demo_plotters/plot_tricontourf.py +28 -0
  46. figrecipe/_dev/demo_plotters/plot_tripcolor.py +29 -0
  47. figrecipe/_dev/demo_plotters/plot_triplot.py +25 -0
  48. figrecipe/_dev/demo_plotters/plot_violinplot.py +25 -0
  49. figrecipe/_dev/demo_plotters/plot_xcorr.py +25 -0
  50. figrecipe/_editor/__init__.py +230 -0
  51. figrecipe/_editor/_bbox.py +978 -0
  52. figrecipe/_editor/_flask_app.py +1229 -0
  53. figrecipe/_editor/_hitmap.py +937 -0
  54. figrecipe/_editor/_overrides.py +318 -0
  55. figrecipe/_editor/_renderer.py +349 -0
  56. figrecipe/_editor/_templates/__init__.py +75 -0
  57. figrecipe/_editor/_templates/_html.py +406 -0
  58. figrecipe/_editor/_templates/_scripts.py +2778 -0
  59. figrecipe/_editor/_templates/_styles.py +1326 -0
  60. figrecipe/_params/_DECORATION_METHODS.py +27 -0
  61. figrecipe/_params/_PLOTTING_METHODS.py +58 -0
  62. figrecipe/_params/__init__.py +9 -0
  63. figrecipe/_recorder.py +126 -73
  64. figrecipe/_reproducer.py +658 -41
  65. figrecipe/_seaborn.py +14 -9
  66. figrecipe/_serializer.py +2 -2
  67. figrecipe/_signatures/README.md +68 -0
  68. figrecipe/_signatures/__init__.py +12 -2
  69. figrecipe/_signatures/_loader.py +515 -56
  70. figrecipe/_utils/__init__.py +6 -4
  71. figrecipe/_utils/_crop.py +10 -4
  72. figrecipe/_utils/_image_diff.py +37 -33
  73. figrecipe/_utils/_numpy_io.py +0 -1
  74. figrecipe/_utils/_units.py +11 -3
  75. figrecipe/_validator.py +12 -3
  76. figrecipe/_wrappers/_axes.py +860 -46
  77. figrecipe/_wrappers/_figure.py +115 -18
  78. figrecipe/plt.py +0 -1
  79. figrecipe/pyplot.py +2 -1
  80. figrecipe/styles/__init__.py +9 -10
  81. figrecipe/styles/_style_applier.py +332 -28
  82. figrecipe/styles/_style_loader.py +172 -44
  83. figrecipe/styles/presets/MATPLOTLIB.yaml +94 -0
  84. figrecipe/styles/presets/SCITEX.yaml +176 -0
  85. figrecipe-0.6.0.dist-info/METADATA +394 -0
  86. figrecipe-0.6.0.dist-info/RECORD +90 -0
  87. figrecipe-0.5.0.dist-info/METADATA +0 -336
  88. figrecipe-0.5.0.dist-info/RECORD +0 -26
  89. {figrecipe-0.5.0.dist-info → figrecipe-0.6.0.dist-info}/WHEEL +0 -0
  90. {figrecipe-0.5.0.dist-info → figrecipe-0.6.0.dist-info}/licenses/LICENSE +0 -0
@@ -18,6 +18,7 @@ Usage:
18
18
 
19
19
  __all__ = [
20
20
  "load_style",
21
+ "load_preset",
21
22
  "unload_style",
22
23
  "get_style",
23
24
  "reload_style",
@@ -31,7 +32,6 @@ from typing import Any, Dict, List, Optional, Union
31
32
 
32
33
  from ruamel.yaml import YAML
33
34
 
34
-
35
35
  # Path to presets directory
36
36
  _PRESETS_DIR = Path(__file__).parent / "presets"
37
37
 
@@ -82,7 +82,7 @@ class DotDict(dict):
82
82
 
83
83
  def __getattr__(self, key: str) -> Any:
84
84
  # Handle special methods first
85
- if key == 'to_subplots_kwargs':
85
+ if key == "to_subplots_kwargs":
86
86
  return lambda: to_subplots_kwargs(self)
87
87
  try:
88
88
  value = self[key]
@@ -172,17 +172,18 @@ def _apply_dark_theme(style_dict: Dict) -> Dict:
172
172
  Style dictionary with dark theme applied
173
173
  """
174
174
  import copy
175
+
175
176
  result = copy.deepcopy(style_dict)
176
177
 
177
178
  # Monaco/VS Code dark theme colors (from scitex-cloud UIUX.md)
178
179
  dark_colors = {
179
- "figure_bg": "#1e1e1e", # VS Code main background
180
- "axes_bg": "#1e1e1e", # Same as figure background
181
- "legend_bg": "#1e1e1e", # Same as figure background
182
- "text": "#d4d4d4", # VS Code default text
183
- "spine": "#3c3c3c", # Subtle border color
184
- "tick": "#d4d4d4", # Match text
185
- "grid": "#3a3a3a", # Subtle grid
180
+ "figure_bg": "#1e1e1e", # VS Code main background
181
+ "axes_bg": "#1e1e1e", # Same as figure background
182
+ "legend_bg": "#1e1e1e", # Same as figure background
183
+ "text": "#d4d4d4", # VS Code default text
184
+ "spine": "#3c3c3c", # Subtle border color
185
+ "tick": "#d4d4d4", # Match text
186
+ "grid": "#3a3a3a", # Subtle grid
186
187
  }
187
188
 
188
189
  # Update theme section
@@ -198,6 +199,43 @@ def _apply_dark_theme(style_dict: Dict) -> Dict:
198
199
  return result
199
200
 
200
201
 
202
+ def load_preset(name: str, dark: bool = False) -> Optional[DotDict]:
203
+ """Load a style preset without affecting global cache.
204
+
205
+ This is useful for GUI editors that need to switch themes
206
+ without affecting the global state.
207
+
208
+ Parameters
209
+ ----------
210
+ name : str
211
+ Preset name (e.g., "SCITEX", "MATPLOTLIB")
212
+ dark : bool, optional
213
+ If True, apply dark theme transformation
214
+
215
+ Returns
216
+ -------
217
+ DotDict or None
218
+ Style configuration as DotDict, or None if not found
219
+ """
220
+ # Resolve aliases
221
+ resolved_name = _PRESET_ALIASES.get(name.upper(), name.upper())
222
+
223
+ # Find the preset file
224
+ style_path = _PRESETS_DIR / f"{resolved_name}.yaml"
225
+
226
+ if not style_path.exists():
227
+ return None
228
+
229
+ style_dict = _load_yaml(style_path)
230
+ style_dict["_name"] = name.upper()
231
+
232
+ # Apply dark theme if requested
233
+ if dark:
234
+ style_dict = _apply_dark_theme(style_dict)
235
+
236
+ return DotDict(style_dict)
237
+
238
+
201
239
  def unload_style() -> None:
202
240
  """Unload the current style and reset to matplotlib defaults.
203
241
 
@@ -218,10 +256,13 @@ def unload_style() -> None:
218
256
 
219
257
  # Reset matplotlib rcParams to defaults
220
258
  import matplotlib as mpl
259
+
221
260
  mpl.rcParams.update(mpl.rcParamsDefault)
222
261
 
223
262
 
224
- def load_style(style: Optional[Union[str, Path, bool]] = "SCITEX", dark: bool = False) -> Optional[DotDict]:
263
+ def load_style(
264
+ style: Optional[Union[str, Path, bool]] = "SCITEX", dark: bool = False
265
+ ) -> Optional[DotDict]:
225
266
  """Load style configuration from preset or YAML file.
226
267
 
227
268
  Parameters
@@ -294,7 +335,14 @@ def load_style(style: Optional[Union[str, Path, bool]] = "SCITEX", dark: bool =
294
335
  resolved_style = base_style
295
336
 
296
337
  # Determine the style path
297
- if isinstance(resolved_style, Path) or (isinstance(resolved_style, str) and ("/" in resolved_style or "\\" in resolved_style or resolved_style.endswith(".yaml"))):
338
+ if isinstance(resolved_style, Path) or (
339
+ isinstance(resolved_style, str)
340
+ and (
341
+ "/" in resolved_style
342
+ or "\\" in resolved_style
343
+ or resolved_style.endswith(".yaml")
344
+ )
345
+ ):
298
346
  # Explicit file path
299
347
  style_path = Path(resolved_style)
300
348
  style_name = str(resolved_style)
@@ -346,6 +394,9 @@ def get_style() -> DotDict:
346
394
  def to_subplots_kwargs(style: Optional[DotDict] = None) -> Dict[str, Any]:
347
395
  """Convert style DotDict to kwargs for ps.subplots().
348
396
 
397
+ Uses YAML-compatible flattened key names as the single source of truth.
398
+ For example, YAML `fonts.axis_label_pt` becomes `fonts_axis_label_pt`.
399
+
349
400
  Parameters
350
401
  ----------
351
402
  style : DotDict, optional
@@ -354,7 +405,7 @@ def to_subplots_kwargs(style: Optional[DotDict] = None) -> Dict[str, Any]:
354
405
  Returns
355
406
  -------
356
407
  dict
357
- Keyword arguments for ps.subplots()
408
+ Keyword arguments for ps.subplots() with YAML-compatible flattened keys.
358
409
 
359
410
  Examples
360
411
  --------
@@ -365,42 +416,75 @@ def to_subplots_kwargs(style: Optional[DotDict] = None) -> Dict[str, Any]:
365
416
  if style is None:
366
417
  style = get_style()
367
418
 
419
+ # YAML-compatible flattened keys (single source of truth)
368
420
  result = {
369
- # Axes dimensions
421
+ # Axes (axes.* in YAML)
370
422
  "axes_width_mm": style.axes.width_mm,
371
423
  "axes_height_mm": style.axes.height_mm,
372
424
  "axes_thickness_mm": style.axes.thickness_mm,
373
- # Margins
374
- "margin_left_mm": style.margins.left_mm,
375
- "margin_right_mm": style.margins.right_mm,
376
- "margin_bottom_mm": style.margins.bottom_mm,
377
- "margin_top_mm": style.margins.top_mm,
378
- # Spacing
379
- "space_w_mm": style.spacing.horizontal_mm,
380
- "space_h_mm": style.spacing.vertical_mm,
381
- # Ticks
382
- "tick_length_mm": style.ticks.length_mm,
383
- "tick_thickness_mm": style.ticks.thickness_mm,
384
- "n_ticks": style.ticks.n_ticks,
385
- # Lines
386
- "trace_thickness_mm": style.lines.trace_mm,
387
- # Markers
388
- "marker_size_mm": style.markers.size_mm,
389
- # Fonts
390
- "font_family": style.fonts.family,
391
- "axis_font_size_pt": style.fonts.axis_label_pt,
392
- "tick_font_size_pt": style.fonts.tick_label_pt,
393
- "title_font_size_pt": style.fonts.title_pt,
394
- "suptitle_font_size_pt": style.fonts.suptitle_pt,
395
- "legend_font_size_pt": style.fonts.legend_pt,
396
- # Padding
397
- "label_pad_pt": style.padding.label_pt,
398
- "tick_pad_pt": style.padding.tick_pt,
399
- "title_pad_pt": style.padding.title_pt,
400
- # Output
401
- "dpi": style.output.dpi,
402
- # Theme
403
- "theme": style.theme.mode,
425
+ # Margins (margins.* in YAML)
426
+ "margins_left_mm": style.margins.left_mm,
427
+ "margins_right_mm": style.margins.right_mm,
428
+ "margins_bottom_mm": style.margins.bottom_mm,
429
+ "margins_top_mm": style.margins.top_mm,
430
+ # Spacing (spacing.* in YAML)
431
+ "spacing_horizontal_mm": style.spacing.horizontal_mm,
432
+ "spacing_vertical_mm": style.spacing.vertical_mm,
433
+ # Ticks (ticks.* in YAML)
434
+ "ticks_length_mm": style.ticks.length_mm,
435
+ "ticks_thickness_mm": style.ticks.thickness_mm,
436
+ "ticks_direction": style.ticks.get("direction", "out"),
437
+ "ticks_n_ticks": style.ticks.n_ticks,
438
+ # Lines (lines.* in YAML)
439
+ "lines_trace_mm": style.lines.trace_mm,
440
+ "lines_errorbar_mm": style.lines.get("errorbar_mm", 0.2),
441
+ "lines_errorbar_cap_mm": style.lines.get("errorbar_cap_mm", 0.8),
442
+ # Markers (markers.* in YAML)
443
+ "markers_size_mm": style.markers.size_mm,
444
+ "markers_scatter_mm": style.markers.get("scatter_mm", style.markers.size_mm),
445
+ "markers_flier_mm": style.markers.get("flier_mm", style.markers.size_mm),
446
+ "markers_edge_width_mm": style.markers.get("edge_width_mm"),
447
+ # Boxplot (boxplot.* in YAML)
448
+ "boxplot_line_mm": style.get("boxplot", {}).get("line_mm", 0.2),
449
+ "boxplot_whisker_mm": style.get("boxplot", {}).get("whisker_mm", 0.2),
450
+ "boxplot_cap_mm": style.get("boxplot", {}).get("cap_mm", 0.2),
451
+ "boxplot_median_mm": style.get("boxplot", {}).get("median_mm", 0.2),
452
+ "boxplot_median_color": style.get("boxplot", {}).get("median_color", "black"),
453
+ "boxplot_flier_edge_mm": style.get("boxplot", {}).get("flier_edge_mm", 0.2),
454
+ # Violinplot (violinplot.* in YAML)
455
+ "violinplot_line_mm": style.get("violinplot", {}).get("line_mm", 0.2),
456
+ "violinplot_inner": style.get("violinplot", {}).get("inner", "box"),
457
+ "violinplot_box_width_mm": style.get("violinplot", {}).get("box_width_mm", 1.5),
458
+ "violinplot_whisker_mm": style.get("violinplot", {}).get("whisker_mm", 0.2),
459
+ "violinplot_median_mm": style.get("violinplot", {}).get("median_mm", 0.8),
460
+ # Barplot (barplot.* in YAML)
461
+ "barplot_edge_mm": style.get("barplot", {}).get("edge_mm", 0.2),
462
+ # Histogram (histogram.* in YAML)
463
+ "histogram_edge_mm": style.get("histogram", {}).get("edge_mm", 0.2),
464
+ # Pie chart (pie.* in YAML)
465
+ "pie_text_pt": style.get("pie", {}).get("text_pt", 6),
466
+ "pie_show_axes": style.get("pie", {}).get("show_axes", False),
467
+ # Imshow (imshow.* in YAML)
468
+ "imshow_show_axes": style.get("imshow", {}).get("show_axes", False),
469
+ "imshow_show_labels": style.get("imshow", {}).get("show_labels", False),
470
+ # Fonts (fonts.* in YAML)
471
+ "fonts_family": style.fonts.family,
472
+ "fonts_axis_label_pt": style.fonts.axis_label_pt,
473
+ "fonts_tick_label_pt": style.fonts.tick_label_pt,
474
+ "fonts_title_pt": style.fonts.title_pt,
475
+ "fonts_suptitle_pt": style.fonts.suptitle_pt,
476
+ "fonts_legend_pt": style.fonts.legend_pt,
477
+ "fonts_annotation_pt": style.fonts.get("annotation_pt", 6),
478
+ # Padding (padding.* in YAML)
479
+ "padding_label_pt": style.padding.label_pt,
480
+ "padding_tick_pt": style.padding.tick_pt,
481
+ "padding_title_pt": style.padding.title_pt,
482
+ # Output (output.* in YAML)
483
+ "output_dpi": style.output.dpi,
484
+ "output_transparent": style.output.get("transparent", True),
485
+ "output_format": style.output.get("format", "pdf"),
486
+ # Theme (theme.* in YAML)
487
+ "theme_mode": style.theme.mode,
404
488
  }
405
489
 
406
490
  # Add theme colors from preset if available
@@ -412,6 +496,50 @@ def to_subplots_kwargs(style: Optional[DotDict] = None) -> Dict[str, Any]:
412
496
  if "colors" in style and "palette" in style.colors:
413
497
  result["color_palette"] = list(style.colors.palette)
414
498
 
499
+ # Add behavior settings (behavior.* in YAML)
500
+ if "behavior" in style:
501
+ behavior = style.behavior
502
+ if hasattr(behavior, "hide_top_spine"):
503
+ result["behavior_hide_top_spine"] = behavior.hide_top_spine
504
+ if hasattr(behavior, "hide_right_spine"):
505
+ result["behavior_hide_right_spine"] = behavior.hide_right_spine
506
+ if hasattr(behavior, "grid"):
507
+ result["behavior_grid"] = behavior.grid
508
+ if hasattr(behavior, "auto_scale_axes"):
509
+ result["behavior_auto_scale_axes"] = behavior.auto_scale_axes
510
+ if hasattr(behavior, "constrained_layout"):
511
+ result["behavior_constrained_layout"] = behavior.constrained_layout
512
+
513
+ # Legacy key aliases for backwards compatibility
514
+ # (These allow existing code using old keys to still work)
515
+ result["margin_left_mm"] = result["margins_left_mm"]
516
+ result["margin_right_mm"] = result["margins_right_mm"]
517
+ result["margin_bottom_mm"] = result["margins_bottom_mm"]
518
+ result["margin_top_mm"] = result["margins_top_mm"]
519
+ result["space_w_mm"] = result["spacing_horizontal_mm"]
520
+ result["space_h_mm"] = result["spacing_vertical_mm"]
521
+ result["tick_length_mm"] = result["ticks_length_mm"]
522
+ result["tick_thickness_mm"] = result["ticks_thickness_mm"]
523
+ result["n_ticks"] = result["ticks_n_ticks"]
524
+ result["trace_thickness_mm"] = result["lines_trace_mm"]
525
+ result["marker_size_mm"] = result["markers_size_mm"]
526
+ result["font_family"] = result["fonts_family"]
527
+ result["axis_font_size_pt"] = result["fonts_axis_label_pt"]
528
+ result["tick_font_size_pt"] = result["fonts_tick_label_pt"]
529
+ result["title_font_size_pt"] = result["fonts_title_pt"]
530
+ result["suptitle_font_size_pt"] = result["fonts_suptitle_pt"]
531
+ result["legend_font_size_pt"] = result["fonts_legend_pt"]
532
+ result["label_pad_pt"] = result["padding_label_pt"]
533
+ result["tick_pad_pt"] = result["padding_tick_pt"]
534
+ result["title_pad_pt"] = result["padding_title_pt"]
535
+ result["dpi"] = result["output_dpi"]
536
+ result["theme"] = result["theme_mode"]
537
+ result["hide_top_spine"] = result.get("behavior_hide_top_spine", True)
538
+ result["hide_right_spine"] = result.get("behavior_hide_right_spine", True)
539
+ result["grid"] = result.get("behavior_grid", False)
540
+ result["auto_scale_axes"] = result.get("behavior_auto_scale_axes", True)
541
+ result["constrained_layout"] = result.get("behavior_constrained_layout", False)
542
+
415
543
  return result
416
544
 
417
545
 
@@ -0,0 +1,94 @@
1
+ # Timestamp: "2025-12-22 13:49:42 (ywatanabe)"
2
+ # File: ./src/figrecipe/styles/presets/MATPLOTLIB.yaml
3
+ # MATPLOTLIB Style Preset
4
+ # =======================
5
+ # Vanilla matplotlib defaults - minimal customization.
6
+ # Use this to reset to standard matplotlib behavior.
7
+
8
+ axes:
9
+ width_mm: null # Use matplotlib default (auto)
10
+ height_mm: null # Use matplotlib default (auto)
11
+ thickness_mm: null # Use matplotlib default
12
+
13
+ margins:
14
+ left_mm: null
15
+ right_mm: null
16
+ bottom_mm: null
17
+ top_mm: null
18
+
19
+ spacing:
20
+ horizontal_mm: null
21
+ vertical_mm: null
22
+
23
+ fonts:
24
+ family: null # matplotlib default (DejaVu Sans)
25
+ axis_label_pt: null
26
+ tick_label_pt: null
27
+ title_pt: null
28
+ suptitle_pt: null
29
+ legend_pt: null
30
+ annotation_pt: null
31
+
32
+ padding:
33
+ label_pt: null
34
+ tick_pt: null
35
+ title_pt: null
36
+
37
+ lines:
38
+ trace_mm: null
39
+ errorbar_mm: null
40
+ errorbar_cap_mm: null
41
+
42
+ ticks:
43
+ length_mm: null
44
+ thickness_mm: null
45
+ direction: null
46
+ n_ticks: null
47
+
48
+ markers:
49
+ size_mm: null
50
+ scatter_mm: null
51
+ edge_width_mm: null
52
+
53
+ legend:
54
+ frameon: null # matplotlib default (True)
55
+ bg: null # matplotlib default
56
+ edgecolor: null # matplotlib default
57
+ alpha: null # matplotlib default
58
+ loc: null # matplotlib default
59
+
60
+ output:
61
+ dpi: 300
62
+ transparent: false
63
+ format: "png"
64
+
65
+ behavior:
66
+ auto_scale_axes: false
67
+ hide_top_spine: false
68
+ hide_right_spine: false
69
+ grid: false
70
+
71
+ theme:
72
+ mode: "light"
73
+ dark:
74
+ figure_bg: "#1e1e1e"
75
+ axes_bg: "#1e1e1e"
76
+ legend_bg: "#1e1e1e"
77
+ text: "#d4d4d4"
78
+ spine: "#d4d4d4"
79
+ tick: "#d4d4d4"
80
+ grid: "#3a3a3a"
81
+ light:
82
+ figure_bg: "white"
83
+ axes_bg: "white"
84
+ legend_bg: "white"
85
+ text: "black"
86
+ spine: "black"
87
+ tick: "black"
88
+ grid: "#cccccc"
89
+
90
+ # Colors: Use matplotlib default (tab10)
91
+ colors:
92
+ palette: null
93
+
94
+ # EOF
@@ -0,0 +1,176 @@
1
+ # Timestamp: "2025-12-22 13:49:08 (ywatanabe)"
2
+ # File: ./src/figrecipe/styles/presets/SCITEX.yaml
3
+ # FIGRECIPE Style Preset
4
+ # ======================
5
+ # Publication-quality settings for scientific figures.
6
+ # Optimized for scientific journals with Arial font.
7
+
8
+ axes:
9
+ width_mm: 40
10
+ height_mm: 28
11
+ thickness_mm: 0.2
12
+
13
+ margins:
14
+ left_mm: 6 # Room for supylabel
15
+ right_mm: 1
16
+ bottom_mm: 5 # Room for supxlabel
17
+ top_mm: 5 # Room for suptitle
18
+
19
+ spacing:
20
+ horizontal_mm: 10 # Between columns
21
+ vertical_mm: 15 # Between rows (includes title + xlabel space)
22
+ suptitle_mm: 5 # Space reserved for figure suptitle
23
+ supxlabel_mm: 3 # Space reserved for figure super x-label
24
+ supylabel_mm: 3 # Space reserved for figure super y-label
25
+
26
+ fonts:
27
+ family: "Arial"
28
+ axis_label_pt: 7
29
+ tick_label_pt: 7
30
+ title_pt: 8
31
+ suptitle_pt: 9 # Figure suptitle (slightly larger than subplot titles)
32
+ supxlabel_pt: 7 # Figure-level x-label (same as axis labels)
33
+ supylabel_pt: 7 # Figure-level y-label (same as axis labels)
34
+ panel_label_pt: 10 # Panel labels (A, B, C, ...) - bold, prominent
35
+ legend_pt: 6
36
+ annotation_pt: 6
37
+
38
+ padding:
39
+ label_pt: 2.0
40
+ tick_pt: 2.0
41
+ title_pt: 4.0
42
+
43
+ lines:
44
+ trace_mm: 0.2
45
+ errorbar_mm: 0.2
46
+ errorbar_cap_mm: 0.8
47
+
48
+ ticks:
49
+ length_mm: 0.8
50
+ thickness_mm: 0.2
51
+ direction: "out"
52
+ n_ticks: 4
53
+
54
+ markers:
55
+ size_mm: 0.8
56
+ scatter_mm: 0.8
57
+ flier_mm: 0.8 # Boxplot outlier marker size
58
+ edge_width_mm: null # None = no border (cleaner than 0)
59
+
60
+ boxplot:
61
+ line_mm: 0.2 # Box outline thickness
62
+ whisker_mm: 0.2 # Whisker line thickness
63
+ cap_mm: 0.2 # Cap line thickness
64
+ median_mm: 0.2 # Median line thickness
65
+ median_color: "black" # Median line color
66
+ flier_edge_mm: 0.2 # Outlier marker edge thickness
67
+
68
+ violinplot:
69
+ line_mm: 0.2 # Violin outline thickness
70
+ inner: "box" # Inner display: "box", "quartile", "point", "stick", or "swarm"
71
+ box_width_mm: 1.5 # Inner box width
72
+ whisker_mm: 0.2 # Whisker line thickness
73
+ median_mm: 0.8 # Median marker size
74
+ alpha: 0.7 # Violin fill transparency (modern: semi-transparent)
75
+ showmeans: false # Show mean line
76
+ showmedians: true # Show median line
77
+ showextrema: false # Hide min/max lines for cleaner look
78
+
79
+ barplot:
80
+ edge_mm: 0.2 # Bar edge/border thickness
81
+
82
+ histogram:
83
+ edge_mm: 0.2 # Histogram bar edge thickness
84
+
85
+ pie:
86
+ text_pt: 6 # Pie chart text size (labels, autopct)
87
+ show_axes: false # Hide axes for pie charts
88
+
89
+ imshow:
90
+ show_axes: false # Hide ticks, ticklabels, spines for imshow
91
+ show_labels: false # Hide x/y labels for imshow
92
+
93
+ eventplot:
94
+ linewidth_mm: 0.2 # Event line thickness
95
+ linelength: 0.8 # Event line length (fraction of spacing)
96
+
97
+ matshow:
98
+ show_axes: false # Hide axes for matrix display
99
+ xticklabel_position: "bottom" # Put xlabels at bottom (not top)
100
+
101
+ spy:
102
+ show_axes: false # Hide axes for spy plots
103
+ xticklabel_position: "bottom" # Put xlabels at bottom
104
+
105
+ legend:
106
+ frameon: false # No frame for clean look
107
+ bg: null # Background (null = use theme.legend_bg)
108
+ edgecolor: null # Frame edge color
109
+ alpha: 1.0 # Transparency
110
+ loc: "best"
111
+
112
+ output:
113
+ dpi: 300
114
+ transparent: true
115
+ format: "pdf"
116
+
117
+ behavior:
118
+ auto_scale_axes: true
119
+ hide_top_spine: true
120
+ hide_right_spine: true
121
+ grid: false
122
+ constrained_layout: true # Auto-spacing for suptitle/supxlabel/supylabel
123
+
124
+ theme:
125
+ mode: "light"
126
+ dark:
127
+ figure_bg: "transparent"
128
+ axes_bg: "transparent"
129
+ legend_bg: "transparent"
130
+ text: "#d4d4d4"
131
+ spine: "#d4d4d4"
132
+ tick: "#d4d4d4"
133
+ grid: "#3a3a3a"
134
+ light:
135
+ figure_bg: "transparent"
136
+ axes_bg: "transparent"
137
+ legend_bg: "transparent"
138
+ text: "black"
139
+ spine: "black"
140
+ tick: "black"
141
+ grid: "#cccccc"
142
+
143
+ # SciTeX Color Palette (RGB format)
144
+ colors:
145
+ palette:
146
+ - [0, 128, 192] # blue
147
+ - [255, 70, 50] # red
148
+ - [20, 180, 20] # green
149
+ - [230, 160, 20] # yellow
150
+ - [200, 50, 255] # purple
151
+ - [20, 200, 200] # lightblue
152
+ - [228, 94, 50] # orange
153
+ - [255, 150, 200] # pink
154
+
155
+ # Named colors
156
+ white: [255, 255, 255]
157
+ black: [0, 0, 0]
158
+ blue: [0, 128, 192]
159
+ red: [255, 70, 50]
160
+ pink: [255, 150, 200]
161
+ green: [20, 180, 20]
162
+ yellow: [230, 160, 20]
163
+ gray: [128, 128, 128]
164
+ grey: [128, 128, 128]
165
+ purple: [200, 50, 255]
166
+ lightblue: [20, 200, 200]
167
+ brown: [128, 0, 0]
168
+ navy: [0, 0, 100]
169
+ orange: [228, 94, 50]
170
+
171
+ # Semantic
172
+ primary: [0, 128, 192]
173
+ secondary: [255, 70, 50]
174
+ accent: [20, 180, 20]
175
+
176
+ # EOF