10#include <top/modules/TOPDoublePulseGenerator/TOPDoublePulseGeneratorModule.h>
13#include <top/geometry/TOPGeometryPar.h>
16#include <framework/datastore/StoreArray.h>
17#include <framework/datastore/StoreObjPtr.h>
20#include <framework/logging/Logger.h>
23#include <framework/dataobjects/EventMetaData.h>
24#include <top/dataobjects/TOPDigit.h>
61 "list of slots for which to generate cal pulse, empty list means all slots.",
65 "ASIC calibration channels (0 - 7), empty list means all channels.",
68 "time difference between first and second pulse [ns].", 21.87);
70 "sigma of time difference [ns].", 40.0e-3);
72 "vector of 256 sample time intervals to construct sample times. "
75 "if true, use sample times from database instead of sampleTimeIntervals.",
78 "number of storage windows (old FW used 64 out of 512)", (
unsigned) 512);
80 "if given, sample times will be saved as root histograms in this file",
95 digits.registerInDataStore();
102 for (
const auto& module : geo->getModules()) {
107 if (!geo->isModuleIDValid(moduleID))
108 B2ERROR(
"Invalid module ID found in input list: " << moduleID);
117 B2ERROR(
"Invalid ASIC channel found in input list: " << ch);
123 double syncTimeBase = geo->getNominalTDC().getSyncTimeBase();
130 B2INFO(
"TOPDoublePulseGenerator: using equidistant sample times");
132 std::vector<double> timeAxis;
133 timeAxis.push_back(0);
135 double rescale = 2 * syncTimeBase / timeAxis.back();
136 for (
auto& t : timeAxis) t *= rescale;
138 B2INFO(
"TOPDoublePulseGenerator: using sample times from steering");
140 B2ERROR(
"sampleTimeIntervals: size must be 256 or empty");
152 if (!(*m_timebase).isValid()) {
153 B2FATAL(
"Sample time calibration requested but not available for run "
154 << evtMetaData->getRun()
155 <<
" of experiment " << evtMetaData->getExperiment());
173 for (
unsigned asic = 0; asic < 64; asic++) {
176 auto pixelID = chMapper.getPixelID(channel);
181 unsigned scrodID = 0;
183 const auto* feMap = feMapper.getMap(moduleID, bs);
184 if (feMap) scrodID = feMap->getScrodID();
185 sampleTimes = (*m_timebase)->getSampleTimes(scrodID, channel % 128);
187 B2WARNING(
"No sample time calibration available for SCROD " << scrodID
188 <<
" channel " << channel % 128 <<
" - equidistant will be used");
193 double time = gRandom->Rndm() * sampleTimes->
getTimeRange();
195 double sample = sampleTimes->
getSample(window, time);
196 auto* digit = digits.appendNew(moduleID, pixelID, sample);
197 digit->setFirstWindow(window);
198 digit->setTime(time);
199 digit->setTimeError(timeError);
200 digit->setChannel(channel);
201 digit->setHitQuality(TOPDigit::c_CalPulse);
205 sample = sampleTimes->
getSample(window, time);
206 digit = digits.appendNew(moduleID, pixelID, sample);
207 digit->setFirstWindow(window);
208 digit->setTime(time);
209 digit->setTimeError(timeError);
210 digit->setChannel(channel);
211 digit->setHitQuality(TOPDigit::c_CalPulse);
230 if (fileName.empty())
return;
232 TFile* fout = TFile::Open(fileName.c_str(),
"recreate");
234 B2ERROR(
"Can't open the output file " << fileName);
240 TH1F scrods(
"scrodID",
"scrod ID's mapped to slots/boardstacks", 64, -0.5, 63.5);
241 scrods.SetXTitle(
"(slot - 1) * 4 + boardstack");
242 scrods.SetYTitle(
"scrod ID");
245 for (
int bs = 0; bs < 4; bs++) {
246 const auto* feMap = feMapper.getMap(moduleID, bs);
248 B2ERROR(
"No front-end mapping available for slot " << moduleID
249 <<
" boardstack " << bs);
252 unsigned scrodID = feMap->getScrodID();
253 std::string subdir =
"scrod" + std::to_string(scrodID);
254 int i = (moduleID - 1) * 4 + bs;
255 scrods.SetBinContent(i + 1, scrodID);
256 fout->mkdir(subdir.c_str());
262 for (
unsigned asic = 0; asic < 64; asic++) {
264 const auto* feMap = feMapper.getMap(moduleID, bs);
265 if (!feMap)
continue;
266 unsigned scrodID = feMap->getScrodID();
267 std::string subdir =
"scrod" + std::to_string(scrodID);
268 fout->cd(subdir.c_str());
273 sampleTimes = (*m_timebase)->getSampleTimes(scrodID, channel);
275 string forWhat =
"scrod " + to_string(scrodID) +
276 " channel " + to_string(channel) +
277 " (slot" + to_string(moduleID) +
", as" + to_string(asic) +
281 "Generator input: sample times for " + forWhat,
282 "sample number",
"t [ns]");
283 std::vector<double> dt;
284 for (
unsigned i = 1; i < timeAxis.size(); i++) {
285 dt.push_back(timeAxis[i] - timeAxis[i - 1]);
288 "Generator input: sample time bins for " + forWhat,
289 "sample number",
"#Delta t [ns]");
300 const std::string& name,
301 const std::string& title,
302 const std::string& xTitle,
303 const std::string& yTitle)
const
305 if (vec.empty())
return;
307 TH1F h(name.c_str(), title.c_str(), vec.size(), 0, vec.size());
308 h.SetXTitle(xTitle.c_str());
309 h.SetYTitle(yTitle.c_str());
310 if (name.find(
"Fit") != string::npos) h.SetLineColor(2);
312 for (
unsigned i = 0; i < vec.size(); i++) h.SetBinContent(i + 1, vec[i]);
Class for accessing objects in the database.
void setDescription(const std::string &description)
Sets the description of the module.
void setPropertyFlags(unsigned int propertyFlags)
Sets the flags for the module properties.
@ c_ParallelProcessingCertified
This module can be run in parallel processing mode safely (All I/O must be done through the data stor...
Accessor to arrays stored in the data store.
Type-safe access to single objects in the data store.
double m_timeDifference
time difference between first and second pulse
std::vector< unsigned > m_asicChannels
ASIC calibration channels.
std::vector< double > m_sampleTimeIntervals
sample time intervals
DBObjPtr< TOPCalTimebase > * m_timebase
sample times from database
unsigned m_storageWindows
number of storage windows
std::vector< int > m_moduleIDs
slot ID's to generate for
bool m_useDatabase
if true, use sample times from database
int m_sampleDivisions
number of sample divisions (from NominalTDC)
double m_timeResolution
sigma of time difference
std::string m_outputFileName
if given, store sample times as root histograms
TOPSampleTimes m_sampleTimes
sample times from steering input
Calibration constants of a singe ASIC channel: time axis (sample times)
double getTimeRange() const
Returns time axis range (time interval corresponding to 4 asic windows)
bool isCalibrated() const
Returns calibration status.
const TOPGeometry * getGeometry() const
Returns pointer to geometry object using basf2 units.
const ChannelMapper & getChannelMapper() const
Returns default channel mapper (mapping of channels to pixels)
static TOPGeometryPar * Instance()
Static method to obtain the pointer to its instance.
const FrontEndMapper & getFrontEndMapper() const
Returns front-end mapper (mapping of SCROD's to positions within TOP modules)
void addParam(const std::string &name, T ¶mVariable, const std::string &description, const T &defaultValue)
Adds a new parameter to the module.
#define REG_MODULE(moduleName)
Register the given module (without 'Module' suffix) with the framework.
double sqrt(double a)
sqrt for double
virtual void initialize() override
Initialize the Module.
virtual void event() override
Event processor.
virtual void endRun() override
End-of-run action.
virtual void terminate() override
Termination action.
TOPDoublePulseGeneratorModule()
Constructor.
void storeSampleTimes(std::string fileName)
Optionally store sample times used by the generator as root histograms fileName root output file name...
virtual void beginRun() override
Called when entering a new run.
virtual ~TOPDoublePulseGeneratorModule()
Destructor.
void saveAsHistogram(const std::vector< double > &vec, const std::string &name, const std::string &title, const std::string &xTitle="", const std::string &yTitle="") const
Save vector to histogram and write it out.
double getSample(int window, double time) const
Returns sample with respect to sample 0 of the specified ASIC window (inverse of getTime).
void setTimeAxis(double syncTimeBase)
Sets equidistant time axis (uncalibrated).
std::vector< double > getTimeAxis() const
Returns time axis (sample times)
Abstract base class for different kinds of events.
record to be used to store ASIC info