The problem
To able to make a nice profile plot function with annotated heights (like #15) the necessary physical variables will need to be present in the dataset (ds), so that when the user provides:
def plot_profiles_1d(ds, variables=["T", "rh", "qv"], height_labels=["z_RHmax", "z_INV"]):
the functions that calculate z_RHmax and z_INV can find the correct fields inside ds.
I think there are basically two ways of doing this:
a) We assume what the fields should be called and require the user to
rename fields (or maybe set the standard_name) attribute
b) We pass in the mapping for the variables as we do it not with kwargs.
I'm worried that option b) might get quite messy. This is because we're here calling a plotting function and then that plotting function calls the underlying function required to calculate the different heights (for example z_maxRH). So we'd need to define a mapping that the plot function can pass down to z_maxRH. If we're making use of a mapping anyway maybe we should just make the user rename things on their dataset with e.g.
ds_fixed = ds.rename(dict(temp="temperature", RH="rh"))
Suggested solution
I think we should go with option a). What we could do to make this nicer for the user is:
- Inform the user what fields are missing and what that field should contain physically, i.e. we'd check for the existence of a variable in a dataset and then raise an exception like:
raise Exception("Couldn't find the variable `{var_name}` in the provided dataset."
"To use {plot_function_name} you need to provide the "
"`{field_description}` as `{var_name}`")
- Optionally, we could allow the user to use CF-convention "standard name" attributes for variables. That way they don't need to rename fields, but simply set the correct "standard name", which many data files already will have.
Implementation details
To make all this work I was thinking we could simply use "standard names" in our code (based on cf-conventions where they exist) and make a module that defines this nomenclature. Something like this:
eurec4a_environment/nomenclature.py:
RELATIVE_HUMIDITY = "relative_humidity"
TEMPERATURE = "air_temperature"
this could be used inside a function as:
import eurec4a_environment.nomenclature as nom
def calc_maxRH_height(ds, z_min=200, z_max=900):
da_rh = _get_field(ds, v=nom.RELATIVE_HUMIDITY)
And _get_field would then handle the checking for fields, returning them and raising helpful exceptions.
Thoughts?
The problem
To able to make a nice profile plot function with annotated heights (like #15) the necessary physical variables will need to be present in the dataset (
ds), so that when the user provides:the functions that calculate
z_RHmaxandz_INVcan find the correct fields insideds.I think there are basically two ways of doing this:
a) We assume what the fields should be called and require the user to
rename fields (or maybe set the
standard_name) attributeb) We pass in the mapping for the variables as we do it not with kwargs.
I'm worried that option b) might get quite messy. This is because we're here calling a plotting function and then that plotting function calls the underlying function required to calculate the different heights (for example
z_maxRH). So we'd need to define a mapping that the plot function can pass down toz_maxRH. If we're making use of a mapping anyway maybe we should just make the user rename things on their dataset with e.g.Suggested solution
I think we should go with option a). What we could do to make this nicer for the user is:
Implementation details
To make all this work I was thinking we could simply use "standard names" in our code (based on cf-conventions where they exist) and make a module that defines this nomenclature. Something like this:
eurec4a_environment/nomenclature.py:this could be used inside a function as:
And
_get_fieldwould then handle the checking for fields, returning them and raising helpful exceptions.Thoughts?