11"""
2- 2D Image
3- ========
4-
5- Display a 2-D image with physical axes using
6- :meth:`~anyplotlib.figure_plots.Axes.imshow`.
7- The image is a synthetic STEM-like diffraction pattern with a physical
8- length scale in nanometres. Circle markers highlight the first-order
9- diffraction spots, and an annular integration widget is placed over the
10- central beam. Pan and zoom with the mouse; press **R** to reset the view,
11- **H** to toggle the histogram, **L** / **S** to cycle colour-scale modes.
2+ 2D Image with Histogram
3+ =======================
4+
5+ Display a 2-D image with physical axes, a colourmap, and an interactive
6+ histogram below — all wired together with draggable threshold widgets.
7+
8+ Layout
9+ ------
10+ A :class:`~anyplotlib.figure_plots.GridSpec` with two rows puts the image
11+ on top and a bar-chart histogram below. Two
12+ :class:`~anyplotlib.widgets.VLineWidget` handles on the histogram mark the
13+ ``display_min`` / ``display_max`` thresholds; dragging them updates the
14+ image colour scale in real time.
15+
16+ Key bindings on the image panel: **R** reset view · **C** toggle colorbar ·
17+ **L** / **S** cycle colour-scale modes.
1218"""
1319import numpy as np
14- import anyplotlib as vw
20+ import anyplotlib as apl
1521
1622
1723rng = np .random .default_rng (1 )
@@ -35,13 +41,21 @@ def _ring(r, r0, width, amp):
3541 + rng .normal (scale = 0.04 , size = (N , N ))
3642)
3743
38- # ── Plot ──────────────────────────────────────────────────────────────────────
39- fig , ax = vw .subplots (1 , 1 , figsize = (500 , 500 ))
40- v = ax .imshow (image , axes = [x , y ], units = "nm" )
44+ # ── Layout: image (top, 3×) + histogram bar chart (bottom, 1×) ────────────────
45+ gs = apl .GridSpec (2 , 1 , height_ratios = [3 , 1 ])
46+ fig = apl .Figure (figsize = (500 , 640 ))
47+ ax_img = fig .add_subplot (gs [0 , 0 ])
48+ ax_hist = fig .add_subplot (gs [1 , 0 ])
49+
50+ # ── Image panel ───────────────────────────────────────────────────────────────
51+ v = ax_img .imshow (image , axes = [x , y ], units = "nm" )
4152v .set_colormap ("inferno" )
4253
43- # ── First-order spot markers ──────────────────────────────────────────────────
44- # imshow axes are centre arrays: pixel = (phys - x[0]) / (x[1] - x[0])
54+ vmin_init = float (image .min ())
55+ vmax_init = float (image .max ())
56+ v .set_clim (vmin = vmin_init , vmax = vmax_init )
57+
58+ # First-order spot markers
4559dx = x [1 ] - x [0 ]
4660
4761
@@ -57,22 +71,39 @@ def phys_to_px(val):
5771 edgecolors = "#00e5ff" , facecolors = "#00e5ff22" ,
5872 labels = ["g1" , "g1_bar" , "g2" , "g2_bar" ])
5973
60- # ── Annular integration widget ────────────────────────────────────────────────
61- cx = cy = float (phys_to_px (0.0 ))
62- v .add_widget ("annular" , color = "#ffcc00" ,
63- cx = cx , cy = cy ,
64- r_outer = float (phys_to_px (2.8 ) - phys_to_px (0.0 )),
65- r_inner = float (phys_to_px (1.2 ) - phys_to_px (0.0 )))
74+ # ── Histogram bar chart ────────────────────────────────────────────────────────
75+ counts , edges = np .histogram (image .ravel (), bins = 64 )
76+ bin_centers = 0.5 * (edges [:- 1 ] + edges [1 :])
77+
78+ h = ax_hist .bar (counts , x_centers = bin_centers , orient = "v" ,
79+ color = "#4fc3f7" , y_units = "count" )
80+
81+ # ── Draggable threshold handles on the histogram ──────────────────────────────
82+ wlo = h .add_vline_widget (vmin_init , color = "#ff6e40" ) # low-threshold handle
83+ whi = h .add_vline_widget (vmax_init , color = "#ffffff" ) # high-threshold handle
84+
85+
86+ @wlo .on_release
87+ def _apply_low (event ):
88+ """Update image display_min when the low handle is released."""
89+ v .set_clim (vmin = event .x )
90+
91+
92+ @whi .on_release
93+ def _apply_high (event ):
94+ """Update image display_max when the high handle is released."""
95+ v .set_clim (vmax = event .x )
96+
6697
6798fig
6899
69100# %%
70- # Adjust display range and colour map
71- # ------------------------------------
72- # :meth:`~anyplotlib.figure_plots.Plot2D.set_clim` clips the colour scale ;
73- # :meth:`~anyplotlib.figure_plots.Plot2D.set_colormap` switches the palette .
101+ # Adjust colour map
102+ # ------------------
103+ # :meth:`~anyplotlib.figure_plots.Plot2D.set_colormap` switches the palette ;
104+ # :meth:`~anyplotlib.figure_plots.Plot2D.set_clim` adjusts the display range .
74105
75- v .set_clim (vmin = 0.0 , vmax = 0.8 )
76106v .set_colormap ("viridis" )
107+ v .set_clim (vmin = 0.0 , vmax = 0.8 )
77108
78109fig
0 commit comments