PySDM_examples.Shima_et_al_2009.tutorial_plotter
1import numpy as np 2from matplotlib import pyplot 3from open_atmos_jupyter_utils import show_plot 4 5from PySDM.physics.constants import si 6 7 8class SpectrumColors: 9 def __init__(self, begining="#2cbdfe", end="#b317b1"): 10 self.b = begining 11 self.e = end 12 13 def __call__(self, value: float): 14 bR, bG, bB = int(self.b[1:3], 16), int(self.b[3:5], 16), int(self.b[5:7], 16) 15 eR, eG, eB = int(self.e[1:3], 16), int(self.e[3:5], 16), int(self.e[5:7], 16) 16 R = bR + int((eR - bR) * value) 17 G = bG + int((eG - bG) * value) 18 B = bB + int((eB - bB) * value) 19 result = f"#{hex(R)[2:4]}{hex(G)[2:4]}{hex(B)[2:4]}" 20 return result 21 22 23class SpectrumPlotter: 24 def __init__(self, settings, grid=True, legend=True, log_base=10): 25 self.settings = settings 26 self.format = "pdf" 27 self.colors = SpectrumColors() 28 self.smooth = False 29 self.smooth_scope = 2 30 self.legend = legend 31 self.grid = grid 32 self.xlabel = "particle radius [µm]" 33 self.ylabel = "dm/dlnr [g/m$^3$]" 34 self.log_base = log_base 35 self.ax = pyplot 36 self.fig = pyplot 37 self.finished = False 38 39 def finish(self): 40 if self.finished: 41 return 42 self.finished = True 43 if self.grid: 44 self.ax.grid() 45 46 self.ax.xscale("log") 47 self.ax.xlabel(self.xlabel) 48 self.ax.ylabel(self.ylabel) 49 if self.legend: 50 self.ax.legend() 51 52 def show(self): 53 self.finish() 54 pyplot.tight_layout() 55 show_plot() 56 57 def save(self, file): 58 self.finish() 59 pyplot.savefig(file, format=self.format) 60 61 def plot(self, spectrum, t): 62 self.plot_analytic_solution(self.settings, t) 63 self.plot_data(self.settings, t, spectrum) 64 65 def plot_analytic_solution(self, settings, t): 66 def analytic_solution(x): 67 return settings.norm_factor * settings.kernel.analytic_solution( 68 x=x, t=t, x_0=settings.X0, N_0=settings.n_part 69 ) 70 71 if t == 0: 72 analytic_solution = settings.spectrum.size_distribution 73 74 volume_bins_edges = self.settings.formulae.trivia.volume( 75 settings.radius_bins_edges 76 ) 77 dm = np.diff(volume_bins_edges) 78 dr = np.diff(settings.radius_bins_edges) 79 80 pdf_m_x = volume_bins_edges[:-1] + dm / 2 81 pdf_m_y = analytic_solution(pdf_m_x) 82 83 pdf_r_x = settings.radius_bins_edges[:-1] + dr / 2 84 pdf_r_y = pdf_m_y * dm / dr * pdf_r_x 85 86 x = pdf_r_x * si.metres / si.micrometres 87 y_true = ( 88 pdf_r_y 89 * self.settings.formulae.trivia.volume(radius=pdf_r_x) 90 * settings.rho 91 / settings.dv 92 * si.kilograms 93 / si.grams 94 ) 95 96 self.ax.plot(x, y_true, color="black") 97 98 def plot_data(self, settings, t, spectrum): 99 if self.smooth: 100 scope = self.smooth_scope 101 if t != 0: 102 new = np.copy(spectrum) 103 for _ in range(2): 104 for i in range(scope, len(spectrum) - scope): 105 new[i] = np.mean(spectrum[i - scope : i + scope + 1]) 106 scope = 1 107 for i in range(scope, len(spectrum) - scope): 108 spectrum[i] = np.mean(new[i - scope : i + scope + 1]) 109 110 x = settings.radius_bins_edges[:-scope] 111 dx = np.diff(x) 112 self.ax.plot( 113 (x[:-1] + dx / 2) * si.metres / si.micrometres, 114 spectrum[:-scope] * si.kilograms / si.grams, 115 label=f"t = {t}s", 116 color=self.colors( 117 t / (self.settings.output_steps[-1] * self.settings.dt) 118 ), 119 ) 120 else: 121 self.ax.step( 122 settings.radius_bins_edges[:-1] * si.metres / si.micrometres, 123 spectrum * si.kilograms / si.grams, 124 where="post", 125 label=f"t = {t}s", 126 color=self.colors( 127 t / (self.settings.output_steps[-1] * self.settings.dt) 128 ), 129 )
class
SpectrumColors:
9class SpectrumColors: 10 def __init__(self, begining="#2cbdfe", end="#b317b1"): 11 self.b = begining 12 self.e = end 13 14 def __call__(self, value: float): 15 bR, bG, bB = int(self.b[1:3], 16), int(self.b[3:5], 16), int(self.b[5:7], 16) 16 eR, eG, eB = int(self.e[1:3], 16), int(self.e[3:5], 16), int(self.e[5:7], 16) 17 R = bR + int((eR - bR) * value) 18 G = bG + int((eG - bG) * value) 19 B = bB + int((eB - bB) * value) 20 result = f"#{hex(R)[2:4]}{hex(G)[2:4]}{hex(B)[2:4]}" 21 return result
class
SpectrumPlotter:
24class SpectrumPlotter: 25 def __init__(self, settings, grid=True, legend=True, log_base=10): 26 self.settings = settings 27 self.format = "pdf" 28 self.colors = SpectrumColors() 29 self.smooth = False 30 self.smooth_scope = 2 31 self.legend = legend 32 self.grid = grid 33 self.xlabel = "particle radius [µm]" 34 self.ylabel = "dm/dlnr [g/m$^3$]" 35 self.log_base = log_base 36 self.ax = pyplot 37 self.fig = pyplot 38 self.finished = False 39 40 def finish(self): 41 if self.finished: 42 return 43 self.finished = True 44 if self.grid: 45 self.ax.grid() 46 47 self.ax.xscale("log") 48 self.ax.xlabel(self.xlabel) 49 self.ax.ylabel(self.ylabel) 50 if self.legend: 51 self.ax.legend() 52 53 def show(self): 54 self.finish() 55 pyplot.tight_layout() 56 show_plot() 57 58 def save(self, file): 59 self.finish() 60 pyplot.savefig(file, format=self.format) 61 62 def plot(self, spectrum, t): 63 self.plot_analytic_solution(self.settings, t) 64 self.plot_data(self.settings, t, spectrum) 65 66 def plot_analytic_solution(self, settings, t): 67 def analytic_solution(x): 68 return settings.norm_factor * settings.kernel.analytic_solution( 69 x=x, t=t, x_0=settings.X0, N_0=settings.n_part 70 ) 71 72 if t == 0: 73 analytic_solution = settings.spectrum.size_distribution 74 75 volume_bins_edges = self.settings.formulae.trivia.volume( 76 settings.radius_bins_edges 77 ) 78 dm = np.diff(volume_bins_edges) 79 dr = np.diff(settings.radius_bins_edges) 80 81 pdf_m_x = volume_bins_edges[:-1] + dm / 2 82 pdf_m_y = analytic_solution(pdf_m_x) 83 84 pdf_r_x = settings.radius_bins_edges[:-1] + dr / 2 85 pdf_r_y = pdf_m_y * dm / dr * pdf_r_x 86 87 x = pdf_r_x * si.metres / si.micrometres 88 y_true = ( 89 pdf_r_y 90 * self.settings.formulae.trivia.volume(radius=pdf_r_x) 91 * settings.rho 92 / settings.dv 93 * si.kilograms 94 / si.grams 95 ) 96 97 self.ax.plot(x, y_true, color="black") 98 99 def plot_data(self, settings, t, spectrum): 100 if self.smooth: 101 scope = self.smooth_scope 102 if t != 0: 103 new = np.copy(spectrum) 104 for _ in range(2): 105 for i in range(scope, len(spectrum) - scope): 106 new[i] = np.mean(spectrum[i - scope : i + scope + 1]) 107 scope = 1 108 for i in range(scope, len(spectrum) - scope): 109 spectrum[i] = np.mean(new[i - scope : i + scope + 1]) 110 111 x = settings.radius_bins_edges[:-scope] 112 dx = np.diff(x) 113 self.ax.plot( 114 (x[:-1] + dx / 2) * si.metres / si.micrometres, 115 spectrum[:-scope] * si.kilograms / si.grams, 116 label=f"t = {t}s", 117 color=self.colors( 118 t / (self.settings.output_steps[-1] * self.settings.dt) 119 ), 120 ) 121 else: 122 self.ax.step( 123 settings.radius_bins_edges[:-1] * si.metres / si.micrometres, 124 spectrum * si.kilograms / si.grams, 125 where="post", 126 label=f"t = {t}s", 127 color=self.colors( 128 t / (self.settings.output_steps[-1] * self.settings.dt) 129 ), 130 )
SpectrumPlotter(settings, grid=True, legend=True, log_base=10)
25 def __init__(self, settings, grid=True, legend=True, log_base=10): 26 self.settings = settings 27 self.format = "pdf" 28 self.colors = SpectrumColors() 29 self.smooth = False 30 self.smooth_scope = 2 31 self.legend = legend 32 self.grid = grid 33 self.xlabel = "particle radius [µm]" 34 self.ylabel = "dm/dlnr [g/m$^3$]" 35 self.log_base = log_base 36 self.ax = pyplot 37 self.fig = pyplot 38 self.finished = False
def
plot_analytic_solution(self, settings, t):
66 def plot_analytic_solution(self, settings, t): 67 def analytic_solution(x): 68 return settings.norm_factor * settings.kernel.analytic_solution( 69 x=x, t=t, x_0=settings.X0, N_0=settings.n_part 70 ) 71 72 if t == 0: 73 analytic_solution = settings.spectrum.size_distribution 74 75 volume_bins_edges = self.settings.formulae.trivia.volume( 76 settings.radius_bins_edges 77 ) 78 dm = np.diff(volume_bins_edges) 79 dr = np.diff(settings.radius_bins_edges) 80 81 pdf_m_x = volume_bins_edges[:-1] + dm / 2 82 pdf_m_y = analytic_solution(pdf_m_x) 83 84 pdf_r_x = settings.radius_bins_edges[:-1] + dr / 2 85 pdf_r_y = pdf_m_y * dm / dr * pdf_r_x 86 87 x = pdf_r_x * si.metres / si.micrometres 88 y_true = ( 89 pdf_r_y 90 * self.settings.formulae.trivia.volume(radius=pdf_r_x) 91 * settings.rho 92 / settings.dv 93 * si.kilograms 94 / si.grams 95 ) 96 97 self.ax.plot(x, y_true, color="black")
def
plot_data(self, settings, t, spectrum):
99 def plot_data(self, settings, t, spectrum): 100 if self.smooth: 101 scope = self.smooth_scope 102 if t != 0: 103 new = np.copy(spectrum) 104 for _ in range(2): 105 for i in range(scope, len(spectrum) - scope): 106 new[i] = np.mean(spectrum[i - scope : i + scope + 1]) 107 scope = 1 108 for i in range(scope, len(spectrum) - scope): 109 spectrum[i] = np.mean(new[i - scope : i + scope + 1]) 110 111 x = settings.radius_bins_edges[:-scope] 112 dx = np.diff(x) 113 self.ax.plot( 114 (x[:-1] + dx / 2) * si.metres / si.micrometres, 115 spectrum[:-scope] * si.kilograms / si.grams, 116 label=f"t = {t}s", 117 color=self.colors( 118 t / (self.settings.output_steps[-1] * self.settings.dt) 119 ), 120 ) 121 else: 122 self.ax.step( 123 settings.radius_bins_edges[:-1] * si.metres / si.micrometres, 124 spectrum * si.kilograms / si.grams, 125 where="post", 126 label=f"t = {t}s", 127 color=self.colors( 128 t / (self.settings.output_steps[-1] * self.settings.dt) 129 ), 130 )