1212from RATapi .rat_core import PlotEventData , makeSLDProfileXY
1313
1414
15- class Figure :
16- """Creates a plotting figure."""
17-
18- def __init__ (self , row : int = 1 , col : int = 1 ):
19- """Initializes the figure and the subplots.
20-
21- Parameters
22- ----------
23- row : int, default: 1
24- The number of rows in subplot
25- col : int, default: 1
26- The number of columns in subplot
27-
28- """
29- self ._fig , self ._ax = plt .subplots (row , col , num = "Reflectivity Algorithms Toolbox (RAT)" )
30- plt .show (block = False )
31- self ._esc_pressed = False
32- self ._close_clicked = False
33- self ._fig .canvas .mpl_connect ("key_press_event" , self ._process_button_press )
34- self ._fig .canvas .mpl_connect ("close_event" , self ._close )
35-
36- def wait_for_close (self ):
37- """Waits for the user to close the figure
38- using the esc key.
39- """
40- while not (self ._esc_pressed or self ._close_clicked ):
41- plt .waitforbuttonpress (timeout = 0.005 )
42- plt .close (self ._fig )
43-
44- def _process_button_press (self , event ):
45- """Process the key_press_event."""
46- if event .key == "escape" :
47- self ._esc_pressed = True
48-
49- def _close (self , _ ):
50- """Process the close_event."""
51- self ._close_clicked = True
52-
53-
5415def plot_errorbars (ax : Axes , x : np .ndarray , y : np .ndarray , err : np .ndarray , one_sided : bool , color : str ):
5516 """Plots the error bars.
5617
@@ -75,33 +36,39 @@ def plot_errorbars(ax: Axes, x: np.ndarray, y: np.ndarray, err: np.ndarray, one_
7536 ax .scatter (x = x , y = y , s = 3 , marker = "o" , color = color )
7637
7738
78- def plot_ref_sld_helper (data : PlotEventData , fig : Optional [Figure ] = None , delay : bool = True ):
39+ def plot_ref_sld_helper (data : PlotEventData , fig : Optional [plt . figure ] = None , delay : bool = True ):
7940 """Clears the previous plots and updates the ref and SLD plots.
8041
8142 Parameters
8243 ----------
8344 data : PlotEventData
8445 The plot event data that contains all the information
8546 to generate the ref and sld plots
86- fig : Figure , optional
47+ fig : matplotlib.pyplot.figure , optional
8748 The figure class that has two subplots
8849 delay : bool, default: True
8950 Controls whether to delay 0.005s after plot is created
9051
9152 Returns
9253 -------
93- fig : Figure
54+ fig : matplotlib.pyplot.figure
9455 The figure class that has two subplots
9556
9657 """
97- if fig is None :
98- fig = Figure (1 , 2 )
99- elif fig ._ax .shape != (2 ,):
100- fig ._fig .clf ()
101- fig ._ax = fig ._fig .subplots (1 , 2 )
58+ preserve_zoom = False
10259
103- ref_plot = fig ._ax [0 ]
104- sld_plot = fig ._ax [1 ]
60+ if fig is None :
61+ fig = plt .subplots (1 , 2 )[0 ]
62+ elif len (fig .axes ) != 2 :
63+ fig .clf ()
64+ fig .subplots (1 , 2 )
65+ fig .subplots_adjust (wspace = 0.3 )
66+
67+ ref_plot = fig .axes [0 ]
68+ sld_plot = fig .axes [1 ]
69+ if ref_plot .lines and fig .canvas .toolbar is not None :
70+ preserve_zoom = True
71+ fig .canvas .toolbar .push_current ()
10572
10673 # Clears the previous plots
10774 ref_plot .cla ()
@@ -160,16 +127,18 @@ def plot_ref_sld_helper(data: PlotEventData, fig: Optional[Figure] = None, delay
160127 # Format the axis
161128 ref_plot .set_yscale ("log" )
162129 ref_plot .set_xscale ("log" )
163- ref_plot .set_xlabel ("Qz " )
164- ref_plot .set_ylabel ("Ref " )
130+ ref_plot .set_xlabel ("$Q_{z} ( \u00c5 ^{-1})$ " )
131+ ref_plot .set_ylabel ("Reflectivity " )
165132 ref_plot .legend ()
166133 ref_plot .grid ()
167134
168- sld_plot .set_xlabel ("Z " )
169- sld_plot .set_ylabel ("SLD" )
135+ sld_plot .set_xlabel ("$Z ( \u00c5 )$ " )
136+ sld_plot .set_ylabel ("$ SLD ( \u00c5 ^{-2})$ " )
170137 sld_plot .legend ()
171138 sld_plot .grid ()
172139
140+ if preserve_zoom :
141+ fig .canvas .toolbar .back ()
173142 if delay :
174143 plt .pause (0.005 )
175144
@@ -204,8 +173,52 @@ def plot_ref_sld(
204173 data .subRoughs = results .contrastParams .subRoughs
205174 data .resample = RATapi .inputs .make_resample (project )
206175
207- figure = Figure (1 , 2 )
176+ figure = plt . subplots (1 , 2 )[ 0 ]
208177
209178 plot_ref_sld_helper (data , figure )
210- if block :
211- figure .wait_for_close ()
179+
180+ plt .show (block = block )
181+
182+
183+ class LivePlot :
184+ """Creates a plot that gets updates from the plot event during a
185+ calculation
186+
187+ Parameters
188+ ----------
189+ block : bool, default: False
190+ Indicates the plot should block until it is closed
191+
192+ """
193+
194+ def __init__ (self , block = False ):
195+ self .block = block
196+ self .closed = False
197+
198+ def __enter__ (self ):
199+ self .figure = plt .subplots (1 , 2 )[0 ]
200+ self .figure .canvas .mpl_connect ("close_event" , self ._setCloseState )
201+ self .figure .show ()
202+ RATapi .events .register (RATapi .events .EventTypes .Plot , self .plotEvent )
203+
204+ return self .figure
205+
206+ def _setCloseState (self , _ ):
207+ """Close event handler"""
208+ self .closed = True
209+
210+ def plotEvent (self , event ):
211+ """Callback for the plot event.
212+
213+ Parameters
214+ ----------
215+ event: PlotEventData
216+ The plot event data.
217+ """
218+ if not self .closed and self .figure .number in plt .get_fignums ():
219+ plot_ref_sld_helper (event , self .figure )
220+
221+ def __exit__ (self , _exc_type , _exc_val , _traceback ):
222+ RATapi .events .clear (RATapi .events .EventTypes .Plot , self .plotEvent )
223+ if not self .closed and self .figure .number in plt .get_fignums ():
224+ plt .show (block = self .block )
0 commit comments