PySDM_examples.Szumowski_et_al_1998.gui_viewer
1import warnings 2 3import numpy as np 4from matplotlib import pyplot, rcParams 5from open_atmos_jupyter_utils import save_and_make_link 6from PySDM_examples.Szumowski_et_al_1998.plots import ( 7 _ImagePlot, 8 _SpectrumPlot, 9 _TemperaturePlot, 10 _TerminalVelocityPlot, 11 _TimeseriesPlot, 12) 13from PySDM_examples.utils.widgets import ( 14 Box, 15 Button, 16 Dropdown, 17 HBox, 18 IntRangeSlider, 19 IntSlider, 20 Layout, 21 Output, 22 Play, 23 VBox, 24 clear_output, 25 display, 26 jslink, 27) 28 29from PySDM.physics import constants as const 30 31 32class GUIViewer: 33 def __init__(self, storage, settings): 34 self.storage = storage 35 self.settings = settings 36 37 self.play = Play(interval=1000) 38 self.step_slider = IntSlider(continuous_update=False, description="t/dt_out:") 39 self.product_select = Dropdown() 40 self.spectrum_select = Dropdown() 41 self.plots_box = Box() 42 43 self.timeseriesOutput = None 44 self.timeseriesPlot = None 45 self.plot_box = None 46 self.spectrum_box = None 47 self.outputs = None 48 self.plots = None 49 self.spectrumOutputs = None 50 self.spectrumPlots = None 51 self.products = None 52 53 self.slider = {} 54 self.lines = {"X": [{}, {}], "Z": [{}, {}]} 55 for xz in ("X", "Z"): 56 self.slider[xz] = IntRangeSlider( 57 min=0, 58 max=1, 59 description=f"{xz}", 60 continuous_update=False, 61 orientation="horizontal" if xz == "X" else "vertical", 62 ) 63 64 self.reinit({}) 65 66 def clear(self): 67 self.plots_box.children = () 68 69 def reinit(self, products): 70 self.products = products 71 self.product_select.options = tuple( 72 (f"{val.name} [{val.unit}]", key) 73 for key, val in sorted(self.products.items(), key=lambda item: item[1].name) 74 if len(val.shape) == 2 75 ) 76 opts = [ 77 ("particle size spectra", "size"), 78 ("terminal velocity", "terminal velocity"), 79 ] 80 if "freezable specific concentration" in products: 81 opts.append(("freezing temperature spectra", "temperature")) 82 if "immersed surface area" in products: 83 pass # TODO #599 84 self.spectrum_select.options = tuple(opts) 85 86 r_bins = self.settings.r_bins_edges.copy() 87 const.convert_to(r_bins, const.si.micrometres) 88 self.spectrumOutputs = {} 89 self.spectrumPlots = {} 90 for key in ("size", "terminal velocity", "temperature"): 91 self.spectrumOutputs[key] = Output() 92 with self.spectrumOutputs[key]: 93 self.spectrumPlots[key] = ( 94 _SpectrumPlot(r_bins, self.settings.spectrum_per_mass_of_dry_air) 95 if key == "size" 96 else ( 97 _TemperaturePlot( 98 self.settings.T_bins_edges, self.settings.formulae 99 ) 100 if key == "temperature" 101 else _TerminalVelocityPlot( 102 self.settings.terminal_velocity_radius_bin_edges, 103 self.settings.formulae, 104 ) 105 ) 106 ) 107 clear_output() 108 109 self.timeseriesOutput = Output() 110 with self.timeseriesOutput: 111 default_figsize = rcParams["figure.figsize"] 112 fig_kw = {"figsize": (2.5 * default_figsize[0], default_figsize[1] / 2)} 113 fig, ax = pyplot.subplots(1, 1, **fig_kw) 114 self.timeseriesPlot = _TimeseriesPlot( 115 fig, ax, self.settings.output_steps * self.settings.dt 116 ) 117 clear_output() 118 119 self.plots = {} 120 self.outputs = {} 121 for key, product in products.items(): 122 if len(product.shape) == 2: 123 self.outputs[key] = Output() 124 with self.outputs[key]: 125 fig, ax = pyplot.subplots(1, 1) 126 self.plots[key] = _ImagePlot( 127 fig, 128 ax, 129 self.settings.grid, 130 self.settings.size, 131 product, 132 show=True, 133 lines=True, 134 ) 135 clear_output() 136 137 self.plot_box = Box() 138 self.spectrum_box = Box() 139 if len(products.keys()) > 0: 140 layout_flex_end = Layout(display="flex", justify_content="flex-end") 141 save_map = Button(icon="save") 142 save_map.on_click(self.handle_save_map) 143 save_spe = Button(icon="save") 144 save_spe.on_click(self.handle_save_spe) 145 self.plots_box.children = ( 146 VBox( 147 children=( 148 HBox( 149 children=( 150 VBox( 151 children=( 152 Box( 153 layout=layout_flex_end, 154 children=(save_map, self.product_select), 155 ), 156 HBox((self.slider["Z"], self.plot_box)), 157 HBox( 158 (self.slider["X"],), layout=layout_flex_end 159 ), 160 ) 161 ), 162 VBox( 163 layout=Layout(), 164 children=( 165 Box( 166 children=(save_spe, self.spectrum_select), 167 layout=layout_flex_end, 168 ), 169 self.spectrum_box, 170 ), 171 ), 172 ) 173 ), 174 HBox((self.timeseriesOutput,)), 175 ) 176 ), 177 ) 178 179 for widget in (self.step_slider, self.play): 180 widget.value = 0 181 widget.max = len(self.settings.output_steps) - 1 182 183 for j, xz in enumerate(("X", "Z")): 184 slider = self.slider[xz] 185 mx = self.settings.grid[j] 186 slider.max = mx 187 slider.value = (0, mx) 188 189 self.replot() 190 191 def handle_save_map(self, _): 192 display(save_and_make_link(self.plots[self.product_select.value].fig)) 193 194 def handle_save_spe(self, _): 195 display(save_and_make_link(self.spectrumPlots[self.spectrum_select.value].fig)) 196 197 def replot(self, *_): 198 selectedImage = self.product_select.value 199 if not (selectedImage is None or selectedImage not in self.plots): 200 self.replot_image() 201 self.outputs[selectedImage].clear_output(wait=True) 202 with self.outputs[selectedImage]: 203 display(self.plots[selectedImage].fig) 204 205 selectedSpectrum = self.spectrum_select.value 206 if not (selectedSpectrum is None or selectedSpectrum not in self.spectrumPlots): 207 self.replot_spectra() 208 self.spectrumOutputs[selectedSpectrum].clear_output(wait=True) 209 with self.spectrumOutputs[selectedSpectrum]: 210 display(self.spectrumPlots[selectedSpectrum].fig) 211 212 self.update_timeseries() 213 self.timeseriesOutput.clear_output(wait=True) 214 with self.timeseriesOutput: 215 display(self.timeseriesPlot.fig) 216 217 def update_spectra(self): 218 selected = self.spectrum_select.value 219 self.spectrum_box.children = [self.spectrumOutputs[selected]] 220 plot = self.spectrumPlots[selected] 221 222 step = self.step_slider.value 223 224 xrange = slice(*self.slider["X"].value) 225 yrange = slice(*self.slider["Z"].value) 226 227 if selected == "size": 228 for key in ("Particles Wet Size Spectrum", "Particles Dry Size Spectrum"): 229 if xrange.start == xrange.stop or yrange.start == yrange.stop: 230 continue 231 try: 232 data = self.storage.load(key, self.settings.output_steps[step]) 233 data = data[xrange, yrange, :] 234 data = np.mean(np.mean(data, axis=0), axis=0) 235 data = np.concatenate(((0,), data)) 236 if key == "Particles Wet Size Spectrum": 237 plot.update_wet(data, step) 238 if key == "Particles Dry Size Spectrum": 239 plot.update_dry(data) 240 except self.storage.Exception: 241 pass 242 elif selected == "terminal velocity": 243 try: 244 data = self.storage.load( 245 "radius binned number averaged terminal velocity", 246 self.settings.output_steps[step], 247 ) 248 249 data = data[xrange, yrange, :] 250 data = np.where(data != 0, data, np.nan) 251 try: 252 with warnings.catch_warnings(record=True) as _: 253 warnings.simplefilter("ignore") 254 data_min = np.nanmin(np.nanmin(data, axis=0), axis=0) 255 data_max = np.nanmax(np.nanmax(data, axis=0), axis=0) 256 except RuntimeWarning: 257 pass 258 plot.update(data_min, data_max, step) 259 except self.storage.Exception: 260 pass 261 elif selected == "temperature": 262 try: 263 dT = abs(self.settings.T_bins_edges[1] - self.settings.T_bins_edges[0]) 264 np.testing.assert_allclose(np.diff(self.settings.T_bins_edges), dT) 265 266 conc = self.storage.load( 267 "particle specific concentration", self.settings.output_steps[step] 268 ) 269 # TODO #705: assert unit == mg^-1 270 conc = conc[xrange, yrange] 271 272 data = self.storage.load( 273 "freezable specific concentration", self.settings.output_steps[step] 274 ) 275 data = data[xrange, yrange, :] 276 277 data = np.sum(np.sum(data, axis=0), axis=0) / np.sum( 278 np.sum(conc, axis=0), axis=0 279 ) 280 data = np.concatenate(((0,), dT * np.cumsum(data[::-1])))[::-1] 281 282 plot.update(data, step) 283 except self.storage.Exception: 284 pass 285 else: 286 raise NotImplementedError() 287 288 def replot_spectra(self, *_): 289 self.update_spectra() 290 291 selected = self.product_select.value 292 if selected is None or selected not in self.plots: 293 return 294 self.plots[selected].update_lines( 295 self.slider["X"].value, self.slider["Z"].value 296 ) 297 298 self.outputs[selected].clear_output(wait=True) 299 300 key = self.spectrum_select.value 301 self.spectrumOutputs[key].clear_output(wait=True) 302 with self.outputs[selected]: 303 display(self.plots[selected].fig) 304 with self.spectrumOutputs[key]: 305 display(self.spectrumPlots[key].fig) 306 307 def update_image(self): 308 selected = self.product_select.value 309 310 if selected in self.outputs: 311 self.plot_box.children = [self.outputs[selected]] 312 313 step = self.step_slider.value 314 try: 315 data = self.storage.load(selected, self.settings.output_steps[step]) 316 except self.storage.Exception: 317 data = None 318 319 self.plots[selected].update( 320 data, step, self.storage.data_range(selected) if data is not None else None 321 ) 322 323 def replot_image(self, *_): 324 selected = self.product_select.value 325 if selected is None or selected not in self.plots: 326 return 327 328 self.update_image() 329 self.outputs[selected].clear_output(wait=True) 330 with self.outputs[selected]: 331 display(self.plots[selected].fig) 332 333 def update_timeseries(self): 334 try: 335 data = self.storage.load("surf_precip") 336 except self.storage.Exception: 337 data = None 338 self.timeseriesPlot.update( 339 data, self.storage.data_range("surf_precip") if data is not None else None 340 ) 341 342 def replot_timeseries(self): 343 self.update_timeseries() 344 self.timeseriesOutput.clear_output(wait=True) 345 with self.timeseriesOutput: 346 display(self.timeseriesPlot.fig) 347 348 def box(self): 349 jslink((self.play, "value"), (self.step_slider, "value")) 350 self.step_slider.observe(self.replot, "value") 351 self.product_select.observe(self.replot_image, "value") 352 self.spectrum_select.observe(self.replot_spectra, "value") 353 for xz in ("X", "Z"): 354 self.slider[xz].observe(self.replot_spectra, "value") 355 return VBox([Box([self.play, self.step_slider]), self.plots_box])
class
GUIViewer:
33class GUIViewer: 34 def __init__(self, storage, settings): 35 self.storage = storage 36 self.settings = settings 37 38 self.play = Play(interval=1000) 39 self.step_slider = IntSlider(continuous_update=False, description="t/dt_out:") 40 self.product_select = Dropdown() 41 self.spectrum_select = Dropdown() 42 self.plots_box = Box() 43 44 self.timeseriesOutput = None 45 self.timeseriesPlot = None 46 self.plot_box = None 47 self.spectrum_box = None 48 self.outputs = None 49 self.plots = None 50 self.spectrumOutputs = None 51 self.spectrumPlots = None 52 self.products = None 53 54 self.slider = {} 55 self.lines = {"X": [{}, {}], "Z": [{}, {}]} 56 for xz in ("X", "Z"): 57 self.slider[xz] = IntRangeSlider( 58 min=0, 59 max=1, 60 description=f"{xz}", 61 continuous_update=False, 62 orientation="horizontal" if xz == "X" else "vertical", 63 ) 64 65 self.reinit({}) 66 67 def clear(self): 68 self.plots_box.children = () 69 70 def reinit(self, products): 71 self.products = products 72 self.product_select.options = tuple( 73 (f"{val.name} [{val.unit}]", key) 74 for key, val in sorted(self.products.items(), key=lambda item: item[1].name) 75 if len(val.shape) == 2 76 ) 77 opts = [ 78 ("particle size spectra", "size"), 79 ("terminal velocity", "terminal velocity"), 80 ] 81 if "freezable specific concentration" in products: 82 opts.append(("freezing temperature spectra", "temperature")) 83 if "immersed surface area" in products: 84 pass # TODO #599 85 self.spectrum_select.options = tuple(opts) 86 87 r_bins = self.settings.r_bins_edges.copy() 88 const.convert_to(r_bins, const.si.micrometres) 89 self.spectrumOutputs = {} 90 self.spectrumPlots = {} 91 for key in ("size", "terminal velocity", "temperature"): 92 self.spectrumOutputs[key] = Output() 93 with self.spectrumOutputs[key]: 94 self.spectrumPlots[key] = ( 95 _SpectrumPlot(r_bins, self.settings.spectrum_per_mass_of_dry_air) 96 if key == "size" 97 else ( 98 _TemperaturePlot( 99 self.settings.T_bins_edges, self.settings.formulae 100 ) 101 if key == "temperature" 102 else _TerminalVelocityPlot( 103 self.settings.terminal_velocity_radius_bin_edges, 104 self.settings.formulae, 105 ) 106 ) 107 ) 108 clear_output() 109 110 self.timeseriesOutput = Output() 111 with self.timeseriesOutput: 112 default_figsize = rcParams["figure.figsize"] 113 fig_kw = {"figsize": (2.5 * default_figsize[0], default_figsize[1] / 2)} 114 fig, ax = pyplot.subplots(1, 1, **fig_kw) 115 self.timeseriesPlot = _TimeseriesPlot( 116 fig, ax, self.settings.output_steps * self.settings.dt 117 ) 118 clear_output() 119 120 self.plots = {} 121 self.outputs = {} 122 for key, product in products.items(): 123 if len(product.shape) == 2: 124 self.outputs[key] = Output() 125 with self.outputs[key]: 126 fig, ax = pyplot.subplots(1, 1) 127 self.plots[key] = _ImagePlot( 128 fig, 129 ax, 130 self.settings.grid, 131 self.settings.size, 132 product, 133 show=True, 134 lines=True, 135 ) 136 clear_output() 137 138 self.plot_box = Box() 139 self.spectrum_box = Box() 140 if len(products.keys()) > 0: 141 layout_flex_end = Layout(display="flex", justify_content="flex-end") 142 save_map = Button(icon="save") 143 save_map.on_click(self.handle_save_map) 144 save_spe = Button(icon="save") 145 save_spe.on_click(self.handle_save_spe) 146 self.plots_box.children = ( 147 VBox( 148 children=( 149 HBox( 150 children=( 151 VBox( 152 children=( 153 Box( 154 layout=layout_flex_end, 155 children=(save_map, self.product_select), 156 ), 157 HBox((self.slider["Z"], self.plot_box)), 158 HBox( 159 (self.slider["X"],), layout=layout_flex_end 160 ), 161 ) 162 ), 163 VBox( 164 layout=Layout(), 165 children=( 166 Box( 167 children=(save_spe, self.spectrum_select), 168 layout=layout_flex_end, 169 ), 170 self.spectrum_box, 171 ), 172 ), 173 ) 174 ), 175 HBox((self.timeseriesOutput,)), 176 ) 177 ), 178 ) 179 180 for widget in (self.step_slider, self.play): 181 widget.value = 0 182 widget.max = len(self.settings.output_steps) - 1 183 184 for j, xz in enumerate(("X", "Z")): 185 slider = self.slider[xz] 186 mx = self.settings.grid[j] 187 slider.max = mx 188 slider.value = (0, mx) 189 190 self.replot() 191 192 def handle_save_map(self, _): 193 display(save_and_make_link(self.plots[self.product_select.value].fig)) 194 195 def handle_save_spe(self, _): 196 display(save_and_make_link(self.spectrumPlots[self.spectrum_select.value].fig)) 197 198 def replot(self, *_): 199 selectedImage = self.product_select.value 200 if not (selectedImage is None or selectedImage not in self.plots): 201 self.replot_image() 202 self.outputs[selectedImage].clear_output(wait=True) 203 with self.outputs[selectedImage]: 204 display(self.plots[selectedImage].fig) 205 206 selectedSpectrum = self.spectrum_select.value 207 if not (selectedSpectrum is None or selectedSpectrum not in self.spectrumPlots): 208 self.replot_spectra() 209 self.spectrumOutputs[selectedSpectrum].clear_output(wait=True) 210 with self.spectrumOutputs[selectedSpectrum]: 211 display(self.spectrumPlots[selectedSpectrum].fig) 212 213 self.update_timeseries() 214 self.timeseriesOutput.clear_output(wait=True) 215 with self.timeseriesOutput: 216 display(self.timeseriesPlot.fig) 217 218 def update_spectra(self): 219 selected = self.spectrum_select.value 220 self.spectrum_box.children = [self.spectrumOutputs[selected]] 221 plot = self.spectrumPlots[selected] 222 223 step = self.step_slider.value 224 225 xrange = slice(*self.slider["X"].value) 226 yrange = slice(*self.slider["Z"].value) 227 228 if selected == "size": 229 for key in ("Particles Wet Size Spectrum", "Particles Dry Size Spectrum"): 230 if xrange.start == xrange.stop or yrange.start == yrange.stop: 231 continue 232 try: 233 data = self.storage.load(key, self.settings.output_steps[step]) 234 data = data[xrange, yrange, :] 235 data = np.mean(np.mean(data, axis=0), axis=0) 236 data = np.concatenate(((0,), data)) 237 if key == "Particles Wet Size Spectrum": 238 plot.update_wet(data, step) 239 if key == "Particles Dry Size Spectrum": 240 plot.update_dry(data) 241 except self.storage.Exception: 242 pass 243 elif selected == "terminal velocity": 244 try: 245 data = self.storage.load( 246 "radius binned number averaged terminal velocity", 247 self.settings.output_steps[step], 248 ) 249 250 data = data[xrange, yrange, :] 251 data = np.where(data != 0, data, np.nan) 252 try: 253 with warnings.catch_warnings(record=True) as _: 254 warnings.simplefilter("ignore") 255 data_min = np.nanmin(np.nanmin(data, axis=0), axis=0) 256 data_max = np.nanmax(np.nanmax(data, axis=0), axis=0) 257 except RuntimeWarning: 258 pass 259 plot.update(data_min, data_max, step) 260 except self.storage.Exception: 261 pass 262 elif selected == "temperature": 263 try: 264 dT = abs(self.settings.T_bins_edges[1] - self.settings.T_bins_edges[0]) 265 np.testing.assert_allclose(np.diff(self.settings.T_bins_edges), dT) 266 267 conc = self.storage.load( 268 "particle specific concentration", self.settings.output_steps[step] 269 ) 270 # TODO #705: assert unit == mg^-1 271 conc = conc[xrange, yrange] 272 273 data = self.storage.load( 274 "freezable specific concentration", self.settings.output_steps[step] 275 ) 276 data = data[xrange, yrange, :] 277 278 data = np.sum(np.sum(data, axis=0), axis=0) / np.sum( 279 np.sum(conc, axis=0), axis=0 280 ) 281 data = np.concatenate(((0,), dT * np.cumsum(data[::-1])))[::-1] 282 283 plot.update(data, step) 284 except self.storage.Exception: 285 pass 286 else: 287 raise NotImplementedError() 288 289 def replot_spectra(self, *_): 290 self.update_spectra() 291 292 selected = self.product_select.value 293 if selected is None or selected not in self.plots: 294 return 295 self.plots[selected].update_lines( 296 self.slider["X"].value, self.slider["Z"].value 297 ) 298 299 self.outputs[selected].clear_output(wait=True) 300 301 key = self.spectrum_select.value 302 self.spectrumOutputs[key].clear_output(wait=True) 303 with self.outputs[selected]: 304 display(self.plots[selected].fig) 305 with self.spectrumOutputs[key]: 306 display(self.spectrumPlots[key].fig) 307 308 def update_image(self): 309 selected = self.product_select.value 310 311 if selected in self.outputs: 312 self.plot_box.children = [self.outputs[selected]] 313 314 step = self.step_slider.value 315 try: 316 data = self.storage.load(selected, self.settings.output_steps[step]) 317 except self.storage.Exception: 318 data = None 319 320 self.plots[selected].update( 321 data, step, self.storage.data_range(selected) if data is not None else None 322 ) 323 324 def replot_image(self, *_): 325 selected = self.product_select.value 326 if selected is None or selected not in self.plots: 327 return 328 329 self.update_image() 330 self.outputs[selected].clear_output(wait=True) 331 with self.outputs[selected]: 332 display(self.plots[selected].fig) 333 334 def update_timeseries(self): 335 try: 336 data = self.storage.load("surf_precip") 337 except self.storage.Exception: 338 data = None 339 self.timeseriesPlot.update( 340 data, self.storage.data_range("surf_precip") if data is not None else None 341 ) 342 343 def replot_timeseries(self): 344 self.update_timeseries() 345 self.timeseriesOutput.clear_output(wait=True) 346 with self.timeseriesOutput: 347 display(self.timeseriesPlot.fig) 348 349 def box(self): 350 jslink((self.play, "value"), (self.step_slider, "value")) 351 self.step_slider.observe(self.replot, "value") 352 self.product_select.observe(self.replot_image, "value") 353 self.spectrum_select.observe(self.replot_spectra, "value") 354 for xz in ("X", "Z"): 355 self.slider[xz].observe(self.replot_spectra, "value") 356 return VBox([Box([self.play, self.step_slider]), self.plots_box])
GUIViewer(storage, settings)
34 def __init__(self, storage, settings): 35 self.storage = storage 36 self.settings = settings 37 38 self.play = Play(interval=1000) 39 self.step_slider = IntSlider(continuous_update=False, description="t/dt_out:") 40 self.product_select = Dropdown() 41 self.spectrum_select = Dropdown() 42 self.plots_box = Box() 43 44 self.timeseriesOutput = None 45 self.timeseriesPlot = None 46 self.plot_box = None 47 self.spectrum_box = None 48 self.outputs = None 49 self.plots = None 50 self.spectrumOutputs = None 51 self.spectrumPlots = None 52 self.products = None 53 54 self.slider = {} 55 self.lines = {"X": [{}, {}], "Z": [{}, {}]} 56 for xz in ("X", "Z"): 57 self.slider[xz] = IntRangeSlider( 58 min=0, 59 max=1, 60 description=f"{xz}", 61 continuous_update=False, 62 orientation="horizontal" if xz == "X" else "vertical", 63 ) 64 65 self.reinit({})
def
reinit(self, products):
70 def reinit(self, products): 71 self.products = products 72 self.product_select.options = tuple( 73 (f"{val.name} [{val.unit}]", key) 74 for key, val in sorted(self.products.items(), key=lambda item: item[1].name) 75 if len(val.shape) == 2 76 ) 77 opts = [ 78 ("particle size spectra", "size"), 79 ("terminal velocity", "terminal velocity"), 80 ] 81 if "freezable specific concentration" in products: 82 opts.append(("freezing temperature spectra", "temperature")) 83 if "immersed surface area" in products: 84 pass # TODO #599 85 self.spectrum_select.options = tuple(opts) 86 87 r_bins = self.settings.r_bins_edges.copy() 88 const.convert_to(r_bins, const.si.micrometres) 89 self.spectrumOutputs = {} 90 self.spectrumPlots = {} 91 for key in ("size", "terminal velocity", "temperature"): 92 self.spectrumOutputs[key] = Output() 93 with self.spectrumOutputs[key]: 94 self.spectrumPlots[key] = ( 95 _SpectrumPlot(r_bins, self.settings.spectrum_per_mass_of_dry_air) 96 if key == "size" 97 else ( 98 _TemperaturePlot( 99 self.settings.T_bins_edges, self.settings.formulae 100 ) 101 if key == "temperature" 102 else _TerminalVelocityPlot( 103 self.settings.terminal_velocity_radius_bin_edges, 104 self.settings.formulae, 105 ) 106 ) 107 ) 108 clear_output() 109 110 self.timeseriesOutput = Output() 111 with self.timeseriesOutput: 112 default_figsize = rcParams["figure.figsize"] 113 fig_kw = {"figsize": (2.5 * default_figsize[0], default_figsize[1] / 2)} 114 fig, ax = pyplot.subplots(1, 1, **fig_kw) 115 self.timeseriesPlot = _TimeseriesPlot( 116 fig, ax, self.settings.output_steps * self.settings.dt 117 ) 118 clear_output() 119 120 self.plots = {} 121 self.outputs = {} 122 for key, product in products.items(): 123 if len(product.shape) == 2: 124 self.outputs[key] = Output() 125 with self.outputs[key]: 126 fig, ax = pyplot.subplots(1, 1) 127 self.plots[key] = _ImagePlot( 128 fig, 129 ax, 130 self.settings.grid, 131 self.settings.size, 132 product, 133 show=True, 134 lines=True, 135 ) 136 clear_output() 137 138 self.plot_box = Box() 139 self.spectrum_box = Box() 140 if len(products.keys()) > 0: 141 layout_flex_end = Layout(display="flex", justify_content="flex-end") 142 save_map = Button(icon="save") 143 save_map.on_click(self.handle_save_map) 144 save_spe = Button(icon="save") 145 save_spe.on_click(self.handle_save_spe) 146 self.plots_box.children = ( 147 VBox( 148 children=( 149 HBox( 150 children=( 151 VBox( 152 children=( 153 Box( 154 layout=layout_flex_end, 155 children=(save_map, self.product_select), 156 ), 157 HBox((self.slider["Z"], self.plot_box)), 158 HBox( 159 (self.slider["X"],), layout=layout_flex_end 160 ), 161 ) 162 ), 163 VBox( 164 layout=Layout(), 165 children=( 166 Box( 167 children=(save_spe, self.spectrum_select), 168 layout=layout_flex_end, 169 ), 170 self.spectrum_box, 171 ), 172 ), 173 ) 174 ), 175 HBox((self.timeseriesOutput,)), 176 ) 177 ), 178 ) 179 180 for widget in (self.step_slider, self.play): 181 widget.value = 0 182 widget.max = len(self.settings.output_steps) - 1 183 184 for j, xz in enumerate(("X", "Z")): 185 slider = self.slider[xz] 186 mx = self.settings.grid[j] 187 slider.max = mx 188 slider.value = (0, mx) 189 190 self.replot()
def
replot(self, *_):
198 def replot(self, *_): 199 selectedImage = self.product_select.value 200 if not (selectedImage is None or selectedImage not in self.plots): 201 self.replot_image() 202 self.outputs[selectedImage].clear_output(wait=True) 203 with self.outputs[selectedImage]: 204 display(self.plots[selectedImage].fig) 205 206 selectedSpectrum = self.spectrum_select.value 207 if not (selectedSpectrum is None or selectedSpectrum not in self.spectrumPlots): 208 self.replot_spectra() 209 self.spectrumOutputs[selectedSpectrum].clear_output(wait=True) 210 with self.spectrumOutputs[selectedSpectrum]: 211 display(self.spectrumPlots[selectedSpectrum].fig) 212 213 self.update_timeseries() 214 self.timeseriesOutput.clear_output(wait=True) 215 with self.timeseriesOutput: 216 display(self.timeseriesPlot.fig)
def
update_spectra(self):
218 def update_spectra(self): 219 selected = self.spectrum_select.value 220 self.spectrum_box.children = [self.spectrumOutputs[selected]] 221 plot = self.spectrumPlots[selected] 222 223 step = self.step_slider.value 224 225 xrange = slice(*self.slider["X"].value) 226 yrange = slice(*self.slider["Z"].value) 227 228 if selected == "size": 229 for key in ("Particles Wet Size Spectrum", "Particles Dry Size Spectrum"): 230 if xrange.start == xrange.stop or yrange.start == yrange.stop: 231 continue 232 try: 233 data = self.storage.load(key, self.settings.output_steps[step]) 234 data = data[xrange, yrange, :] 235 data = np.mean(np.mean(data, axis=0), axis=0) 236 data = np.concatenate(((0,), data)) 237 if key == "Particles Wet Size Spectrum": 238 plot.update_wet(data, step) 239 if key == "Particles Dry Size Spectrum": 240 plot.update_dry(data) 241 except self.storage.Exception: 242 pass 243 elif selected == "terminal velocity": 244 try: 245 data = self.storage.load( 246 "radius binned number averaged terminal velocity", 247 self.settings.output_steps[step], 248 ) 249 250 data = data[xrange, yrange, :] 251 data = np.where(data != 0, data, np.nan) 252 try: 253 with warnings.catch_warnings(record=True) as _: 254 warnings.simplefilter("ignore") 255 data_min = np.nanmin(np.nanmin(data, axis=0), axis=0) 256 data_max = np.nanmax(np.nanmax(data, axis=0), axis=0) 257 except RuntimeWarning: 258 pass 259 plot.update(data_min, data_max, step) 260 except self.storage.Exception: 261 pass 262 elif selected == "temperature": 263 try: 264 dT = abs(self.settings.T_bins_edges[1] - self.settings.T_bins_edges[0]) 265 np.testing.assert_allclose(np.diff(self.settings.T_bins_edges), dT) 266 267 conc = self.storage.load( 268 "particle specific concentration", self.settings.output_steps[step] 269 ) 270 # TODO #705: assert unit == mg^-1 271 conc = conc[xrange, yrange] 272 273 data = self.storage.load( 274 "freezable specific concentration", self.settings.output_steps[step] 275 ) 276 data = data[xrange, yrange, :] 277 278 data = np.sum(np.sum(data, axis=0), axis=0) / np.sum( 279 np.sum(conc, axis=0), axis=0 280 ) 281 data = np.concatenate(((0,), dT * np.cumsum(data[::-1])))[::-1] 282 283 plot.update(data, step) 284 except self.storage.Exception: 285 pass 286 else: 287 raise NotImplementedError()
def
replot_spectra(self, *_):
289 def replot_spectra(self, *_): 290 self.update_spectra() 291 292 selected = self.product_select.value 293 if selected is None or selected not in self.plots: 294 return 295 self.plots[selected].update_lines( 296 self.slider["X"].value, self.slider["Z"].value 297 ) 298 299 self.outputs[selected].clear_output(wait=True) 300 301 key = self.spectrum_select.value 302 self.spectrumOutputs[key].clear_output(wait=True) 303 with self.outputs[selected]: 304 display(self.plots[selected].fig) 305 with self.spectrumOutputs[key]: 306 display(self.spectrumPlots[key].fig)
def
update_image(self):
308 def update_image(self): 309 selected = self.product_select.value 310 311 if selected in self.outputs: 312 self.plot_box.children = [self.outputs[selected]] 313 314 step = self.step_slider.value 315 try: 316 data = self.storage.load(selected, self.settings.output_steps[step]) 317 except self.storage.Exception: 318 data = None 319 320 self.plots[selected].update( 321 data, step, self.storage.data_range(selected) if data is not None else None 322 )
def
box(self):
349 def box(self): 350 jslink((self.play, "value"), (self.step_slider, "value")) 351 self.step_slider.observe(self.replot, "value") 352 self.product_select.observe(self.replot_image, "value") 353 self.spectrum_select.observe(self.replot_spectra, "value") 354 for xz in ("X", "Z"): 355 self.slider[xz].observe(self.replot_spectra, "value") 356 return VBox([Box([self.play, self.step_slider]), self.plots_box])