@@ -17,9 +17,10 @@ def output_images(state: ReconsState, out_dir: Path, options: SaveOptions):
1717 if ty not in _SAVE_FUNCS :
1818 raise ValueError (f"Unknown image type '{ ty } '" )
1919
20+ ext = options .plot_ext if ty in _PLOT_FUNCS else 'tiff'
2021 try :
2122 out_name = options .img_fmt .format (
22- type = ty , iter = state .iter ,
23+ type = ty , iter = state .iter , ext = ext
2324 )
2425 out_path = out_dir / out_name
2526 except KeyError as e :
@@ -175,6 +176,60 @@ def _save_object_mag(state: ReconsState, out_path: Path, options: SaveOptions, s
175176 w .write (obj_mag , ** write_opts )
176177
177178
179+ def _plot_scan (state : ReconsState , out_path : Path , options : SaveOptions ):
180+ from matplotlib import pyplot
181+ fig , ax = pyplot .subplots (figsize = (4 , 4 ), dpi = options .plot_dpi , constrained_layout = True )
182+
183+ ax .set_aspect (1. )
184+ [l , r , b , t ] = state .object .sampling .mpl_extent ()
185+ ax .set_xlim (l , r )
186+ ax .set_ylim (b , t )
187+
188+ scan = to_numpy (state .scan )
189+ i = numpy .arange (scan [..., 0 ].size )
190+ ax .scatter (scan [..., 1 ].ravel (), scan [..., 0 ].ravel (), c = i , s = 0.2 , cmap = 'plasma' )
191+
192+ fig .savefig (out_path )
193+ pyplot .close (fig )
194+
195+
196+ def _plot_tilt (state : ReconsState , out_path : Path , options : SaveOptions ):
197+ from matplotlib import pyplot
198+
199+ fig , ax = pyplot .subplots (figsize = (4 , 4 ), dpi = options .plot_dpi , constrained_layout = True )
200+
201+ ax .set_aspect (1. )
202+ [l , r , b , t ] = state .object .sampling .mpl_extent ()
203+ ax .set_xlim (l , r )
204+ ax .set_ylim (b , t )
205+
206+ scan = to_numpy (state .scan )
207+ tilt = to_numpy (state .tilt )
208+ tilt = tilt [..., 1 ] + tilt [..., 0 ]* 1.j
209+ max_tilt = max (numpy .max (numpy .abs (tilt )), 1.0 ) # at least 1 mrad
210+ c = colorize_complex (tilt / max_tilt , amp = True , rescale = False )
211+ ax .scatter (scan [..., 1 ].ravel (), scan [..., 0 ].ravel (), c = c , s = 0.2 )
212+
213+ fig .draw_without_rendering ()
214+ trans = ax .transAxes + fig .transFigure .inverted ()
215+ legend_ax_max = trans .transform ([0.95 , 0.02 ])
216+ legend_ax_size = (0.1 , 0.1 )
217+ legend_ax = fig .add_axes ((legend_ax_max [0 ] - legend_ax_size [0 ], legend_ax_max [1 ], * legend_ax_size ), projection = 'polar' )
218+
219+ legend_ax .set_rmax (max_tilt ) # type: ignore
220+ legend_ax .set_theta_direction (- 1 ) # type: ignore
221+ legend_ax .set_axis_off ()
222+
223+ thetas = numpy .linspace (0. , 2 * numpy .pi , 70 )
224+ rs = numpy .concatenate ([[0.0 ], numpy .geomspace (0.1 , 1.0 , 30 )])
225+ rr , tt = numpy .meshgrid (rs , thetas , indexing = 'ij' )
226+ c2 = colorize_complex (rr * numpy .exp (1.j * tt ), rescale = False )
227+ legend_ax .pcolormesh (tt , rr * max_tilt , c2 )
228+ legend_ax .text (- numpy .pi / 2. , max_tilt * 1.05 , f"{ max_tilt :.1f} mrad" , ha = 'center' , va = 'bottom' , size = 'small' )
229+
230+ fig .savefig (out_path )
231+ pyplot .close (fig )
232+
178233
179234_SAVE_FUNCS : t .Dict [str , t .Callable [[ReconsState , Path , SaveOptions ], t .Any ]] = {
180235 'probe' : _save_probe ,
@@ -185,4 +240,8 @@ def _save_object_mag(state: ReconsState, out_path: Path, options: SaveOptions, s
185240 'object_phase_sum' : partial (_save_object_phase , stack = False ),
186241 'object_mag_stack' : partial (_save_object_mag , stack = True ),
187242 'object_mag_sum' : partial (_save_object_mag , stack = False ),
188- }
243+ 'scan' : _plot_scan ,
244+ 'tilt' : _plot_tilt ,
245+ }
246+ # save functions with special handling of file extensions
247+ _PLOT_FUNCS : t .Set [str ] = {'scan' , 'tilt' }
0 commit comments