def profile_p(p, x, ax=None, **kwargs): """Plot atmospheric profile against pressure in linear space. Parameters: p (ndarray): Pressure [Pa]. x (ndarray): Atmospheric property. ax (AxesSubplot): Axes to plot in. **kwargs: Additional keyword arguments passed to `plt.plot`. See also: :func:`~typhon.plots.profile_p_log` Plot profile against pressure in log space. :func:`~typhon.plots.profile_z` Plot profile against height. Examples: .. plot:: :include-source: import numpy as np import matplotlib.pyplot as plt import typhon.plots p = typhon.math.nlogspace(1000e2, 0.1e2, 50) # pressure in Pa. x = np.exp(p / p[0]) fig, ax = plt.subplots() typhon.plots.profile_p(p, x, ax=ax) plt.show() """ if ax is None: ax = plt.gca() # Label and format for yaxis. formatter.set_yaxis_formatter(formatter.HectoPascalFormatter(), ax=ax) if ax.get_subplotspec().is_first_col(): ax.set_ylabel('Pressure [hPa]') # Actual plot. ret = ax.plot(x, p, **kwargs) if hasattr(ax.yaxis, 'set_inverted'): # Matplotlib >=3.1.0 # In matplotlib==3.1.0 the yaxis has to be inverted after actual plot # (https://github.com/matplotlib/matplotlib/issues/14615) ax.yaxis.set_inverted(True) elif not ax.yaxis_inverted(): # Matplotlib <=3.0.3 ax.invert_yaxis() return ret
def profile_z(z, x, ax=None, **kwargs): """Plot atmospheric profile of arbitrary property against height (in km). Parameters: z (ndarray): Height [m]. x (ndarray): Atmospheric property. ax (AxesSubplot): Axes to plot in. **kwargs: Additional keyword arguments passed to `plt.plot`. See also: :func:`~typhon.plots.profile_p` Plot profile against pressure in linear space. :func:`~typhon.plots.profile_p_log` Plot profile against pressure in log space. Examples: .. plot:: :include-source: import numpy as np import matplotlib.pyplot as plt import typhon.plots z = np.linspace(0, 80e3, 50) x = np.sin(z / 5e3) fig, ax = plt.subplots() typhon.plots.profile_z(z, x, ax=ax) plt.show() """ if ax is None: ax = plt.gca() # Determine min/max pressure of data in plot. The current axis limits are # also taken into account. This ensures complete data coverage when using # the function iteratively on the same axis. zmin = np.min((np.min(z), *ax.get_ylim())) zmax = np.max((np.max(z), *ax.get_ylim())) ax.set_ylim(zmin, zmax) # Label and format for yaxis. if ax.is_first_col(): ax.set_ylabel('Height [km]') # Actual plot. ret = ax.plot(x, z, **kwargs) formatter.set_yaxis_formatter(formatter.ScalingFormatter('kilo', '{x:g}'), ax=ax) return ret
def profile_p(p, x, ax=None, **kwargs): """Plot atmospheric profile against pressure in linear space. Parameters: p (ndarray): Pressure [Pa]. x (ndarray): Atmospheric property. ax (AxesSubplot): Axes to plot in. **kwargs: Additional keyword arguments passed to `plt.plot`. See also: :func:`~typhon.plots.profile_p_log` Plot profile against pressure in log space. :func:`~typhon.plots.profile_z` Plot profile against height. Examples: .. plot:: :include-source: import numpy as np import matplotlib.pyplot as plt import typhon.plots p = typhon.math.nlogspace(1000e2, 0.1e2, 50) # pressure in Pa. x = np.exp(p / p[0]) fig, ax = plt.subplots() typhon.plots.profile_p(p, x, ax=ax) plt.show() """ if ax is None: ax = plt.gca() # Determine min/max pressure of data in plot. The current axis limits are # also taken into account. This ensures complete data coverage when using # the function iteratively on the same axis. pmin = np.min((np.min(p), *ax.get_ylim())) pmax = np.max((np.max(p), *ax.get_ylim())) ax.set_ylim(pmax, pmin) # implicitly invert yaxis # Label and format for yaxis. formatter.set_yaxis_formatter(formatter.HectoPascalFormatter(), ax=ax) if ax.is_first_col(): ax.set_ylabel('Pressure [hPa]') # Actual plot. return ax.plot(x, p, **kwargs)
def profile_p_log(p, x, ax=None, **kwargs): """Plot atmospheric profile against pressure in log space. This function is a wrapper for :func:`~typhon.plots.profile_p`: The input values as well as additional keyword arguments are passed through and the yscale is set to "log". Parameters: p (ndarray): Pressure [Pa]. x (ndarray): Atmospheric property. ax (AxesSubplot): Axes to plot in. **kwargs: Additional keyword arguments passed to `plt.plot`. See also: :func:`~typhon.plots.profile_p` Plot profile against pressure in linear space. :func:`~typhon.plots.profile_z` Plot profile against height. Examples: .. plot:: :include-source: import numpy as np import matplotlib.pyplot as plt import typhon.plots p = typhon.math.nlogspace(1000e2, 0.1e2, 50) x = np.exp(p / p[0]) fig, ax = plt.subplots() typhon.plots.profile_p_log(p, x, ax=ax) plt.show() """ if ax is None: ax = plt.gca() # Call ``set_yscale`` before plot to prevent reset of axis inverting in # matplotlib 3.1.0 (https://github.com/matplotlib/matplotlib/issues/14620) ax.set_yscale('log') ret = profile_p(p, x, ax=ax, **kwargs) # Set logarithmic scale. formatter.set_yaxis_formatter(formatter.HectoPascalLogFormatter(), ax=ax) return ret
def plot_from_konrad_diff(variable,exps,exp_ref, same=False, delta=10, delta_ref=5, xrefline=0, xrefline_ref=None, title=None, labels=None, styles=None, label_ref=None, style_ref=None ): """Plots variable profiles from several `konrad` experiments in relation to a given reference experiment. Parameters ---------- variable : str Variable name in the output file. exps : list List of strings describing the paths to the output files. exp_ref : str String describing the path to the output file for the reference experiment. same : bool, optional If `True`, profiles are plotted in the same pair of axes. Otherwise, there are as many pairs of axes as profiles (`False` is the default). Reference profile has always its own pair of axes. delta : scalar, optional Offset added to the extrema of the data. delta_ref : scalar, optional Offset added to the extrema of the reference data. xrefline : scalar, optional If `same` is `True`, plots a vertical reference line at the given scalar value. If `same` is `False`, plots vertical reference lines at each axis. By default the lines are zero lines. xrefline_ref : scalar or `None` optional Plots a vertical reference line at the given scalar value. If `None`, no reference line is plotted: this is the default. title : str or `None`, optional An overarching title for the figure (`None` is the default). labels, styles : dict or `None`, optional Dictionaries containing profile labels and line styles. Usually created by zipping two lists, e.g. `labels = dict(zip(exps,labels))`. The `styles` dictionaries are passed as keyword arguments to the `plt.plot` function. If `None`, one gets default styles and/or labels. label_ref : str or `None`, optional String containing reference profile label. style_ref : dict or `None`, optional Dictionary containing reference profile line styles. Returns ------- fig : matplotlib.Figure Figure with the plots. axes : matplotlib.Axes Axes for the figure. """ (p, data,minimum_diff,maximum_diff, minimum_ref,maximum_ref ) = get_from_konrad_ref(variable,exps,exp_ref) # Gets the data n = len(list(data.keys())) # Experiment count ext_exps = list(data.keys()) # Experiment list width = 2 # Width (two pairs) height = 5 # Height if same: fig = plt.figure(dpi=300,figsize=(width*2,height)) axes = { "ref" : fig.add_subplot(1,2,1), "diff" : fig.add_subplot(1,2,2) } for e in data: # Plotting ax = axes["diff"] labelsd = labels stylesd = styles if e == exp_ref: ax = axes["ref"] labelsd = label_ref stylesd = style_ref if isinstance(label_ref,str): labelsd = { e : label_ref } if isinstance(style_ref,dict): stylesd = { e : style_ref } if labelsd == None: if stylesd == None: ax.plot(data[e],p) elif stylesd[e] == None: ax.plot(data[e],p) else: ax.plot(data[e],p,**stylesd[e]) elif labelsd[e] == None: if stylesd == None: ax.plot(data[e],p) elif stylesd[e] == None: ax.plot(data[e],p) else: ax.plot(data[e],p,**stylesd[e]) else: if stylesd == None: ax.plot(data[e],p,label=labelsd[e]) elif stylesd[e] == None: ax.plot(data[e],p,label=labelsd[e]) else: labels_and_styles=stylesd[e] labels_and_styles["label"]=labelsd[e] ax.plot(data[e],p,**labels_and_styles) for e in axes: ax=axes[e] ax.invert_yaxis() # Settings for y-axes ax.set_yscale("log") if e != "ref": ax.tick_params(axis='y',which='both',labelleft=False) if e == "ref": formatter.set_yaxis_formatter(formatter.HectoPascalLogFormatter(), ax=ax) ax.tick_params(axis='y',which='both',labelsize=6) ax.set_ylabel(p_a,fontsize=6) if e != "ref": # Settings for x-axes ax.set_xlim(minimum_diff - delta,maximum_diff + delta) ax.set_xlabel(Dvariable_label[variable],fontsize=6) if e == "ref": ax.set_xlim(minimum_ref - delta_ref,maximum_ref + delta_ref) ax.set_xlabel(variable_label[variable],fontsize=6) ax.tick_params(axis='x',which='both',labeltop=False,labelsize=6) ax.minorticks_off() # Unsets minor ticks if e != "ref": # Reference line ax.axvline(x=xrefline,lw=0.7,color=(0,0,0)) if ( e == "ref" and xrefline_ref != None ): ax.axvline(x=xrefline_ref,lw=0.7,color=(0,0,0)) if e != "ref": ax.legend(fontsize=5) # Legend if ( e == "ref" and label_ref != None ): ax.set_title(label_ref,fontsize=5) else: fig = plt.figure(dpi=300,figsize=(width*n,height)) axes = { ext_exps[i-1] : fig.add_subplot(1,n,i) for i in range(1,n+1) } for e in axes: # Plotting ax = axes[e] labelsd = labels stylesd = styles if e == exp_ref: labelsd = label_ref stylesd = style_ref if isinstance(label_ref,str): labelsd = { e : label_ref } if isinstance(style_ref,dict): stylesd = { e : style_ref } if labelsd == None: if stylesd == None: ax.plot(data[e],p) elif stylesd[e] == None: ax.plot(data[e],p) else: ax.plot(data[e],p,**stylesd[e]) elif labelsd[e] == None: if stylesd == None: ax.plot(data[e],p) elif stylesd[e] == None: ax.plot(data[e],p) else: ax.plot(data[e],p,**stylesd[e]) else: if stylesd == None: ax.plot(data[e],p,label=labelsd[e]) elif stylesd[e] == None: ax.plot(data[e],p,label=labelsd[e]) else: labels_and_styles=stylesd[e] labels_and_styles["label"]=labelsd[e] ax.plot(data[e],p,**labels_and_styles) ax.invert_yaxis() # Settings for y-axes ax.set_yscale("log") if e != exp_ref: ax.tick_params(axis='y',which='both',labelleft=False) if e == exp_ref: formatter.set_yaxis_formatter(formatter.HectoPascalLogFormatter(), ax=ax) ax.tick_params(axis='y',which='both',labelsize=6) ax.set_ylabel(p_a,fontsize=6) if e != exp_ref: # Settings for x-axes ax.set_xlim(minimum_diff - delta,maximum_diff + delta) if e == exp_ref: ax.set_xlim(minimum_ref - delta_ref,maximum_ref + delta_ref) if e != exp_ref: ax.set_xlabel(Dvariable_label[variable],fontsize=6) if e == exp_ref: ax.set_xlabel(variable_label[variable],fontsize=6) ax.tick_params(axis='x',which='both',labeltop=False,labelsize=6) ax.minorticks_off() # Unsets minor ticks if e != exp_ref: # Reference line ax.axvline(x=xrefline,lw=0.7,color=(0,0,0)) if ( e == exp_ref and xrefline_ref != None ): ax.axvline(x=xrefline_ref,lw=0.7,color=(0,0,0)) if e != exp_ref: # Set axes titles ax.set_title(labels[e],fontsize=5) if ( e == exp_ref and label_ref != None ): ax.set_title(label_ref,fontsize=5) if title != None: # Title settings fig.suptitle(title,fontsize=5,y=0.95) fig.set_tight_layout("tight") # Other settings return (fig,axes)
def plot_from_konrad(variable,exps, same=False, delta=10, xrefline=None, title=None, labels=None, styles=None ): """Plots variable profiles from several `konrad` experiments. Parameters ---------- variable : str Variable name in the output file. exps : list List of strings describing the paths to the output files. same : bool, optional If `True`, profiles are plotted in the same pair of axes. Otherwise, there are as many pairs of axes as profiles (`False` is the default). delta : scalar, optional Offset added to the extrema of the data. xrefline : scalar or `None`, optional If `same` is `True`, plots a vertical reference line at the given scalar value. If `same` is `False`, plots vertical reference lines at each axis. If `None`, plots no vertical reference lines (`None` is the default). title : str or `None`, optional An overarching title for the figure (`None` is the default). labels, styles : dict or `None`, optional Dictionaries containing profile labels and line styles. Usually created by zipping two lists, e.g. `labels = dict(zip(exps,labels))`. The `styles` dictionaries are passed as keyword arguments to the `plt.plot` function. If `None`, one gets default styles and/or labels. Returns ------- fig : matplotlib.Figure Figure with the plots. axes : matplotlib.Axes Axes for the figure. """ (p,data,minimum,maximum) = get_from_konrad(variable,exps) # Gets the data n = len(exps) # Experiment count width = 1 # Width (one pair) height = 5 # Height if same: fig = plt.figure(dpi=300,figsize=(3*width,height)) axes = fig.add_subplot(1,1,1) for e in data: # Plotting ax = axes if labels == None: if styles == None: ax.plot(data[e],p) elif styles[e] == None: ax.plot(data[e],p) else: ax.plot(data[e],p,**styles[e]) elif labels[e] == None: if styles == None: ax.plot(data[e],p) elif styles[e] == None: ax.plot(data[e],p) else: ax.plot(data[e],p,**styles[e]) else: if styles == None: ax.plot(data[e],p,label=labels[e]) elif styles[e] == None: ax.plot(data[e],p,label=labels[e]) else: labels_and_styles = styles[e] labels_and_styles["label"] = labels[e] ax.plot(data[e],p,**labels_and_styles) ax = axes ax.invert_yaxis() # Settings for y-axis ax.set_yscale("log") formatter.set_yaxis_formatter(formatter.HectoPascalLogFormatter(), ax=ax) ax.tick_params(axis='y',which='both',labelsize=6) ax.set_ylabel(p_a,fontsize=6) ax.set_xlim(minimum - delta,maximum + delta) # Settings for x-axis ax.tick_params(axis='x',which='both',labeltop=False,labelsize=6) ax.set_xlabel(variable_label[variable],fontsize=6) ax.minorticks_off() # Unsets minor ticks if xrefline != None: # Reference line ax.axvline(x=xrefline,lw=0.7,color=(0,0,0)) ax.legend(fontsize=5) # Legend else: fig = plt.figure(dpi=300,figsize=(n*width,height)) axes = { exps[i-1] : fig.add_subplot(1,n,i) for i in range(1,n+1) } for e in axes: # Plotting ax = axes[e] if labels == None: if styles == None: ax.plot(data[e],p) elif styles[e] == None: ax.plot(data[e],p) else: ax.plot(data[e],p,**styles[e]) elif labels[e] == None: if styles == None: ax.plot(data[e],p) elif styles[e] == None: ax.plot(data[e],p) else: ax.plot(data[e],p,**styles[e]) else: if styles == None: ax.plot(data[e],p,label=labels[e]) elif styles[e] == None: ax.plot(data[e],p,label=labels[e]) else: labels_and_styles = styles[e] labels_and_styles["label"] = labels[e] ax.plot(data[e],p,**labels_and_styles) ax.invert_yaxis() # Settings for y-axes ax.set_yscale("log") if e != exps[0]: ax.tick_params(axis='y',which='both',labelleft=False) if e == exps[0]: formatter.set_yaxis_formatter(formatter.HectoPascalLogFormatter(), ax=ax) ax.tick_params(axis='y',which='both',labelsize=6) ax.set_ylabel(p_a,fontsize=6) ax.set_xlim(minimum - delta,maximum + delta) # Settings for x-axes ax.tick_params(axis='x',which='both',labeltop=False,labelsize=6) ax.set_xlabel(variable_label[variable],fontsize=6) ax.minorticks_off() # Unsets minor ticks if xrefline != None: # Reference line ax.axvline(x=xrefline,lw=0.7,color=(0,0,0)) ax.set_title(labels[e],fontsize=5) # Sets axes titles if title != None: # Title settings fig.suptitle(title,fontsize=5,y=0.95) fig.set_tight_layout("tight") # Other settings return (fig,axes)