Reorganize attribute documentation
The current documentation for attributes could use some refreshing.
- Most attributes cannot be searched directly in the search bar (known problem). Ideally the way that attributes are documented should be done in a way where they can be searched. Maybe we should replace the table with something closer to the API page?
- Attributes are not organized well. Organizing them into series, plot, subplot, and axis is something I have found very confusing.
- In particular, typing something like
plotattr(:Subplot)in the REPL outputs a large list of attributes. This hinders discoverability and accessibility. In my experience, I have always had to look through all four tabs in the docs to look for an attribute. - What would be better for
plotattr(:Subplot)is to reorganize the categories into things like Annotation, Background, Foreground, Colorbar, Legend, Title, as well as a few others. A lot of the attribute names in this list heavily suggest this anyway. This way, when one needs to find attributes related to the legend, there is a clearly labeled tab in the docs for that, or typing e.g.plotattr(:Legend)would yield all of its relevant attributes (cf. this issue)
- In particular, typing something like
- The types required for the attributes are not always intuitive. For example,
colorbar_tickscould use some explaining on the different possible argument types, asUnion{Symbol, Tuple{AbstractVector{Real}, AbstractVector{AbstractString}}, AbstractVector{Real}}is not obvious how to interpret. Also, a lot of attributes have no description.
A documentation style like that on the API page would be able to solve these problems simply by allowing more room for the description, explanation of types, and examples. Categorizing them into titles like Colorbar, Legend, etc. would keep these pages manageable in length.
These are good suggestions IMHO. See also https://github.com/JuliaPlots/Plots.jl/issues/676 bit unsure whether this https://github.com/JuliaPlots/Plots.jl/issues/2337 should still be open
Point 1. has finally been fixed yesterday (https://github.com/JuliaPlots/PlotDocs.jl/pull/318 - https://github.com/JuliaPlots/PlotDocs.jl/pull/320). When searching for e.g. show_empty_bins, a search results pointing to https://docs.juliaplots.org/stable/generated/attributes_series/ is proposed.
You can search for attributes but also aliases now.
Not sure about 2. (I am not sure that the proposed approach would enhance clarity).
Point 3. is a julia language pre-requisite and has nothing to do with Plots, although since beginners are likely to use Plots rapidly, we could maybe add a link to https://docs.julialang.org/en/v1/manual/types/#Type-Unions and a note in the attributes page. Maybe somewhere around here: https://github.com/JuliaPlots/PlotDocs.jl/blob/master/src/PlotDocs.jl#L267-L270.
Point 1. has finally been fixed yesterday (#318 - #320). When searching for e.g.
show_empty_bins, a search results pointing to https://docs.juliaplots.org/stable/generated/attributes_series/ is proposed. You can search for attributes but also aliases now.
If I search show_empty_bins, the relevant hits with the list of attributes are the last two. I'm not sure about the details of the search mechanism with Documenter.jl. This may be an issue with that package.
If I search markersize, the first result should point straight to the page that has the information about this attribute. But this page is far down the list, and it's not obvious which one. (It's the one called "Series Attributes") Also, if I search for its alias ms, it's basically at the bottom of the results.
Maybe the attribute pages need to be prioritized more in the search results.
Not sure about 2. (I am not sure that the proposed approach would enhance clarity).
I think it would enhance clarity greatly. I'm not the only one that has been frustrated with finding attribute documentation. See here, here, here. Also, anecdotes from my friends. I'm motivated to fix this partly because this was by far the most frustrating thing about learning Julia for me.
I remember trying to figure out how to manipulate the legend and could not figure out which one of Series, Plot, Subplot, and Axis had the entries for legend attributes, even after many iterations. But if they were all listed under a section called "Legend Attributes," it would be obvious. Legend attributes was particularly confusing since one can have a plot of lines and points all on the same canvas, with one legend, and yet the attributes are listed under Subplot, not Plot.
Point 3. is a
julialanguage pre-requisite and has nothing to do withPlots, although since beginners are likely to usePlotsrapidly, we could maybe add a link to https://docs.julialang.org/en/v1/manual/types/#Type-Unions and a note in the attributes page. Maybe somewhere around here: https://github.com/JuliaPlots/PlotDocs.jl/blob/master/src/PlotDocs.jl#L267-L270.
The type system is indeed something baked into the language itself. However, it is a good idea to explain the types and give examples of the possible values that it can take. This is especially important since beginners and many end-users do not regularly use or encounter abstract types, yet these are the very people that probably want to understand what the attributes mean.
To give another example, bins has the type
Union{Integer, Symbol, Tuple{Integer, Integer}, AbstractVector}
but a lot of people don't know that StepRange <: AbstractVector, or may be confused by Int vs. Integer.
Instead, here is how I would write the following doc entry:
bins :: Union{Integer, Symbol, Tuple{Integer, Integer}, AbstractVector}
Defines the number of bins. Aliases :bin, :nb, :nbin, :nbins.
Can take in one of the following types:
Integer– defines the approximate number of bins to aim for. Not guaranteed to give the exact value.bins=10gives a 1D histogram with about 10 bins.bins=10gives a 2D histogram with about 10 bins for each dimension.
Tuple{Integer, Integer}– for two-dimensional histograms, defines the approximate number of bins per dimension. Not guaranteed to give the exact values.bins=(10, 20)gives a 2D histogram with about 10 bins for thexdimension and about 20 bins for theydimension.
Symbol– defines the auto-binning algorithm to use.:sturges– Sturges' rule:sqrt– Square root rule:rice– Rice rule:scott– Scott's normal reference rule:fd(default) – Freedman-Diaconis' rule
AbstractVector– defines a vector of values for bin edges.bins=range(-10, 10, length=21)gives a histogram with bins starting from -10, ending at 10, and containing 21 break values, giving 20 bins.
Relevant attribute for the following series types:
This is the type of entry I'd like to see for every single attribute that exists.
If I search show_empty_bins, the relevant hits with the list of attributes are the last two. I'm not sure about the details of the search mechanism with Documenter.jl. This may be an issue with that package.
Yeah well I didn't say it was perfect. The current solution is monkey patching the domify method from Documenter in order to tweak the search index when using raw html tables:
https://github.com/JuliaPlots/PlotDocs.jl/blob/48095129f658a04706481b788cc134bed65fc357/docs/make.jl#L14-L48
I agree that it would be better to weight the search result in order to make the result appear at the top of the results. As you can see in search.js, there is a boost field, that we could use to tweak the search order. I gave it a try but couldn't find a solution while implementing https://github.com/JuliaPlots/PlotDocs.jl/pull/318 (which in the end is just a hack).
But if they were all listed under a section called "Legend Attributes," it would be obvious.
That could work, but that would need some effort to integrate smoothly in Plots and PlotDocs. It's "only" a matter of putting in development time, and producing something not being too convoluted and difficult to maintain because of its complexity.
Instead, here is how I would write the following doc entry:
That looks nice indeed. Currently you can see that the description types are defined here. If you can make it work without increasing the complexity too much I'd be happy to integrate this, but be aware that implementing a clean and generic solution for the arguments and their description might be non-trivial.
With the entry I wrote, I think it's a bit too complex to be included as part of a dictionary. The majority of attributes won't be as complex as bins, but there are still quite a few that need more than a few lines to completely document.
My idea is the tables should be replaced with pages that resemble the API page. The disadvantages with the tables right now is that the attributes cannot directly be searched, and the amount of information for a given attribute is softly constrained by a box. (Not an actual constraint...but the dictionary+table format strongly suggests terse descriptions) Additionally, there seems to be a lot of inherent complications that are coming from the fact that it's the Plots.jl repository generating the attribute tables.
With the API pages, all the information I wrote can be put into an entry for bins and formatted just like above, and it will also be easier to search for the particular attribute in the search bar (but enhancing the search itself should be a separate issue).
One issue is how to include this information in the REPL. Right now, typing plotattr("bins") gives the information, but it is different than typing ?bins since bins has to be a method, and ?plotattr("bins") won't work. Is there a way to make this work if the attributes were documented on an API page? I understand that this is not how keywords are normally documented...
I'm willing to put in the work to recategorize all of the attributes and create separate API pages for each of them. Just want to figure out the best way to approach this.
One way to recategorize them is the following:
- Series attributes stay the same. On the API page, every entry contains a "Relevant attribute for the following series types:" list that denotes all of the series types which the attribute can modify.
- Plot attributes is renamed to Global attributes. This is probably a less ambiguous word to refer to those attributes which impact the entire plot.
- Subplot attributes are split up into the following categories:
- Annotation attributes:
annotationcolorannotationfontfamilyannotationfontsizeannotationhalignannotationrotationannotationsannotationvalign - Colorbar attributes:
climscolorbarcolorbar_continuous_valuescolorbar_discrete_valuescolorbar_fontfamilycolorbar_formattercolorbar_scalecolorbar_tickfontcolorcolorbar_tickfontfamilycolorbar_tickfonthaligncolorbar_tickfontrotationcolorbar_tickfontsizecolorbar_tickfontvaligncolorbar_tickscolorbar_titlecolorbar_title_locationcolorbar_titlefontcolorcolorbar_titlefontfamilycolorbar_titlefonthaligncolorbar_titlefontrotationcolorbar_titlefontsizecolorbar_titlefontvalign - Legend attributes:
legend_background_colorlegend_columnlegend_fontlegend_font_colorlegend_font_familylegend_font_halignlegend_font_pointsizelegend_font_rotationlegend_font_valignlegend_foreground_colorlegend_positionlegend_titlelegend_title_fontlegend_title_font_familylegend_title_font_halignlegend_title_font_pointsizelegend_title_font_rotationlegend_title_font_valign - Margin attributes:
bottom_marginleft_marginmarginright_margintop_margin - Title attributes:
titletitlefontcolortitlefontfamilytitlefonthaligntitlefontrotationtitlefontsizetitlefontvaligntitlelocation - 3D-specific attributes:
cameraprojectionprojection_type - Other subplot attributes:
aspect_ratiobackground_color_insidebackground_color_subplotcolor_paletteextra_kwargsfontfamily_subplotforeground_color_subplotforeground_color_titleframestylesubplot_index
- Annotation attributes:
- Axis attributes stay the same.
We might also want to consider making the attribute names consistent with regards to spacing, snake-case, etc. Right now, all the annotation attributes are concatenated words, the colorbar attributes are all over the place, the legend attributes are all snakecase, and the title attributes are concatenated. Also, clims (colorbar limits) has an official name that is different from the other colorbar attributes.
What we shouldn't change is that there is a single source of truth. On the other hand I don't see a reason why you couldn't generate the markdown in https://github.com/JuliaPlots/PlotDocs.jl/issues/323#issuecomment-1345472075 from the current stucture when you change the descripion string in Plots.jl. I would probably like to have a frontpage that only lists the attributes as links, such that you get the detailed information if you click on it.
On the other hand I don't see a reason why you couldn't generate the markdown in #323 (comment) from the current stucture when you change the descripion string in Plots.jl.
I'm not sure I follow. It is technically possible to fit all of the information in the table, but it wouldn't look good as the last column would take up too much space. There's a bunch of nested bullet points, and for some attributes, the list of relevant series types which the attribute applies to can be huge. The information really needs the entire space on the page to be readable, not just a single column. A tabular format encourages terse docstrings, so it would be nice to have more information to enhance accessibility. Plus, right now the backticks don't render in the table, and there is the occasional \n in the descriptions.
Essentially, my position is this: I know what format I want to present the information to be as complete and concise as possible, and am thinking the present table is not adequate enough to realize that, but function docstrings do. Thus the question becomes how to replicate the function docstring format as closely as possible within the limits of Documenter.jl. If the attribute names themselves show up on the results page when searching in the docs, that would help greatly with discoverability.
I'm not saying we should keep that table. We can generate from the dictionary in Plots.jl/src/attr_descr.jl any markdown.
Does the information have to be written as part of a dictionary, or can I write the markdown directly? Using ## and ### headers would be good enough for organization.
In principle its fine to use markdown stings there, however we should take care not to break usage of that information in plotattr and docstrings.
Thats either keeping the dictionary structure or also changing how these functions use that information.
One way is to keep the dictionary as-is, but create new pages with pure Markdown, replacing the generated/attribute_series.md, etc. That way plotattr functionality won't be broken. There'll be a disconnect between documentation on the site and documentation as seen in the REPL via plotattr, but I think this'll be a good start. What do you think?
Sounds reasonable to me
Example for series attributes. While creating this page, it was found that match_dimensions was not being generated in the table.