Particle physics - exercise 1d solution

in utopian-io •  10 months ago  (edited)



This post is my implementation of @lemouth's fourth exercise in his series aiming at getting voluntary contributions from software developers and Utopian-io to help in producing open-source software providing physics analysis testing new theories stretching beyond the Standard Model.
The objectives of the project are described in @lemouth's first post in this series.

View of the CMS endcap through the barrel sections.
Image credits - Julian Williams on Wikipedia]

Post Body

For this last exercise, @lemouth introduced us to the concept of cutflows.

A cutflow is a list of event selection strategy which ensure that selected events meet certain criteria to ascertain signal quality and ensure that minimum characteristics are satisfied for the target of the experimentation.
For example, events must present a large amount of missing energy to be candidates for the search for Dark Matter.

Cutflows must also kill undesirable background events while keeping signals of interest as untouched as possible. Losing signal in the process is unavoidable but must be kept to a minimal level.

As always for these exercises, the Madanalysis5 framework is relied upon to extract event information from sample files and provide the analysis development with key programmatic utilities such as calculating transverse momentum and missing energy.

Missing Energy

With this exercise we were also introduced to the concept of missing energy.
This is the energy not detected during experimentation but is expected with the laws of conservation of energy and momentum.

Missing energy is in principle carried by particles that do not interact with the electromagnetic and strong forces and, for this reason, is difficult to detect.

This energy can be carried in large parts by neutrinos but can also be taken as a a clue that may go towards validating new theories beyond the Standard Model

While the total amount of energy involved in an event is hard to measure, the energy carried in the transverse direction of the beam axis is initially zero. For this reason the energy measured in the transverse direction (ET) also indicates the amount of missing energy (MET) by applying the principle of conservation of energy.

Search for Dark Matter

In the research paper at the center of this exercise, the writers describe how Dark Matter (DM) may be produced in proton-proton collisions in the Large Hadron Collider and how this Dark Matter may result in a large amount of missing transverse momentum pTmiss.

The paper also provides in its introduction the summary of a couple of different models predicting the production of DM particles along with a single photon with large transverse momentum.

The analysis thus focuses on selecting events with large missing transverse energy and a signal photon with large transverse momentum.

As always, some cleaning up of the sample events is to be implemented in order to get rid of particle detection overlap and ensure object isolation.

Cutflow Implemented in this Exercise

The cutflow described in section 3 of the research paper is as follows. Each selected event must pass the following cuts:

  • Missing transverse moment pTmiss must be at least 170 GeV.
  • At least one photon with transverse momentum pTγ greater than 175 GeV and pseudo-rapidity |η| < 1.44
  • Minimum opening angle between missing transverse momentum and any of the four highest transverse momenta jets greater than 0.5 (for jets with pT > 30GeV and |η| < 5)
  • Signal photon pTγ and pTmiss are separated by at least 2 radians.
  • electrons and muons with pT > 10 GeV must be separated from signal photon with ΔR > 0.5

From the above, I added the following cuts to the Initialize method:

  Manager()->AddCut("dPhi(pT(miss), pT(jet))");
  Manager()->AddCut("pt_photon > 175 & |n| < 1.44");
  Manager()->AddCut("dPhi(pT(miss), pT(photon))");
  Manager()->AddCut("DR(electron, signal_photon)");
  Manager()->AddCut("DR(muon, signal_photon)");

The Execute method was then updated with the following steps:

Apply cut for pTmiss:

  if(!Manager()->ApplyCut(event.rec()->MET().momentum().Pt() > 170,
    return true;

Extract jets (see above):
Note that I preserved the code from the last exercise with regards to generate histograms.

  bool found = false;
  std::vector<const RecJetFormat*> signal_jets;
  for (auto &jet : event.rec()->jets())
    if ( > 30 && jet.abseta() < 5)
      if (!found)
        Manager()->FillHisto("n_jets", jet.eta());
        found = true;
      cout << "Adding jet - Pt = " << << ", |n| = " << jet.eta() << endl;

Remove jets electrons overlap:
I used here the JetCleaning method provided by Madanalysis on electrons (not necessary on muons).

  for (auto &electron : event.rec()->electrons())
    double eta = electron.abseta();
    double pt =;
    double iso_var = PHYSICS->Isol->eflow->sumIsolation(electron,
    if( (eta > 1.44) and (eta<1.57) ) continue;
    if(eta > 2.5) continue;
    if(iso_var>0.15*pt) continue;
    if (pt>10) electrons.push_back(&electron);
  signal_jets = PHYSICS->Isol->JetCleaning(signal_jets, electrons, 0.2);

Clean muons:

  for (auto &muon : event.rec()->muons())
    double eta = muon.abseta();
    double pt =;
    double iso_var = PHYSICS->Isol->eflow->sumIsolation(muon,
    if(eta > 2.4) continue;
    if(iso_var>0.20*pt) continue;
    if (pt>10) muons.push_back(&muon);

Check that at least one photon meets pTγ > 175 GeV and |η| < 1.44:

    std::none_of(event.rec()->photons().begin(), event.rec()->photons().end(),
                 [](const RecPhotonFormat& photon) { return > 175 && photon.abseta() < 1.44; }),
    "pt_photon > 175 & |n| < 1.44"))
    return true;

Isolate signal photon:
This was done using Table 3 selection criteria in the research paper with the same implementation as in the last exercise.

Verify opening angle between missing transverse momentum and signal photon is greater than 2 radians:

  if(!Manager()->ApplyCut(signal_photon->dphi_0_pi(event.rec()->MET().momentum()) < 2,
                          "dPhi(pT(miss), pT(photon))"))
    return true;

ΔR between electrons/muons (with pT > 10 GeV) and signal photon:

    std::any_of(event.rec()->electrons().begin(), event.rec()->electrons().end(),
                  [&signal_photon](const RecLeptonFormat& electron) {
                    return > 10 && electron.dr(signal_photon) > 0.5;
      "DR(electron, signal_photon)"))
    return true;

    std::any_of(muons.begin(), muons.end(),
                  [&signal_photon](const RecLeptonFormat* muon) {
                    return muon->pt() > 10 && muon->dr(signal_photon) > 0.5;
      "DR(*muon, signal_photon)"))
    return true;
  return true;

Note that while doing this exercise I discovered the std::none_of and std::any_of methods provided by the C++ standard library.
These proved any to reduce the code size and make it more explicit.

Execution on Sample File

At the time of this writing @lemouth hasn't had the chance yet to provide a suitable sample file.

As I'm due to go abroad for a few days pretty soon I release this code without being to execute it against such file.


Madanalysis Credits:
E. Conte, B. Fuks and G. Serret,
Comput. Phys. Commun. 184 (2013) 222

E. Conte, B. Dumont, B. Fuks and C. Wymant,
Eur. Phys. J. C 74 (2014) 10, 3103

B. Dumont, B. Fuks, S. Kraml et al.,
Eur. Phys. J. C 75 (2015) 2, 56

Series Backlinks

Authors get paid when people like you upvote their post.
If you enjoyed what you read here, create your account today and start earning FREE STEEM!
Sort Order:  

There are a lot of proton-proton collisions in the Sun.

If DM is produced in these collisions are any mass defects showing up in stellar evolution models?

That is, if this is actually happening would this produce different results in stellar simulations than we observe in actual stars?


That's interesting. Never thought about it. Do these collisions have enough energy to produce heavy particles?

Hi. Thank you for the contribution, your explanation is very understandable. I hope to see the edition of the corrections recommended by lemouth.

Please, remove the following text in the series backlinks section :):

If the post is not the first post in a series, link to the previous posts of the series.

Your contribution has been evaluated according to Utopian policies and guidelines, as well as a predefined set of questions pertaining to the category.

To view those questions and the relevant answers related to your post, click here.

Need help? Write a ticket on
Chat with us on Discord.

This post has been voted on by the steemstem curation team and voting trail.

There is more to SteemSTEM than just writing posts, check here for some more tips on being a community member. You can also join our discord here to get to know the rest of the community!

Hey @irelandscape
Thanks for contributing on Utopian.
We’re already looking forward to your next contribution!

Want to chat? Join us on Discord

Vote for Utopian Witness!

Congratulations @irelandscape! You have completed the following achievement on Steemit and have been rewarded with new badge(s) :

Award for the number of comments

Click on the badge to view your Board of Honor.
If you no longer want to receive notifications, reply to this comment with the word STOP

Do you like SteemitBoard's project? Then Vote for its witness and get one more award!