Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Declarative Plotting Interface Improvements #1016

Open
5 tasks
jrleeman opened this issue Mar 14, 2019 · 13 comments · Fixed by #2156
Open
5 tasks

Declarative Plotting Interface Improvements #1016

jrleeman opened this issue Mar 14, 2019 · 13 comments · Fixed by #2156
Labels
Area: Plots Pertains to producing plots Epic Describes larger effort that is broken down into smaller issues GEMPAK Conversion Needed to replicate GEMPAK functionality

Comments

@jrleeman
Copy link
Contributor

jrleeman commented Mar 14, 2019

After using the declarative plotting interface in some examples, here are some suggestions for improvements to the declarative plotting interface. I'd propose that this is a 'living issue' and contributed to by any and all with individual issues/PRs being raised as this wish list is addressed.

  • Currently any out of order execution (common in the notebooks) causes errors. I don't know if we can fix that due to the way the internals work, but at least documenting this and setting best practices of all declarative plotting calls in a single notebook cell might be best.
  • Layout of plots does not work as one might initially expect. Currently we set the layout attribute on a panel with a tuple of the location as in matplotlib. (1, 2, 2) While that behavior is fine, when adding panels to the panel container we just pass a simple list. It would be desirable to have the capability to not set the layout attribute and determine the layout by passing a list of lists. For example to layout a 2x2 figure it would be pc.panels = [[p1, p2], [p3, p4]].
  • Currently if you want the same contour plot on two different panels, you have to create the contour plots twice as they cannot be reused. This seems like a pitfall as it requires duplication of code and cycles. I can see many scenarios like wanting contoured heights on two different panels in the same panel container.
  • Adding an XY plot would be good so panels with time, temperature graphs, etc could be added.
  • When Add function to find local extrema and plot separately #1689 is solved, add an attribute that ties into the max/min plotting (akin to the GEMPAK HILO parameter).
@jrleeman jrleeman added Area: Plots Pertains to producing plots Epic Describes larger effort that is broken down into smaller issues GEMPAK Conversion Needed to replicate GEMPAK functionality labels Mar 14, 2019
@kgoebber
Copy link
Collaborator

kgoebber commented Mar 15, 2019

I've played a bit with the declarative syntax and here are some of the things that would be nice to have incorporated. Some easier than others, but want to document them here.

  • Improve documentation of trait settings for declarative plotting classes. For example, setting the contour trait currently has the description of A trait type representing a Union type. Huh? We'll need some examples of typical settings for each of the traits in the documentation.

  • Ability to easily convert units (e.g., temperature in Kelvin to Celsius). I've overcome this by assigning a new variable to the dataset, its not too bad, but seems like overkill just to get a different unit of the same variable.

  • Ability to change linestyle (e.g., specify dotted or dashed lines)

  • I'm not a huge fan of the current "contours" set-up. For GEMPAK users they have been used to giving a contour interval if only a single number is given, not the number of contours to plot. Would be great to have the ability to set just a contour interval or a tuple of (cint, start, stop) or something similar

  • Contour labels

  • Ability to invoke smoothing of data (e.g., geopotential height field so it is not overly "wavy" over mountainous terrain

  • Multiple title locations for a given map. I typically use plt.title to plot a left and right title, would be nice feature to have.

  • colorfill plots (plt.contourf) with needed colorbar and setting of colormaps and norms

  • Add wind barbs to the plots, again might need ability to convert units as most model data is in m/s, but we plot knots

  • An ability to save the figure instead of just showing

  • Use a calculation to plot a variable (e.g., wind speed, absolute vorticity). This is the hardest for sure and likely won't be able to be tackled for a while, but I'll record it here nonetheless. We should be able to get some examples out that show how to do a calculation and add it to the dataset for plotting as it is not too hard, but would be nice to have this feature eventually.

@dopplershift
Copy link
Member

dopplershift commented May 15, 2019

Documentation can be improved by:

  1. Writing non-crappy docstrings for the properties--I just didn't think about them being user-facing when I wrote them.

  2. Can attach documentation to traitlets:

class Plot2D(HasTraits):
    field = Unicode()
    field.__doc__ = """Name of field to plot

    More documentation about field.
    """

this would override the documentation that's built-in. Unfortunately, as noted in ipython/traitlets#461, providing the help parameter to the Trait constructor does not help the sphinx docs. The solution there about putting triple-quoted string also only works for the class where the trait is defined--subclasses revert back to the regular Trait documentation.

@sgdecker
Copy link
Contributor

I see a checkmark next to "Improve documentation of trait settings..." above, but when I try this in a notebook:

from metpy.plots.declarative import PlotObs
obs = PlotObs()
obs?

I get:

Type:        PlotObs
String form: <metpy.plots.PlotObs object at 0x7fc850162e50>
File:        ~/local/miniconda3/envs/met433/lib/python3.9/site-packages/metpy/plots/__init__.py
Docstring:  
The highest level class related to plotting observed surface and upperair data.

This class collects all common methods no matter whether plotting a upper-level or
surface data using station plots.

List of Traits:
  * level
  * time
  * fields
  * locations (optional)
  * time_window (optional)
  * formats (optional)
  * colors (optional)
  * plot_units (optional)
  * vector_field (optional)
  * vector_field_color (optional)
  * vector_field_length (optional)
  * vector_plot_units (optional)
  * reduce_points (optional)
  * fontsize (optional)

Ideally, each trait would have a one-line definition included (similar to what you see when you first run, say, sfmap)

Then, trying obs.time? produces:

Type:        NoneType
String form: None
Docstring:   <no docstring>

until I define it. Then I get:

Type:        datetime
String form: 2021-08-10 12:00:00
File:        ~/local/miniconda3/envs/met433/lib/python3.9/datetime.py
Docstring:  
datetime(year, month, day[, hour[, minute[, second[, microsecond[,tzinfo]]]]])

The year, month and day arguments are required. tzinfo may be None, or an
instance of a tzinfo subclass. The remaining arguments may be ints.

which is more informative, but presents something of a bootstrap problem to the user, as you don't necessarily know how to define a trait w/o the documentation in the first place. In GEMPAK, I can do (p)help dattim whether I've set that parameter to anything or not. Yes, you can go to documentation in another browser tab, but it does reduce the introspection some.

@sgdecker
Copy link
Contributor

To be more specific, the documentation here is great:
https://unidata.github.io/MetPy/latest/api/generated/metpy.plots.PlotObs.html#metpy.plots.PlotObs

The Attributes Summary is basically what I'm looking to be included in the output of ? in the notebook (and note the list of attributes is a superset of the list of traits that appears now).

Actually, doing help(obs) is pretty comprehensive, but the ordering is a bit strange (from a newbie/student perspective) and is a bit excessive in terms of exposing a lot of internals that 99% of users don't need to know.

Maybe what we have is the best it can be, but there is a bit of friction here.

@sgdecker
Copy link
Contributor

It looks like #2016 may address some of this, but looking through the traitlets documentation, I wonder if adding @default functions would address my main issue, so that typing obs.time? would generate documentation even before obs.time is set to some value by the user.

I might play around with this and see what happens.

@dopplershift
Copy link
Member

If you come up with any leads on things that help address the shortcomings you're running into, we're happy to take a look.

@sgdecker
Copy link
Contributor

sgdecker commented Aug 24, 2021

I don't think I see this one above:

  • Allow user to pick a color other than black for the MapPanel layers

#1691 is related.

@dopplershift
Copy link
Member

@kgoebber I know we talked about coloring map layers before, and now I don't remember where we ended up. I have a fuzzy inkling around "I don't want to add a ton of styling traits..."

@kgoebber
Copy link
Collaborator

kgoebber commented Aug 24, 2021 via email

@sgdecker
Copy link
Contributor

sgdecker commented Aug 27, 2021

  • Eliminate the huge margins that result when saving a figure to PDF format.

I know there are ways to accomplish this when using matplotlib directly, but I haven't discovered a way to achieve the same effect with the declarative interface.

  • Add a built-in formatter function equivalent to GEMPAK's STDZ parameter, accessible from PlotObs.formats, which converts geopotential height observations to the standard three-character abbreviation if the level being plotted is a standard/mandatory level. Examples:
Level Value Displayed as
850 1504 504
700 3010 010
500 5524 552
300 9001 900
200 12346 235
  • Provide a similar SLP formatter so that the lambda function that appears in many examples is unnecessary.

@dopplershift
Copy link
Member

@sgdecker #2425 gives control to map feature color/linewidth.

@sgdecker
Copy link
Contributor

sgdecker commented Dec 7, 2022

[ ] When #1689 is solved, add an attribute that ties into the max/min plotting (akin to the GEMPAK HILO parameter).

@kgoebber
Copy link
Collaborator

kgoebber commented Dec 7, 2022

@sgdecker Yes, I think that would be good to do. I do have some code that finds extrema and is in a couple of the examples on the old gallery site, but I need to refine it and make the contribution.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Area: Plots Pertains to producing plots Epic Describes larger effort that is broken down into smaller issues GEMPAK Conversion Needed to replicate GEMPAK functionality
Projects
None yet
Development

Successfully merging a pull request may close this issue.

5 participants