SnowLense
This is a module for plotting Snow profiles read from .pro files ( and soon SMET time series).
Usage
Either you directly use the SnowpackPlotter class, or the plotProfile function. Or, the recommended way, use the wrapper functions which check the arguments and keywords, and give some assistance, when something is wrong.
There is a help function available, which takes exactly the same arguments as the plot function, and will give an overview of what will happen.
All plotting functions return a figure, and optionally the SnowpackPlotter object. However, the figure is closed before returning, to increase performance (the overhead can become quite large). To display the figure, use the built in show_figure() function (and plt.show() if you are not using a notebook)
Note
Any unknown keyword argument will be passed to matplotlibs plotting functions, so be careful about spelling mistakes, as they will throw an error.
Please be aware that indicating the mfcrust with lines might be a an expensive computation, and may take a while. If you are looking to just see where it is, i would recommend using the mfcrust_color kwarg, to highlight it in orange.
Examples
This part is used before all the examples below:
from snowpat import snowpackreader as spr
from snowpat import SnowLense as sl
import datetime
pro = spr.readPRO("test.pro")
pro.discard_below_ground(discard=True) # do operations as you wish
profile = pro.get_profile_nr(300) # get a single profile for plotting later (profile at the 300th date)
date = datetime.datetime(2022, 11, 7, 12, 0, 0) # set a date to read a profile at
var_codes_to_plot = ["0513, 0503"] # Per default only grain type, i.e. 0513 is plotted
var_codes_to_plot = [pro.name_to_code("grain type"), pro.name_to_code("element temperature")] # will give the same as above
The Wrapper functions plot, help
This makes it easy to use the functionality of the plotting, with some checks being performed on the keyword arguments, and a help function that takes the same signature as the plotting function.
# the plot function returns the figure, and a plotter object, which also stores the figure
# if outfile is given, the figure will directly be saved
fig, plotter = sl.plot(pro, var_codes=var_codes ,outfile="test.png", ind_mfcrust=False, n_cols=2)
# some checks on the arguments are done before plotting. And if you need help use:
sl.help(pro, var_codes=var_codes ,outfile="test.png", ind_mfcrust=False, n_cols=2)
# or just
sl.help(pro)
# this will throw an exception as colorbar is not supposed to be a string
sl.help(pro, var_codes=var_codes , colorbar="foo")
# to plot a single profile:
fig,_ = sl.plot(profile, **kwargs)
# and as well
sl.help(profile)
# can also be done by giving a day to the plotter object
fig, plotter = sl.plot(pro, profile_on=date)
The SnowpackPlotter
# set up an object
plotter = sl.SnowpackPlotter(pro,savefile="test.png")
# plot needs a list of variable codes that should be plotted, it returns the figure, but also stores it
fig = plotter.plot(var_codes=var_codes)
# to display it with
sl.show_figure(fig)
# or
plotter.show()
# plt.show () # if you are not using an interactive python interpreter
plotter.save() # uses the filename given at initialisation (if given)
# or
plotter.save("test.png")
# to plot a profile out of it:
fig_profile = plotter.plotProfileOn(date)
Adjust plots retrospectively
If you want to edit, or customize parts of the plot that is returned, you can obtain the figure object and get an axes object as usual with plt.Figure.get_axes() and then index it accordingly. Additionally, a convenience function that directly returns the required axes object exists with SnowLense.SnowpackPlotter.getSubplot(idx:Int).
# get the subplot with index i, start counting top left, and go to the right, if more than 1 column
ax = plotter.getSubplot(1)
# add a title
ax.set_title("Title")
# the full figure object
fig_latest = plotter.getLatestFigure()
Single Profile Plot
This can be done with:
fig_profile = sl.plotProfile(profile, out="test.png", ind_mfcrust=True, standardized_limits=True)
Handle Specific Processing Requirements
If you want to do some data processing on part of the data you can give a processing function; Colormaps, and Normalizations, as well as labels for the colorbar, for each variable to plot
The data editing function needs to take a variable code, and the data for 1 variable at 1 time point as input, and return the data in the same format (np.ndarray [n_layers,])
import numpy as np
def edit_data(var_code:str, data:np.ndarray): # This is a dummy function to show how to edit the data
new_data = data.copy() # !!! be careful to always operate on a copy of the data, otherwise it will change the stored data!!
if var_code == "0503":
new_data = data + 273.15 # For example change Temperature to Kelvin
# if var code == ... # do processing for other variables
# ...
return new_data
cmap = {"0503":"plasma"} # We want to use this colormap for some reason
import matplotlib.colors as mcolors
# you might need to give a new norm then (Here because data is in another range)
norm = {"0503": mcolors.Normalize(vmin=250, vmax=280)}
# and now the colorbar label is going to be wrong, as originally it was in Celsius
# so we need to change it
cbar_label = {"0503": "Temperature [K]"}
# now we give everything to our plotting function (use keywords, and not just hand over the variables)
fig, plotter = sl.plot(pro, var_codes=var_codes, adjust_data=edit_data, cmap=cmap, norm=norm, ind_mfcrust=False, cbar_label=cbar_label)
# to show the figure again:
sl.show_figure(fig)