Open FlavioRyu opened 2 years ago
Can you update this issue @FlavioRyu
Yes, I've changed a lot since I posted this original issue so I will try to give a summary (otherwise this would become a documentation) of what is the current situation.
There are 5 classes: EmptyPlot
, PythRatio
, PythCMatrix
, PythPull
and PythProjection
, where the first is the mother class of the others (can be considered a virtual class). Each individual plot classes store specific rcParams
values in form of a dictionary; the user can pass in the constructor (under the argument rcp_kw
) a dictionary containing rcParams keys and this will be used to internally update the plot default rcParams.
The most important function is the display()
function which is present in all child classes. This effectively draws the entire plot by calling plotting functions such as matpltolib.errorbar()
, matpltolib.imshow()
and mplhep.histplot()
(where, btw, the last one is a helper for matpltolib.stairs()
and matpltolib.errorbar()
).
Class storing basic attributes such as figure size, master title (or figure title), positioning of subplots present in the figure, etc. Member functioins are functions that are common to all other plot classes such as create_canvas()
, make_subplot()
, set_color()
, save_image()
etc. to name a few.
The base class also stores two dictionaries (called xtitles_dict
and xtitles_dict
) to store x and y titles (or labels) of any subplot that might be present in the plot. These titles are set by the user calling the function axes_labels()
. Below is an explanation of these two dictionaries (taken from source code)
# set default dict of axes titles
self.xtitles_dict = {
"xmain" : '',
"xtop" : '',
"xbot" : '',
"xleft" : '', # not used
"xright": ''
}
self.ytitles_dict = {
"ymain" : '',
"ytop" : '',
"ybot" : '',
"yleft" : '', # not used
"yright": ''
}
"""
The terms 'main', 'top', 'bot' etc. refer to the follownig subplot scheme:
--------
| top |
--------
----- -------- -----
| | | | | |
|left | | main | |right|
| | | | | |
----- -------- -----
--------
| bot |
--------
And each plot type (ratio, pull, projection, corrm) will be a combination of
these subplots (Ax objects). For example, the ratio plot will be made of main
and bot subplots and the projection plot will be made of main, top and right
subplots. The left subplot is currently not used and might be deleted in the
future if no use cases are found.
The space between the subplots is called 'spacing' throughout all classes
"""
As matplotlib makes a lot of confusion in the rcParams
that control font sizes of each element in the plot, I decided to standardise them in the following way (example from pull plot):
matplotlib.rcParams['axes.titlesize']
matplotlib.rcParams['font.size']
fontsize
attribute, which is passed in as first argument in axes_labels()
functionUse case example:
my_dict={
'axes.titlesize': 20,
'font.size': 11
}
obj = PythRatio(hist_list, size=(6,8), title='Master Title', spacing=0, rcp_kw=my_dict)
obj.set_stack_color(reverse=True, colormap='gist_rainbow')
obj.axes_labels(15, xbot=xaxis_label, ymain='Events', ybot='Data/Pred.')
obj.set_bot_yaxis([0.5, 1.5], 0.25, edges=False) # strongly recommend user to do this
obj.plot_errors(hatch='/////', alpha=0.2)
obj.display()
set_bot_yaxis
is recommended because if user doesn't call this, the y axis of the ratio plot (the bottom subplot) will be drawn automatically by matplotlib but this might not always be the desired output. For instance, axis tick labels might overlap to other parts of the plot but this can be avoided by specifying a custom y axis range and the edges
boolean.
Output of example:
Use case example:
obj = PythCMatrix(data, 0.001, title='Master Title')
obj.set_color(colormap='bwr')
obj.display(set_cbar=False)
In the constructor, the float after the data is the threshold value for which the data will be cut. In the display()
function, it is possible to specify whether a colorbar on the side is wanted or not. The figure size changed automatically: figure side length (in inches) is len(data)/3
.
Output of example:
Use case example:
my_dict={
'axes.titlesize': 15
}
hist1 = PythPullPlot(data0.iloc[0:40], title='Master Title', rcp_kw=my_dict)
hist1.set_rangex([-6, 11])
hist1.axes_labels(12, xmain=r'$(\hat{\theta}-\theta)/\Delta\theta$')
hist1.display()
set_rangex()
can be called by user to impose a custom x range for the plot. The figure size of the pull plot changes according to the length of nuisance parameters (n
) to be plotted: figsize = (2, 0.4012*n**(0.763))
(this formula was empirically derived).
Output of example:
Use case example:
my_dict={
'axes.titlesize': 20,
'xaxis.labellocation': 'right',
'yaxis.labellocation': 'top',
}
plot = PythProjection(size=(6,6), title='Master Title', spacing=0.08, rcp_kw=my_dict)
plot.fill(hist)
plot.axes_labels(15, ymain=r'$p_y$ [MeV]', xmain=r'$p_x$ [MeV]', xright='righttitle', ytop='toptitle')
plot.put_grid()
plot.set_color(colormap='binary')
plot.display()
Output of example:
@jkwinter Can you review this issue and give your updates on what changed/what needs to change?
How will we provide plotting classes to users? TODO:
In terms of structure, Flavio has documented this in the plotting readme. In terms of functionality
Open points:
Plotting to-do list General
Hist1D
RatioPlot
PullPlot
ProjectionPlot
CMatrixPlot
I was just brainstorming about the use case of our classes before even starting to have a skeleton and I came up with this:
This a brief example of some functionalities that I thought might be useful to have for some histogram types. These classes will all inherit from a more general
BasicHisto
(which contains methods such asmake_grid()
ordisplay()
and attributes likeline
oraxis
) class which will take in the histogram object (which is a boost-hist for now) and extrapolate and store all relevant information about it. The idea is to create a subclass for each histogram type.It is a very basic scratch so let me know if there is anything that I got wrong or that should be changed about the structure in general.
Edit: this does not make use of any canvas or pad structures.