Skip to content

Commit 9d8d349

Browse files
authored
feat/refactor!: revamping labels (#596)
* feat: rework labels * fix: docs * docs: update docstrings, import aliases, formatting * fix: append_text, add above/left, add tests * fix: append_text, add above/left, add tests * chore: cleanup tests * fix: supplementary handling * chore: cleanup
1 parent f88fdb9 commit 9d8d349

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

46 files changed

+1387
-913
lines changed

README.md

Lines changed: 21 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -40,32 +40,31 @@ Documentation can be found at [mplhep.readthedocs.io](https://mplhep.readthedocs
4040
### Styling
4141

4242
```python
43-
import mplhep as hep
44-
hep.style.use(hep.style.ROOT) # For now ROOT defaults to CMS
45-
# Or choose one of the experiment styles
46-
hep.style.use(hep.style.ATLAS)
47-
# or
48-
hep.style.use("CMS") # string aliases work too
49-
# {"ALICE" | "ATLAS" | "CMS" | "LHCb1" | "LHCb2" | "DUNE" | "DUNE1"}
43+
import mplhep as mh
44+
mh.style.use(mh.style.ROOT) # For now ROOT defaults to CMS
45+
# OR
46+
mh.style.use(mh.style.ATLAS)
47+
# OR
48+
mh.style.use("CMS") # string aliases work too
5049
```
5150

5251
Or use `matplotlib` API directly
5352

5453
```python
55-
plt.style.use(hep.style.ROOT)
54+
plt.style.use(mh.style.ROOT)
5655
```
5756
**If the default styles are not what you need, please open an issue.**
5857

5958
Default experiment labels are also available.
6059

6160
```python
6261
# Overall - both left and right annotation
63-
hep.<experiment>.label(<text>, data=<True|False>, lumi=50, year=2017)
64-
# Just experiment label and <text> such as 'Preliminary' or 'Simulation'
65-
hep.<experiment>.text(<text>)
62+
mh.<experiment>.label(<text>, data=<True|False>, lumi=50, year=2017)
63+
# OR
64+
mh.<experiment>.text(<text>)
6665
```
6766

68-
You can use `loc={0..5}` to control the label positioning.
67+
You can use `loc={0..4}` to control the label positioning.
6968

7069
<p float="left">
7170
<img src="tests/baseline/test_label_loc.png" width="100%" />
@@ -77,7 +76,7 @@ You can use `loc={0..5}` to control the label positioning.
7776

7877
```python
7978
h, bins = [2, 3, 2], [0, 1, 2, 3]
80-
hep.histplot(h, bins)
79+
mh.histplot(h, bins)
8180
```
8281

8382
#### 2D Histograms
@@ -86,40 +85,40 @@ hep.histplot(h, bins)
8685
import numpy as np
8786
xbins, ybins = [0, 1, 2, 3], [0, 1, 2, 3]
8887
H = np.array([[2,3,2], [1,2,1], [3,1,3]])
89-
hep.hist2dplot(H, xbins, ybins)
88+
mh.hist2dplot(H, xbins, ybins)
9089
```
9190

9291
# More Information
9392

9493
### Save all labels at once
95-
- `hep.savelabels('test.png')` will produces 4 variation on experiment label
94+
- `mh.savelabels('test.png')` will produces 4 variation on experiment label
9695
- "" -> "test.png"
9796
- "Preliminary" -> "test_pas.png"
9897
- "Supplementary" -> "test_supp.png"
9998
- "Work in Progress" -> "test_wip.png"
10099
- Options can also be specified manually
101-
- `hep.savelabels('test', labels=["FOO", "BAR"], suffixes=["foo.pdf", "bar"])` will produce
100+
- `mh.savelabels('test', labels=["FOO", "BAR"], suffixes=["foo.pdf", "bar"])` will produce
102101
- "FOO" -> "foo.pdf"
103102
- "BAR" -> "test_bar.png"
104103
- Other components of `<experiment>.label()` will remain unchanged.
105104

106105
### Other styles:
107-
- `hep.style.use("fira")` - use Fira Sans
108-
- `hep.style.use("firamath")` - use Fira Math
106+
- `mh.style.use("fira")` - use Fira Sans
107+
- `mh.style.use("firamath")` - use Fira Math
109108

110109
#### Styles can be chained:
111-
- e.g. `hep.style.use(["CMS", "fira", "firamath"])`
110+
- e.g. `mh.style.use(["CMS", "fira", "firamath"])`
112111
- reappearing `rcParams` get overwritten silently
113112

114113
#### Styles can be modified on the fly
115114
- Since styles are dictionaries and they can be chained/overwritten they can be easily modified on the fly. e.g.
116115
```
117-
hep.style.use("CMS")
118-
hep.style.use({"font.sans-serif":'Comic Sans MS'})
116+
mh.style.use("CMS")
117+
mh.style.use({"font.sans-serif":'Comic Sans MS'})
119118
```
120119

121120
#### Styling with LaTeX
122-
- `hep.style.use("CMSTex")` - Use LaTeX to produce all text labels
121+
- `mh.style.use("CMSTex")` - Use LaTeX to produce all text labels
123122
- Requires having the full tex-live distro
124123
- True Helvetica
125124
- Use sansmath as the math font

docs/source/api.rst

Lines changed: 24 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,30 +11,50 @@ Primary functions.
1111

1212
.. autofunction:: mplhep.hist2dplot
1313

14+
.. autofunction:: mplhep.funcplot
15+
1416
.. # List all modules when appropriately privatized
1517
.. automodule:: mplhep.plot
1618
:members:
1719
20+
21+
Text functions
22+
========================
23+
24+
Functions to annotate figures in a convenient way. Typically ``append_text`` can be used to place an additional artist after ``add_text``.
25+
26+
.. autofunction:: mplhep.label.add_text
27+
28+
.. autofunction:: mplhep.label.append_text
29+
30+
1831
Experiment label helpers
1932
========================
2033

2134
Experiment specific helpers.
2235

2336
For the effects of the ``label`` method, see also the gallery examples in :ref:`gallery-labels`.
2437

25-
.. autofunction:: mplhep.cms.lumitext
38+
39+
.. autofunction:: mplhep.cms.label
2640

2741
.. autofunction:: mplhep.cms.text
2842

29-
.. autofunction:: mplhep.cms.label
43+
.. autofunction:: mplhep.atlas.label
3044

3145
.. autofunction:: mplhep.atlas.text
3246

33-
.. autofunction:: mplhep.atlas.label
47+
.. autofunction:: mplhep.lhcb.label
3448

3549
.. autofunction:: mplhep.lhcb.text
3650

37-
.. autofunction:: mplhep.lhcb.label
51+
.. autofunction:: mplhep.alice.label
52+
53+
.. autofunction:: mplhep.alice.text
54+
55+
.. autofunction:: mplhep.dune.label
56+
57+
.. autofunction:: mplhep.dune.text
3858

3959

4060
Axes helpers

docs/source/conf.py

Lines changed: 34 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -69,18 +69,47 @@ def linkcode_resolve(domain, info):
6969
return None
7070
if not info["module"]:
7171
return None
72-
mod = importlib.import_module(info["module"])
72+
73+
# Handle module aliasing for experiment modules
74+
module_name = info["module"]
75+
if module_name.startswith("mplhep.") and module_name.split(".")[-1] in [
76+
"cms",
77+
"atlas",
78+
"lhcb",
79+
"alice",
80+
"dune",
81+
]:
82+
# Map aliased modules to their actual module names
83+
alias_map = {
84+
"mplhep.cms": "mplhep.exp_cms",
85+
"mplhep.atlas": "mplhep.exp_atlas",
86+
"mplhep.lhcb": "mplhep.exp_lhcb",
87+
"mplhep.alice": "mplhep.exp_alice",
88+
"mplhep.dune": "mplhep.exp_dune",
89+
}
90+
module_name = alias_map.get(module_name, module_name)
91+
92+
try:
93+
mod = importlib.import_module(module_name)
94+
except ImportError:
95+
return None
96+
7397
modpath = [p for p in sys.path if mod.__file__.startswith(p)]
7498
if len(modpath) < 1:
7599
msg = "Cannot deduce module path"
76100
raise RuntimeError(msg)
77101
modpath = modpath[0]
78-
obj = reduce(getattr, [mod, *info["fullname"].split(".")])
102+
103+
try:
104+
obj = reduce(getattr, [mod, *info["fullname"].split(".")])
105+
except AttributeError:
106+
return None
107+
79108
try:
80109
path = inspect.getsourcefile(obj)
81110
relpath = path[len(modpath) + 1 :]
82111
_, lineno = inspect.getsourcelines(obj)
83-
except TypeError:
112+
except (TypeError, OSError):
84113
# skip property or other type that inspect doesn't like
85114
return None
86115
return f"http://github.com/scikit-hep/mplhep/blob/{githash}/{relpath}#L{lineno}"
@@ -172,7 +201,7 @@ def linkcode_resolve(domain, info):
172201
ax.plot(x, np.asarray(y), label=label)
173202

174203
kwargs = {
175-
"label": "Preliminary",
204+
"text": "Preliminary",
176205
"data": True,
177206
"ax": ax,
178207
"year": 2016,
@@ -188,7 +217,7 @@ def linkcode_resolve(domain, info):
188217
elif "dune" in style.lower():
189218
mplhep.dune.label(**kwargs)
190219
ax.legend()
191-
ax.set_xlabel("$m_{\mu\mu}$ [GeV]")
220+
ax.set_xlabel(r"$m_{\mu\mu}$ [GeV]")
192221
ax.set_ylabel("Events")
193222
path = Path(
194223
here / f"_static/_generated/{style}/{histtype}/pos{position}.png"

docs/source/install.rst

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,14 +12,14 @@ primary functionality can be accessed as follows:
1212
1313
import numpy as np
1414
import matplotlib.pyplot as plt
15-
import mplhep as hep
15+
import mplhep as mh
1616
1717
# Load style sheet
18-
plt.style.use(hep.style.CMS) # or ATLAS/LHCb2
18+
plt.style.use(mh.style.CMS) # or ATLAS/LHCb2
1919
2020
h, bins = np.histogram(np.random.random(1000))
2121
fig, ax = plt.subplots()
22-
hep.histplot(h, bins)
22+
mh.histplot(h, bins)
2323
2424
Will feature binder
2525

examples/Examples.ipynb

Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
"import matplotlib.pyplot as plt\n",
1515
"import numpy as np\n",
1616
"\n",
17-
"import mplhep as hep"
17+
"import mplhep as mh"
1818
]
1919
},
2020
{
@@ -52,11 +52,11 @@
5252
"y = np.random.normal(512, 112, 240)\n",
5353
"z = np.random.normal(0.5, 0.1, 240)\n",
5454
"\n",
55-
"plt.style.use([hep.style.ROOT, hep.style.firamath])\n",
55+
"plt.style.use([mh.style.ROOT, mh.style.firamath])\n",
5656
"\n",
5757
"f, ax = plt.subplots()\n",
5858
"ax.scatter(x, y, c=z, label=\"XSX\")\n",
59-
"hep.cms.label(loc=0)\n",
59+
"mh.cms.label(loc=0)\n",
6060
"\n",
6161
"plt.show()"
6262
]
@@ -98,16 +98,16 @@
9898
"axs = axs.flatten()\n",
9999
"\n",
100100
"axs[0].set_title(\"Default\", fontsize=18)\n",
101-
"hep.histplot(h, bins, ax=axs[0])\n",
101+
"mh.histplot(h, bins, ax=axs[0])\n",
102102
"\n",
103103
"axs[1].set_title(\"Plot Edges\", fontsize=18)\n",
104-
"hep.histplot(h, bins, edges=True, ax=axs[1])\n",
104+
"mh.histplot(h, bins, edges=True, ax=axs[1])\n",
105105
"\n",
106106
"axs[2].set_title(\"Plot Errorbars\", fontsize=18)\n",
107-
"hep.histplot(h, bins, yerr=np.sqrt(h), ax=axs[2])\n",
107+
"mh.histplot(h, bins, yerr=np.sqrt(h), ax=axs[2])\n",
108108
"\n",
109109
"axs[3].set_title(\"Filled Histogram\", fontsize=18)\n",
110-
"hep.histplot(h, bins, histtype=\"fill\", ax=axs[3])\n",
110+
"mh.histplot(h, bins, histtype=\"fill\", ax=axs[3])\n",
111111
"\n",
112112
"\n",
113113
"plt.tight_layout()\n",
@@ -149,17 +149,17 @@
149149
"axs = axs.flatten()\n",
150150
"\n",
151151
"axs[0].set_title(\"Default Overlay\", fontsize=18)\n",
152-
"hep.histplot([h, 1.5 * h], bins, ax=axs[0])\n",
152+
"mh.histplot([h, 1.5 * h], bins, ax=axs[0])\n",
153153
"\n",
154154
"axs[1].set_title(\"Default Overlay w/ Errorbars\", fontsize=18)\n",
155-
"hep.histplot([h, 1.5 * h], bins, yerr=[np.sqrt(h), np.sqrt(1.5 * h)], ax=axs[1])\n",
155+
"mh.histplot([h, 1.5 * h], bins, yerr=[np.sqrt(h), np.sqrt(1.5 * h)], ax=axs[1])\n",
156156
"\n",
157157
"\n",
158158
"axs[2].set_title(\"Automatic Errorbars\", fontsize=18)\n",
159-
"hep.histplot([h, 1.5 * h], bins, yerr=True, ax=axs[2])\n",
159+
"mh.histplot([h, 1.5 * h], bins, yerr=True, ax=axs[2])\n",
160160
"\n",
161161
"axs[3].set_title(\"With Labels\", fontsize=18)\n",
162-
"hep.histplot([h, 1.5 * h], bins, yerr=True, ax=axs[3], label=[\"First\", \"Second\"])\n",
162+
"mh.histplot([h, 1.5 * h], bins, yerr=True, ax=axs[3], label=[\"First\", \"Second\"])\n",
163163
"\n",
164164
"axs[3].legend(fontsize=16)\n",
165165
"\n",
@@ -202,16 +202,16 @@
202202
"axs = axs.flatten()\n",
203203
"\n",
204204
"axs[0].set_title(\"Default\", fontsize=18)\n",
205-
"hep.histplot([h, 1.5 * h], bins, stack=True, ax=axs[0])\n",
205+
"mh.histplot([h, 1.5 * h], bins, stack=True, ax=axs[0])\n",
206206
"\n",
207207
"axs[1].set_title(\"Plot Edges\", fontsize=18)\n",
208-
"hep.histplot([h, 1.5 * h], bins, edges=True, stack=True, ax=axs[1])\n",
208+
"mh.histplot([h, 1.5 * h], bins, edges=True, stack=True, ax=axs[1])\n",
209209
"\n",
210210
"axs[2].set_title(\"Plot Errorbars\", fontsize=18)\n",
211-
"hep.histplot([h, 1.5 * h], bins, yerr=[np.sqrt(h), np.sqrt(h)], stack=True, ax=axs[2])\n",
211+
"mh.histplot([h, 1.5 * h], bins, yerr=[np.sqrt(h), np.sqrt(h)], stack=True, ax=axs[2])\n",
212212
"\n",
213213
"axs[3].set_title(\"Filled Histogram\", fontsize=18)\n",
214-
"hep.histplot([1.5 * h, h], bins, histtype=\"fill\", stack=True, ax=axs[3])\n",
214+
"mh.histplot([1.5 * h, h], bins, histtype=\"fill\", stack=True, ax=axs[3])\n",
215215
"\n",
216216
"plt.tight_layout()\n",
217217
"plt.show()"
@@ -256,7 +256,7 @@
256256
"H, xedges, yedges = np.histogram2d(x, y, bins=(xedges, yedges))\n",
257257
"\n",
258258
"fig, ax = plt.subplots()\n",
259-
"hep.hist2dplot(H, xedges, yedges, labels=True);"
259+
"mh.hist2dplot(H, xedges, yedges, labels=True);"
260260
]
261261
},
262262
{

src/mplhep/__init__.py

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,12 @@
77

88
# Get styles directly, also available within experiment helpers.
99
# Get helper functions
10-
from . import alice, atlas, cms, comp, dune, label, lhcb, plot
10+
from . import comp, label, plot
11+
from . import exp_alice as alice
12+
from . import exp_atlas as atlas
13+
from . import exp_cms as cms
14+
from . import exp_dune as dune
15+
from . import exp_lhcb as lhcb
1116
from . import styles as style
1217
from ._tools import Config
1318
from ._version import version as __version__ # noqa: F401
@@ -25,7 +30,7 @@
2530
plot_model,
2631
plot_two_hist_comparison,
2732
)
28-
from .label import add_text, save_variations, savelabels
33+
from .label import add_text, append_text, save_variations, savelabels
2934
from .plot import (
3035
append_axes,
3136
box_aspect,
@@ -53,9 +58,8 @@
5358
# Configs
5459
rcParams = Config(
5560
label=Config(
61+
text=None,
5662
data=None,
57-
kind=None,
58-
supplementary=None,
5963
year=None,
6064
lumi=None,
6165
llabel=None,
@@ -80,6 +84,7 @@
8084
"add_text",
8185
"alice",
8286
"append_axes",
87+
"append_text",
8388
"atlas",
8489
"box_aspect",
8590
"cms",

0 commit comments

Comments
 (0)