Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Populate EventHeader from EventWindowMarker and ProtonBunchTime #1252

Draft
wants to merge 7 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions CommonMC/fcl/prolog.fcl
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,13 @@ CommonMC: {
RecoFromMCTruth : true
RecoFromMCTruthErr : 0.5
}
# Make an EventHeader object from the ProtonBunchTime and EventWindowMarker data products
makeEventHeaderFromLegacyMC : {
module_type : MakeEventHeaderFromLegacyMC
protonBunchTimeMCTag : "EWMProducer"
eventWindowMarkerTag : "EWMProducer"
maxPrint : 0
}
}
FindMCPrimary : {
module_type : FindMCPrimary
Expand Down
132 changes: 132 additions & 0 deletions CommonMC/src/MakeEventHeaderFromLegacyMC_module.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
//
// Read legacy MC data products and create an mu2e::EventHeader data product, that is populated
// from information found in the EventWindowMarker and ProtonBunchTime data products. This emulates
// what data will look like.
//
// The plan is to prepare for data by migrating trigger and reco algorithms to using this
// data product instead of EventWindowMarker and ProtonBunchTime.
//
// The mu2e::EventHEadevent header combines information from the heartbeat packet, defined in,
// https://mu2e-docdb.fnal.gov/cgi-bin/sso/ShowDocument?docid=4914
// and the propossed CFO Event Window Data Record, defined on page 22 of
// https://mu2e-docdb.fnal.gov/cgi-bin/sso/ShowDocument?docid=19095
//
// Rob Kutschke, 2024
//

#include "Offline/DataProducts/inc/EventWindowMarker.hh"
#include "Offline/GlobalConstantsService/inc/GlobalConstantsHandle.hh"
#include "Offline/GlobalConstantsService/inc/PhysicsParams.hh"
#include "Offline/MCDataProducts/inc/ProtonBunchTimeMC.hh"
#include "Offline/Mu2eUtilities/inc/EventHeaderFacade.hh"

#include "artdaq-core-mu2e/Data/EventHeader.hh"

#include "art/Framework/Core/EDProducer.h"
#include "art/Framework/Core/ModuleMacros.h"
#include "art/Framework/Principal/Event.h"

#include <iostream>

namespace mu2e {

class MakeEventHeaderFromLegacyMC : public art::EDProducer {

public:

struct Config {
using Name=fhicl::Name;
using Comment=fhicl::Comment;

fhicl::Atom<art::InputTag> protonBunchTimeMCTag{Name("protonBunchTimeMCTag"), Comment("Input tag for a ProtonBunchTimeMC data product.")};
fhicl::Atom<art::InputTag> eventWindowMarkerTag{Name("eventWindowMarkerTag"), Comment("Input tag for an EventWindowMarker data product.")};
fhicl::Atom<unsigned> maxPrint{Name("maxPrint"), Comment("Maximum number of events to print."), 0};
};
typedef art::EDProducer::Table<Config> Parameters;

explicit MakeEventHeaderFromLegacyMC(const Parameters& conf);

void produce( art::Event& event) override;

private:

// A copy of the run time configuration.
Config _conf;

// Initialized from run-time configuration
art::ProductToken<ProtonBunchTimeMC> _protonBunchTimeMCToken;
art::ProductToken<EventWindowMarker> _eventWindowMarkerToken;
unsigned _maxPrint;

// Intialized from GlobalConstants service
// Duration of one tick of the DAQ clock
double _nominalDAQClockTick; // ns

// Duration of one tick of the clock that measures RF0
double _nominalRF0ClockTick; // ns

// Counter to limit printout.
unsigned _nEvents = 0;

};

MakeEventHeaderFromLegacyMC::MakeEventHeaderFromLegacyMC(const Parameters& conf)
: art::EDProducer(conf),
_conf(conf()),
_protonBunchTimeMCToken{consumes<ProtonBunchTimeMC>(conf().protonBunchTimeMCTag())},
_eventWindowMarkerToken{consumes<EventWindowMarker>(conf().eventWindowMarkerTag())},
_maxPrint(conf().maxPrint()),
_nominalDAQClockTick{GlobalConstantsHandle<PhysicsParams>()->getNominalDAQClockTick()},
_nominalRF0ClockTick{GlobalConstantsHandle<PhysicsParams>()->getNominalRF0ClockTick()}
{
produces<EventHeader>();
}

void MakeEventHeaderFromLegacyMC::produce( art::Event& event){

auto const& pbtmc = event.getProduct(_protonBunchTimeMCToken);
auto const& ewm = event.getProduct(_eventWindowMarkerToken);

const uint16_t eventDuration{uint16_t(std::round(ewm.eventLength()/_nominalDAQClockTick))};

// Fixme: this may need more work when new bits are assigned.
const uint8_t flags{uint8_t(ewm.spillType())};

// Fixme: do we want to mock this up?
const EWT ewt{0};

// Convert MC truth time offset to the unsigned binary format.
// Fixme: need to understand and document the actual conventions for this parameter.
// currently reverse engineering what was done in MDC2020.
const uint8_t rfmTDC_estimated = uint8_t( std::floor(-pbtmc.pbtime_ / _nominalRF0ClockTick) );

// Fixme: Good enough for now. Our legacy MC info does not have separate estimated and measured values.
const uint8_t rfmTDC_measured{rfmTDC_estimated};

// Fixme: Need to set real bits here.
const uint32_t mode{0};

auto header = std::make_unique<EventHeader>( ewt, mode, rfmTDC_estimated, flags, eventDuration, rfmTDC_measured);

if ( _nEvents < _maxPrint ) {
++_nEvents;
std::cout << "\nEvent: " << event.id() << std::endl;
std::cout << " EWM: Spill type: " << ewm.spillType() << " Event length: " << ewm.eventLength() << std::endl;
std::cout << " ProtonBunchTimeMC: pbtime_: " << pbtmc.pbtime_ << std::endl;
std::cout << " Header: " << *header << std::endl;
EventHeaderFacade f(*header, *GlobalConstantsHandle<PhysicsParams>());
std::cout << " Readback: " << std::endl;
std::cout << " Event duration: " << f.eventDuration() << std::endl;
std::cout << " pbtime measured: " << f.rf0OffsetMeasured()
<< " residual: " << f.rf0OffsetMeasured()- pbtmc.pbtime_
<< std::endl;
std::cout << " pbtime estimated: " << f.rf0OffsetEstimated() << std::endl;
}

event.put(std::move(header));

} // end analyze

} // end namespace mu2e

DEFINE_ART_MODULE(mu2e::MakeEventHeaderFromLegacyMC)
1 change: 1 addition & 0 deletions CommonMC/src/SConscript
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ helper.make_plugins( [ mainlib,
'mu2e_DataProducts',
'mu2e_DbTables',
'mu2e_GeneralUtilities',
'artdaq-core-mu2e_Data',
'art_Framework_Core',
'art_Framework_Principal',
'art_Framework_Services_Registry',
Expand Down
1 change: 1 addition & 0 deletions GlobalConstantsService/data/globalConstants_01.txt
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ double physicsParams.nominalDRPeriod = 1695.; // ns
int physicsParams.nominalDAQTicks = 68; // ticks of DAQ clock in DRPeriod
int physicsParams.nominalDAQOnSpillBins = 5; // how often to 68->67
double physicsParams.nominalDAQFrequency = 40.; // MHz
double physicsParams.nominalRF0ClockFrequency = 800.; // MHz. Frequency of the clock that measures RF0 offset.

// charged pion and kaon
vector<int> physicsParams.freeLifePDGId = { 211, 312 };
Expand Down
11 changes: 8 additions & 3 deletions GlobalConstantsService/inc/PhysicsParams.hh
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@ namespace mu2e

typedef std::string targetMat;

static constexpr double MHzPerGHz = 1000.; // Number of one MHz in one GHz.

// Proton parameters
double getProtonEnergy () const { return _protonEnergy; }
double getProtonKE () const { return _protonKE; }
Expand All @@ -47,7 +49,9 @@ namespace mu2e
int getNominalDAQTicks() const { return _nominalDAQTicks; } // counts, DAQ ticks per DRperiod
int getNominalDAQOnSpillBins() const { return _nominalDAQOnSpillBins; } // how often to 68->67
double getNominalDAQFrequency() const { return _nominalDAQFrequency; } // MHz
double getNominalDAQClockTick() const { return 1000.0/_nominalDAQFrequency; } // ns
double getNominalDAQClockTick() const { return MHzPerGHz/_nominalDAQFrequency; } // ns
double getNominalRF0ClockFrequency() const { return _nominalRF0ClockFrequency; } // MHz
double getNominalRF0ClockTick() const { return MHzPerGHz/_nominalRF0ClockFrequency; } // ns

// Lifetimes of free (not stopped) particles. We provide them
// here because values coming from other sources are not accurate
Expand Down Expand Up @@ -169,10 +173,11 @@ namespace mu2e
double _protonKE;
double _protonMomentum;

double _nominalDRPeriod;
double _nominalDRPeriod; // ns
int _nominalDAQTicks;
int _nominalDAQOnSpillBins;
double _nominalDAQFrequency;
double _nominalDAQFrequency; // MHz
double _nominalRF0ClockFrequency; // MHz

typedef std::map<PDGCode::type, double> FreeLifeMap;
FreeLifeMap freeLifetime_;
Expand Down
1 change: 1 addition & 0 deletions GlobalConstantsService/src/PhysicsParams.cc
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ namespace mu2e {
_nominalDAQTicks = config.getInt("physicsParams.nominalDAQTicks");
_nominalDAQOnSpillBins = config.getInt("physicsParams.nominalDAQOnSpillBins");
_nominalDAQFrequency = config.getDouble("physicsParams.nominalDAQFrequency");
_nominalRF0ClockFrequency = config.getDouble("physicsParams.nominalRF0ClockFrequency");

std::vector<int> tmpPDGId;
config.getVectorInt("physicsParams.freeLifePDGId", tmpPDGId, tmpPDGId);
Expand Down
36 changes: 36 additions & 0 deletions Mu2eUtilities/inc/EventHeaderFacade.hh
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
#ifndef Mu2eUtilities_inc_EventHeaderFacade_hh
#define Mu2eUtilities_inc_EventHeaderFacade_hh
//
// Facade class to Compute derived information from an EventHeader object.
//
// Rob Kutschke, 2024

#include "artdaq-core-mu2e/Data/EventHeader.hh"

namespace mu2e {

class PhysicsParams;

class EventHeaderFacade {
public:

EventHeaderFacade( EventHeader const& hdr, PhysicsParams const& physicsParams );

double eventDuration() const { return double(_hdr.eventDuration) * _nominalDAQClockTick; }
double rf0OffsetMeasured() const { return -(double(_hdr.rfmTDC_measured)+0.5) * _nominalRF0ClockTick; }
double rf0OffsetEstimated() const { return -(double(_hdr.rfmTDC_est)+0.5) * _nominalRF0ClockTick; }

private:
EventHeader const& _hdr;

// Duration of one tick of the DAQ clock
double _nominalDAQClockTick; // ns

// Duration of one tick of the clock that measures RF0
double _nominalRF0ClockTick; // ns

}; // end class EventHeaderFacade

} // end namespace mu2e

#endif/*Mu2eUtilities_inc_EventHeaderFacade_hh*/
14 changes: 14 additions & 0 deletions Mu2eUtilities/src/EventHeaderFacade.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
//
// Facade class to Compute derived information from an EventHeader object.
//
// Rob Kutschke, 2024

#include "Offline/GlobalConstantsService/inc/PhysicsParams.hh"
#include "Offline/Mu2eUtilities/inc/EventHeaderFacade.hh"

mu2e::
EventHeaderFacade::EventHeaderFacade( EventHeader const& hdr, PhysicsParams const& par ):
_hdr(hdr),
_nominalDAQClockTick{par.getNominalDAQClockTick()},
_nominalRF0ClockTick{par.getNominalRF0ClockTick()}
{}
1 change: 1 addition & 0 deletions Mu2eUtilities/src/SConscript
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ mainlib = helper.make_mainlib ( [ 'mu2e_ConditionsService',
'mu2e_GeneralUtilities',
'mu2e_TrackerGeom',
'BTrk_BbrGeom',
'artdaq-core-mu2e_Data',
'gsl',
'art_Persistency_Common',
'art_Persistency_Provenance',
Expand Down
4 changes: 4 additions & 0 deletions Print/fcl/print.fcl
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,10 @@ physics :{

printModule : {
module_type : PrintModule
EventHeaderPrinter : {
verbose : 1
}

genParticlePrinter : {
verbose : 1
}
Expand Down
3 changes: 3 additions & 0 deletions Print/fcl/printLong.fcl
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@ physics :{
printModule : {
module_type : PrintModule

EventHeaderPrinter : {
verbose : 1
}
statusG4Printer : {
verbose : 0
}
Expand Down
35 changes: 35 additions & 0 deletions Print/inc/EventHeaderPrinter.hh
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
//
// Utility class to print an EventHeader with conversions to physical units.
//
#ifndef Print_inc_EventHeaderPrinter_hh
#define Print_inc_EventHeaderPrinter_hh

#include <cstring>
#include <iostream>

#include "CLHEP/Vector/ThreeVector.h"

#include "Offline/Print/inc/ProductPrinter.hh"
#include "artdaq-core-mu2e/Data/EventHeader.hh"
#include "art/Framework/Principal/Handle.h"
#include "canvas/Persistency/Common/Ptr.h"

namespace mu2e {

class EventHeaderPrinter : public ProductPrinter {
public:
EventHeaderPrinter() {}
EventHeaderPrinter(const Config& conf) : ProductPrinter(conf) {}

// all the ways to request a printout
void Print(art::Event const& event, std::ostream& os = std::cout) override;
void Print(const art::Handle<EventHeader>& handle, std::ostream& os = std::cout);
void Print(const art::ValidHandle<EventHeader>& handle,
std::ostream& os = std::cout);
void Print(const mu2e::EventHeader& obj, int ind = -1,
std::ostream& os = std::cout);
void PrintHeader(const std::string& tag, std::ostream& os = std::cout);
};

} // namespace mu2e
#endif
65 changes: 65 additions & 0 deletions Print/src/EventHeaderPrinter.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@

#include "Offline/GlobalConstantsService/inc/GlobalConstantsHandle.hh"
#include "Offline/GlobalConstantsService/inc/PhysicsParams.hh"
#include "Offline/Mu2eUtilities/inc/EventHeaderFacade.hh"
#include "Offline/Print/inc/EventHeaderPrinter.hh"
#include "art/Framework/Principal/Provenance.h"
#include <iomanip>
#include <string>

void mu2e::EventHeaderPrinter::Print(art::Event const& event, std::ostream& os) {
if (verbose() < 1) return;
if (tags().empty()) {
// if a list of instances not specified, print all instances
std::vector<art::Handle<EventHeader> > vah = event.getMany<EventHeader>();
for (auto const& ah : vah) Print(ah);
} else {
// print requested instances
for (const auto& tag : tags()) {
auto ih = event.getValidHandle<EventHeader>(tag);
Print(ih);
}
}
}

void mu2e::EventHeaderPrinter::Print(const art::Handle<EventHeader>& handle,
std::ostream& os) {
if (verbose() < 1) return;
// the product tags with all four fields, with underscores
std::string tag = handle.provenance()->productDescription().branchName();
tag.pop_back(); // remove trailing dot
PrintHeader(tag, os);
Print(*handle);
}

void mu2e::EventHeaderPrinter::Print(const art::ValidHandle<EventHeader>& handle,
std::ostream& os) {
if (verbose() < 1) return;
// the product tags with all four fields, with underscores
std::string tag = handle.provenance()->productDescription().branchName();
tag.pop_back(); // remove trailing dot
PrintHeader(tag, os);
Print(*handle);
}

void mu2e::EventHeaderPrinter::Print(const mu2e::EventHeader& obj, int ind,
std::ostream& os) {
if (verbose() < 1) return;

os << std::setiosflags(std::ios::fixed | std::ios::right);

os << obj << std::endl;

if (verbose() < 2) return;
EventHeaderFacade ehf( obj, *(GlobalConstantsHandle<PhysicsParams>()) );
os << " Event Duration: " << ehf.eventDuration() << " ns"
<< "\n RF0 Offset Estimated: " << ehf.rf0OffsetEstimated() << " ns"
<< "\n RF0 Offset Measured: " << ehf.rf0OffsetMeasured() << " ns"
<< std::endl;
}

void mu2e::EventHeaderPrinter::PrintHeader(const std::string& tag,
std::ostream& os) {
if (verbose() < 1) return;
os << "\nProductPrint " << tag << "\n";
}
Loading