Skip to content

Commit

Permalink
Merge pull request #81 from danielhundhausen/main
Browse files Browse the repository at this point in the history
Misc fixes/improvements to documentation, new CMS colors, plot style
  • Loading branch information
danielhundhausen authored Aug 28, 2024
2 parents aeb106c + cba8694 commit 9a7e381
Show file tree
Hide file tree
Showing 9 changed files with 98 additions and 42 deletions.
2 changes: 1 addition & 1 deletion .flake8
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
[flake8]
ignore = W391, W503
ignore = W391, W503, E712
max-line-length = 88
extend-ignore = E203, E704, E266
exclude = menu_tools/object_performance/quality_obj.py,menu_tools/**/test_*.py
16 changes: 12 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,20 +6,28 @@
trigger turn-on curves, and scalings for the assessment of the physics performance of the CMS Phase-2 L1 Menu.

For further instructions on how to run the tools, see the `docs`.
Some documentation can also be found in the [wiki](https://github.com/cms-l1-dpg/Phase2-L1MenuTools/wiki).

## Setup

These tools are expected to be used primarily on lxplus.
To clone the repository run

```bash
git clone [email protected]:cms-l1-dpg/Phase2-L1MenuTools.git
```

A standard venv with Python3.11 can be created on lxplus
via `python3.11 -m venv <name_of_venv>` and all necessary
dependencies installed via `pip install .`:
dependencies installed via `pip install -e .`:

```bash
python3.11 -m venv pyenv
python3.11 -m venv <name_of_venv>
source <name_of_venv>/bin/activate
pip install .
pip install -e .
```

**ATTENTION:** Whenever you pull changes you need to `pip install . --upgrade`
**ATTENTION:** If you do not use the `-e` flag (editable), you will `pip install . --upgrade` whenever you pull changes.

You can then execute the tools via

Expand Down
6 changes: 3 additions & 3 deletions docs/development.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,10 @@
Poetry is used as a backend for packaging and for dependency
management. To set up a working development environment, create
a virtual environment and install the `poetry` python package.
Then install all develpoment dependencies:
Then `poetry install` installs all develpoment dependencies:

```bash
python@3.11 -m venv <name_of_venv>
python3.11 -m venv <name_of_venv>
source <name_of_venv>/bin/activate
pip install poetry
poetry install
Expand All @@ -24,7 +24,7 @@ pytest -vv
```

to run all tests. The `-vv` option is optional and can be omitted.
For some of the tests the presence of the V29 caching files is required.
For some of the tests the presence of the `V29` caching files is required.


## Code Formatting and Linting
Expand Down
29 changes: 21 additions & 8 deletions docs/object-performance.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,16 @@

The object performance tools allow the user to produce
matching efficiency, turn-on curves, and scaling plots for
the various L1 objects under test.
the various L1 objects.
The definition of each object to be tested is detailed in
this [TWiki page](https://twiki.cern.ch/twiki/bin/view/CMS/PhaseIIL1TriggerMenuTools).

A detailed description of each step, together with instructions on how to set up the configuration files for the cache and plotting steps, is given in [the Wiki pages](https://github.com/cms-l1-dpg/Phase2-L1MenuTools/wiki).
A detailed description of each step, together with instructions on how to set up the
configuration files for the cache and plotting steps, is given in
[the Wiki pages](https://github.com/cms-l1-dpg/Phase2-L1MenuTools/wiki).

The following presents the commands to be run to produce the standard set of validation plots (cf. [these slides](https://twiki.cern.ch/twiki/pub/CMS/PhaseIIL1TriggerMenuTools/Phase2Menu_validation123x-3.pdf)).
The following presents the commands to be run to produce the standard set of validation
plots (cf. [these slides](https://twiki.cern.ch/twiki/pub/CMS/PhaseIIL1TriggerMenuTools/Phase2Menu_validation123x-3.pdf)).

## Table of content

Expand All @@ -17,6 +20,10 @@
* [Reference config files](#reference-config-files)

## Caching the NTuple trees

**Note:** When running on lxplus, usually the cache files will already
be present in the symliked directory included with the repo.

In order to run the next steps, the object
`TTrees` from the L1NTuples need to be cached
as `awkward` arrays saved into `.parquet` files.
Expand All @@ -27,9 +34,11 @@
```

An example for a caching config can be found at `configs/V29/caching.yaml`.
The output of this step is saved to `cache`. The repository by default includes a symlink to a directory which should already contain most of the desireable object caches.
This step needs to be run only once per configuration (unless changes in the input L1 ntuples occur) and the `.parquet` files generated by the code can be used for all the subsequent steps of the workflow,
without having to open the `.root` files and load the objects every time the framework is run.
The output of this step is saved to `cache`.
This step needs to be run only once per configuration (unless changes in the input
L1 ntuples occur) and the `.parquet` files generated by the code can be
used for all the subsequent steps of the workflow, without having to open the
`.root` files and load the objects every time the framework is run.

## Efficiency and Scalings
To produce matching efficiencies, turn-on curves, and L1 scalings run
Expand All @@ -47,9 +56,13 @@
Default configuration files are contained in `configs` and should be used as
templates for custom configurations.

The points used for the calculation of the scalings correspond to the list of threshold cuts defined in [`scaling_thresholds`](https://github.com/cms-l1-dpg/Phase2-L1MenuTools/blob/main/configs/scaling_thresholds.yaml).
The points used for the calculation of the scalings correspond to the list of
threshold cuts defined in
[`scaling_thresholds`](https://github.com/cms-l1-dpg/Phase2-L1MenuTools/blob/main/configs/scaling_thresholds.yaml).

The outputs will be written to the `outputs/<VERSION>` directory, where `<VERSION>` is the version of the ntuples used for the plots as specified in the `.yaml` config file (more details on the config file are given below).
The outputs will be written to the `outputs/<VERSION>` directory,
where `<VERSION>` is the version of the ntuples used for the plots as specified
in the `.yaml` config file (more details on the config file are given below).
In the current version of the code, the plots will be saved in three folders under `outputs/<VERSION>`:

* `distributions`: plots of the distributions (histograms) used to compute the efficiencies. For each efficiency curve plotted, these plots depict the distributions used for as numberator and denumerator in the computation of the efficiencies.
Expand Down
2 changes: 1 addition & 1 deletion docs/objects.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ centrally, by default at
configs/<VERSION>/objects
```

All objects found in yaml files in this directory will be found by
All objects defined in yaml files in this directory will be found by
the code.

## Object configuration
Expand Down
49 changes: 40 additions & 9 deletions menu_tools/object_performance/plotter.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import warnings
import yaml

import matplotlib as mpl
import matplotlib.pyplot as plt
import mplhep as hep
import numpy as np
Expand All @@ -17,6 +18,19 @@
from menu_tools.utils.objects import Object


colors = [
"#3f90da",
"#ffa90e",
"#bd1f01",
"#94a4a2",
"#832db6",
"#a96b59",
"#e76300",
"#b9ac70",
"#717581",
"#92dadd",
]
mpl.rcParams["axes.prop_cycle"] = mpl.cycler(color=colors)
plt.style.use(hep.style.CMS)


Expand Down Expand Up @@ -170,8 +184,12 @@ def _plot_efficiency_curve(self):

# Save figure
plot_fname = f"{self.plot_name}_{self.threshold}_{self.version}"
plt.savefig(os.path.join(self._outdir_turnons, f"{plot_fname}.png"))
plt.savefig(os.path.join(self._outdir_turnons, f"{plot_fname}.pdf"))
plt.savefig(
os.path.join(self._outdir_turnons, f"{plot_fname}.png"), bbox_inches="tight"
)
plt.savefig(
os.path.join(self._outdir_turnons, f"{plot_fname}.pdf"), bbox_inches="tight"
)
self._save_json(os.path.join(self._outdir_turnons, f"{plot_fname}.json"))

# Save config
Expand Down Expand Up @@ -210,7 +228,9 @@ def _plot_iso_vs_efficiency_curve(self):
# Save figure
plot_fname = f"{self.plot_name}_{self.threshold}_{self.version}"
plt.savefig(os.path.join(self._outdir_turnons, f"{plot_fname}.png"))
plt.savefig(os.path.join(self._outdir_turnons, f"{plot_fname}.pdf"))
plt.savefig(
os.path.join(self._outdir_turnons, f"{plot_fname}.pdf"), bbox_inches="tight"
)
self._save_json(os.path.join(self._outdir_turnons, f"{plot_fname}.json"))

# Save config
Expand Down Expand Up @@ -243,11 +263,19 @@ def _plot_raw_counts(self):
xbins,
ref_hist[0],
where="mid",
label="ref: " + obj_key,
ls="--",
color="k",
ls="-.",
)

# mock plot outside of visible range to create legend entry for ref
ax.plot(
[xbins[0] - 100, xbins[0] - 99],
[0, 0],
label="reference object",
color="black",
linestyle="-.",
)
plt.gca().set_prop_cycle(None)

for obj_key, gen_hist_trig in self.turnon_collection.hists.items():
if obj_key == "ref":
continue
Expand All @@ -263,11 +291,14 @@ def _plot_raw_counts(self):
**err_kwargs,
)

self._style_plot(fig, ax)
self._style_plot(fig, ax, legend_loc="best")
# Save figure
plot_fname = f"{self.plot_name}_{self.threshold}_dist_{self.version}"
plt.savefig(os.path.join(self._outdir_distributions, f"{plot_fname}.png"))
plt.savefig(os.path.join(self._outdir_distributions, f"{plot_fname}.pdf"))
plt.savefig(
os.path.join(self._outdir_distributions, f"{plot_fname}.pdf"),
bbox_inches="tight",
)

plt.close()

Expand Down Expand Up @@ -408,7 +439,7 @@ def plot(self):
f"{self.plot_name}_{self.version}",
)
plt.savefig(f"{plot_fname}.png")
plt.savefig(f"{plot_fname}.pdf")
plt.savefig(f"{plot_fname}.pdf", bbox_inches="tight")
self._save_json(f"{plot_fname}.json")

## save config
Expand Down
18 changes: 16 additions & 2 deletions menu_tools/rate_plots/plotter.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import json

import awkward as ak
import matplotlib as mpl
import matplotlib.pyplot as plt
import mplhep as hep
import numpy as np
Expand All @@ -14,6 +15,19 @@
from menu_tools.utils.objects import Object
from menu_tools.rate_plots.config import RatePlotConfig

colors = [
"#3f90da",
"#ffa90e",
"#bd1f01",
"#94a4a2",
"#832db6",
"#a96b59",
"#e76300",
"#b9ac70",
"#717581",
"#92dadd",
]
mpl.rcParams["axes.prop_cycle"] = mpl.cycler(color=colors)
plt.style.use(hep.style.CMS)


Expand Down Expand Up @@ -97,7 +111,7 @@ def _plot_single_version_rate_curves(self):
)
print("Saving to ", fname)
plt.savefig(fname + ".png")
plt.savefig(fname + ".pdf")
plt.savefig(fname + ".pdf", bbox_inches="tight")

with open(fname + ".json", "w") as outfile:
outfile.write(json.dumps(plot_dict, indent=4))
Expand Down Expand Up @@ -152,7 +166,7 @@ def _plot_version_comparsion_rate_curves(self):
self._outdir, f"{v1}-vs-{v2}_{self._online_offline}_{self.cfg.plot_name}"
)
plt.savefig(fname + ".png")
plt.savefig(fname + ".pdf")
plt.savefig(fname + ".pdf", bbox_inches="tight")

plt.close()

Expand Down
1 change: 0 additions & 1 deletion menu_tools/rate_table/menu_table.py
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,6 @@ def _load_cached_arrays(self, object_name: str) -> ak.Array:
# instead of a single number.
if isinstance(arr[0], ak.highlevel.Record):
arr = ak.zip({field: [[k] for k in arr[field]] for field in arr.fields})
# arr = ak.zip({field: np.expand_dims(arr[field], 0) for field in arr.fields})

if "eta" in arr.fields:
arr = ak.with_name(arr, "Momentum4D")
Expand Down
17 changes: 4 additions & 13 deletions menu_tools/utils/compare_plots.py
Original file line number Diff line number Diff line change
Expand Up @@ -155,29 +155,20 @@ def comp_plots(
d_p2 = dict(zip(plots[1]["xbins"], plots[1]["efficiency"]))

# add 100% eff line
# axs[0].axhline(1,ls = ":", alpha = 0.5, c = "k")
# axs[0].axhline(1,ls = ":", alpha = 0.5, c = "k")

df_p1 = pd.Series(d_p1)
df_p2 = pd.Series(d_p2)

# ax = axs[1]
# ax = axs[1]

if (df_p1.sum() != 0) and (df_p1.sum() != 0):
diff = df_p1 - df_p2
if ptype == "rate":
diff /= df_p2
label = p1["label"].split(",")[0]

diff.plot(
ax=axs[1], color=color, label=label
) # , marker = ".", color = color)
# axs[1].errorbar(
# p1["xbins"],df_p1 - df_p2,
# yerr = np.hypot(plots[0]["efficiency_err"], plots[1]["efficiency_err"]),
# # label = label, marker = ".", color = color,
# label = label, ls = lss[i], color = color, mfc="none" if i == 1 else color,
# **(p1["err_kwargs"])
# )
diff.plot(ax=axs[1], color=color, label=label)
if ptype == "turnon":
if len(plots[0]["efficiency_err"][0]) != len(
plots[1]["efficiency_err"][0]
Expand All @@ -192,7 +183,7 @@ def comp_plots(
diff.index,
diff.values - y_err,
diff.values + y_err,
# label = label,
# label = label,
alpha=0.3,
color=color,
)
Expand Down

0 comments on commit 9a7e381

Please sign in to comment.