136#include "TRestDetectorSignalToRawSignalProcess.h"
138#include <TObjString.h>
139#include <TRestRawReadoutMetadata.h>
223 double startTimeNoOffset = 0;
228 bool thresholdReached =
false;
234 startTimeNoOffset = t;
235 thresholdReached =
true;
238 if (!thresholdReached) {
239 RESTWarning <<
"Integral threshold for trigger not reached" <<
RESTendl;
240 startTimeNoOffset = 0;
244 startTimeNoOffset = obs;
247 fReadout = GetMetadata<TRestDetectorReadout>();
249 if (fReadout ==
nullptr) {
250 RESTError <<
"TRestDetectorSignalToRawSignalProcess::ProcessEvent: "
251 <<
"TRestDetectorReadout metadata not found" <<
RESTendl;
255 set<const TRestDetectorSignal*> tpcSignals;
259 if (signal->GetSignalType() ==
"tpc") {
260 tpcSignals.insert(signal);
271 if (tpcSignals.empty()) {
276 double startTime = std::numeric_limits<float>::max();
277 for (
const auto& signal : tpcSignals) {
278 const auto minTime = signal->GetMinTime();
279 if (minTime < startTime) {
284 if (startTime >= std::numeric_limits<float>::max()) {
287 startTimeNoOffset = startTime;
290 RESTDebug <<
"TRestDetectorSignalToRawSignalProcess::ProcessEvent: "
291 <<
"Trigger mode integralThresholdTPC" <<
RESTendl;
293 const double signalIntegralThreshold = 0.5;
294 double totalEnergy = 0;
295 for (
const auto& signal : tpcSignals) {
296 totalEnergy += signal->GetIntegral();
298 if (totalEnergy < signalIntegralThreshold) {
303 double minTime = std::numeric_limits<float>::max();
304 for (
const auto& signal : tpcSignals) {
305 const auto maxSignalTime = signal->GetMaxTime();
306 if (maxSignalTime > maxTime) {
307 maxTime = maxSignalTime;
309 const auto minSignalTime = signal->GetMinTime();
310 if (minSignalTime < minTime) {
311 minTime = minSignalTime;
316 if (minTime > maxTime) {
318 RESTWarning <<
"TRestDetectorSignalToRawSignalProcess::ProcessEvent: "
325 <<
"TRestDetectorSignalToRawSignalProcess::ProcessEvent: " << inputEvent->GetID()
326 <<
" signal minTime < 0. Setting min time to 0, but this should probably never happen"
334 bool thresholdReached =
false;
335 double maxEnergy = 0;
336 while (t < maxTime) {
339 for (
const auto& signal : tpcSignals) {
342 if (energy > maxEnergy) {
345 if (maxEnergy > signalIntegralThreshold) {
346 thresholdReached =
true;
352 if (!thresholdReached) {
361 double startTime = t;
362 startTimeNoOffset = startTime;
370 cerr <<
"TRestDetectorSignalToRawSignalProcess::ProcessEvent: "
371 <<
"Trigger mode not recognized" <<
RESTendl;
377 Int_t signalID = signal->GetSignalID();
378 string type = signal->GetSignalType();
380 if (fParametersMap.find(type) == fParametersMap.end()) {
381 RESTWarning <<
"TRestDetectorSignalToRawSignalProcess::ProcessEvent: "
382 <<
"type " << type <<
" not found in parameters map" <<
RESTendl;
386 double sampling = fParametersMap.at(type).sampling;
387 double shapingTime = fParametersMap.at(type).shapingTime;
388 double calibrationGain = fParametersMap.at(type).calibrationGain;
389 double calibrationOffset = fParametersMap.at(type).calibrationOffset;
391 double timeStart = startTimeNoOffset -
fTriggerDelay * sampling;
392 double timeEnd = timeStart +
fNPoints * sampling;
393 RESTDebug <<
"fTimeStart: " << timeStart <<
" us " <<
RESTendl;
394 RESTDebug <<
"fTimeEnd: " << timeEnd <<
" us " <<
RESTendl;
398 cerr <<
"TRestDetectorSignalToRawSignalProcess::ProcessEvent: "
399 <<
"fTimeStart < - fTriggerDelay * fSampling" << endl;
408 RESTError <<
"TRestDetectorSignalToRawSignalProcess::ProcessEvent: "
409 <<
"fTimeStart < - fTriggerDelay * fSampling" <<
RESTendl;
413 vector<Double_t> data(
fNPoints, calibrationOffset);
415 for (
int m = 0; m < signal->GetNumberOfPoints(); m++) {
416 Double_t t = signal->GetTime(m);
417 Double_t d = signal->GetData(m);
420 cout <<
"Signal: " << n <<
" Sample: " << m <<
" T: " << t <<
" Data: " << d << endl;
423 if (t > timeStart && t < timeEnd) {
425 Int_t timeBin = (Int_t)round((t - timeStart) / sampling);
427 if (
GetVerboseLevel() >= TRestStringOutput::REST_Verbose_Level::REST_Warning) {
428 if (timeBin < 0 || timeBin >
fNPoints) {
429 cout <<
"Time bin out of range!!! bin value: " << timeBin << endl;
434 RESTDebug <<
"Adding data: " << signal->GetData(m) <<
" to Time Bin: " << timeBin <<
RESTendl;
435 data[timeBin] += calibrationGain * signal->GetData(m);
439 if (shapingTime > 0) {
440 const auto sinShaper = [](Double_t t) -> Double_t {
446 return TMath::Exp(-3.0 * t) * TMath::Power(t, 3.0) * TMath::Sin(t) * 22.68112123672292;
449 const auto shapingFunction = [&sinShaper](Double_t t) -> Double_t {
459 vector<Double_t> dataAfterShaping(
fNPoints, calibrationOffset);
460 for (
int i = 0; i <
fNPoints; i++) {
461 const Double_t value = data[i] - calibrationOffset;
466 for (
int j = 0; j <
fNPoints; j++) {
467 dataAfterShaping[j] += value * shapingFunction(((j - i) * sampling) / shapingTime);
470 data = dataAfterShaping;
475 for (
int x = 0; x <
fNPoints; x++) {
476 double value = round(data[x]);
477 if (
GetVerboseLevel() >= TRestStringOutput::REST_Verbose_Level::REST_Warning) {
478 if (value < numeric_limits<Short_t>::min() || value > numeric_limits<Short_t>::max()) {
479 RESTDebug <<
"value (" << value <<
") is outside short range ("
480 << numeric_limits<Short_t>::min() <<
", " << numeric_limits<Short_t>::max()
485 if (value < numeric_limits<Short_t>::min()) {
486 value = numeric_limits<Short_t>::min();
488 }
else if (value > numeric_limits<Short_t>::max()) {
489 value = numeric_limits<Short_t>::max();
498 RESTDebug <<
"Adding signal to raw signal event" <<
RESTendl;
503 RESTDebug <<
"TRestDetectorSignalToRawSignalProcess. Returning event with N signals "
514 TString readoutTypesString =
GetParameter(
"readoutTypes",
"");
516 TObjArray* readoutTypesArray = readoutTypesString.Tokenize(
",");
517 for (
int i = 0; i < readoutTypesArray->GetEntries(); i++) {
518 fReadoutTypes.insert(((TObjString*)readoutTypesArray->At(i))->GetString().Data());
520 cout <<
"readout types: ";
521 for (
const auto& type : fReadoutTypes) {
527 const string defaultType;
528 fReadoutTypes.insert(defaultType);
529 fParametersMap[defaultType] = {};
531 for (
const auto& type : fReadoutTypes) {
532 fReadoutTypes.insert(type);
533 fParametersMap[type] = {};
535 string typeCamelCase = type;
536 typeCamelCase[0] = toupper(typeCamelCase[0]);
539 parameters.sampling = GetDblParameterWithUnits(
"sampling" + typeCamelCase, parameters.sampling);
540 parameters.shapingTime =
541 GetDblParameterWithUnits(
"shapingTime" + typeCamelCase, parameters.shapingTime);
542 parameters.calibrationGain =
543 GetDblParameterWithUnits(
"gain" + typeCamelCase, parameters.calibrationGain);
544 parameters.calibrationOffset =
545 GetDblParameterWithUnits(
"offset" + typeCamelCase, parameters.calibrationOffset);
546 parameters.calibrationEnergy =
547 Get2DVectorParameterWithUnits(
"calibrationEnergy" + typeCamelCase, parameters.calibrationEnergy);
548 parameters.calibrationRange =
549 Get2DVectorParameterWithUnits(
"calibrationRange" + typeCamelCase, parameters.calibrationRange);
551 const bool isLinearCalibration =
552 (parameters.calibrationEnergy.Mod() != 0 && parameters.calibrationRange.Mod() != 0);
554 if (isLinearCalibration) {
555 const auto range = numeric_limits<Short_t>::max() - numeric_limits<Short_t>::min();
556 parameters.calibrationGain =
557 range * (parameters.calibrationRange.Y() - parameters.calibrationRange.X()) /
558 (parameters.calibrationEnergy.Y() - parameters.calibrationEnergy.X());
559 parameters.calibrationOffset =
560 range * (parameters.calibrationRange.X() -
561 parameters.calibrationGain * parameters.calibrationEnergy.X()) +
562 numeric_limits<Short_t>::min();
564 fParametersMap[type] = parameters;
568 if (nPoints == PARAMETER_NOT_FOUND_STR) {
574 const set<string> validTriggerModes = {
"firstDeposit",
"integralThreshold",
"fixed",
575 "observable",
"firstDepositTPC",
"integralThresholdTPC"};
578 <<
"' which is not a valid trigger mode. Please use one of the following trigger modes: ";
579 for (
const auto& triggerMode : validTriggerModes) {
580 RESTError << triggerMode <<
" ";
591 fSampling = fParametersMap.at(defaultType).sampling;
592 fShapingTime = fParametersMap.at(defaultType).shapingTime;
594 fCalibrationOffset = fParametersMap.at(defaultType).calibrationOffset;
601 RESTError <<
"You need to set 'triggerModeObservableName' to a valid analysis tree observable"
610Double_t TRestDetectorSignalToRawSignalProcess::GetEnergyFromADC(Double_t adc,
const string& type)
const {
611 if (fParametersMap.find(type) == fParametersMap.end()) {
612 RESTWarning <<
"TRestDetectorSignalToRawSignalProcess::GetEnergyFromADC: "
613 <<
"type " << type <<
" not found in parameters map" <<
RESTendl;
616 const auto gain = fParametersMap.at(type).calibrationGain;
617 const auto offset = fParametersMap.at(type).calibrationOffset;
618 return (adc - offset) / gain;
621Double_t TRestDetectorSignalToRawSignalProcess::GetADCFromEnergy(Double_t energy,
const string& type)
const {
622 if (fParametersMap.find(type) == fParametersMap.end()) {
623 RESTWarning <<
"TRestDetectorSignalToRawSignalProcess::GetEnergyFromADC: "
624 <<
"type " << type <<
" not found in parameters map" <<
RESTendl;
627 const auto gain = fParametersMap.at(type).calibrationGain;
628 const auto offset = fParametersMap.at(type).calibrationOffset;
629 return energy * gain + offset;
632Double_t TRestDetectorSignalToRawSignalProcess::GetTimeFromBin(Double_t bin,
const string& type)
const {
633 if (fParametersMap.find(type) == fParametersMap.end()) {
634 RESTWarning <<
"TRestDetectorSignalToRawSignalProcess::GetEnergyFromADC: "
635 <<
"type " << type <<
" not found in parameters map" <<
RESTendl;
638 const auto sampling = fParametersMap.at(type).sampling;
642Double_t TRestDetectorSignalToRawSignalProcess::GetBinFromTime(Double_t time,
const string& type)
const {
643 if (fParametersMap.find(type) == fParametersMap.end()) {
644 RESTWarning <<
"TRestDetectorSignalToRawSignalProcess::GetEnergyFromADC: "
645 <<
"type " << type <<
" not found in parameters map" <<
RESTendl;
648 const auto sampling = fParametersMap.at(type).sampling;
649 return (UShort_t)((time +
fTriggerDelay * sampling) / sampling);
659 for (
const auto& readoutType : fReadoutTypes) {
661 string type = readoutType;
665 RESTMetadata <<
"Readout type: " << type <<
RESTendl;
666 RESTMetadata <<
"Sampling time: " << fParametersMap.at(readoutType).sampling * 1000 <<
" ns"
668 const double shapingTime = fParametersMap.at(readoutType).shapingTime;
669 if (shapingTime > 0) {
670 RESTMetadata <<
"Shaping time: " << shapingTime * 1000 <<
" ns" <<
RESTendl;
673 if (IsLinearCalibration()) {
674 RESTMetadata <<
"Calibration energies: (" << fParametersMap.at(readoutType).calibrationEnergy.X()
675 <<
", " << fParametersMap.at(readoutType).calibrationEnergy.Y() <<
") keV"
677 RESTMetadata <<
"Calibration range: (" << fParametersMap.at(readoutType).calibrationRange.X()
678 <<
", " << fParametersMap.at(readoutType).calibrationRange.Y() <<
")" <<
RESTendl;
680 RESTMetadata <<
"ADC Gain: " << fParametersMap.at(readoutType).calibrationGain <<
RESTendl;
681 RESTMetadata <<
"ADC Offset: " << fParametersMap.at(readoutType).calibrationOffset <<
RESTendl;
A process to convert a TRestDetectorSignalEvent into a TRestRawSignalEvent.
TVector2 fCalibrationEnergy
two distinct energy values used for calibration
TRestDetectorSignalEvent * fInputSignalEvent
A pointer to the specific TRestDetectorSignalEvent input.
TRestEvent * ProcessEvent(TRestEvent *inputEvent) override
The main processing event function.
Double_t fSampling
The sampling time from the binned raw output signal.
void Initialize() override
Function to initialize input/output event members and define the section name.
void InitProcess() override
To be executed at the beginning of the run (outside event loop)
TRestRawSignalEvent * fOutputRawSignalEvent
A pointer to the specific TRestRawSignalEvent input.
std::string fTriggerMode
It is used to define the way the time start will be fixed.
void PrintMetadata() override
It prints out the process parameters stored in the metadata structure.
TVector2 fCalibrationRange
position in the range corresponding to the energy in 'fCalibrationEnergy'. Values between 0 and 1
Double_t fIntegralThreshold
This parameter is used by integralWindow trigger mode to define the acquisition window.
Int_t fNPoints
The number of points of the resulting output signal.
TRestDetectorSignalToRawSignalProcess()
Default constructor.
std::string fTriggerModeObservableName
The name of the observable used to define the trigger mode (i.e. g4Ana_sensitiveVolumeFirstHitTime)
~TRestDetectorSignalToRawSignalProcess()
Default destructor.
Int_t fTriggerFixedStartTime
The starting time for the "fixed" trigger mode (can be offset by the trigger delay)
Double_t fCalibrationGain
Int_t fTriggerDelay
The number of time bins the time start is delayed in the resulting output signal.
void LoadConfig(const std::string &configFilename, const std::string &name="")
Function to load the configuration from an external configuration file.
void InitFromConfigFile() override
Function reading input parameters from the RML TRestDetectorSignalToRawSignalProcess metadata section...
void BeginPrintProcess()
[name, cut range]
void SetObservableValue(const std::string &name, const T &value)
Set observable value for AnalysisTree.
A base class for any REST event.
An event container for time rawdata signals with fixed length.
It defines a Short_t array with a physical parameter that evolves in time using a fixed time bin.
void Print() const
It prints the signal data on screen.
void SetSignalID(Int_t sID)
It sets the id number of the signal.
void AddPoint(Short_t)
Adds a new point to the end of the signal data array.
@ REST_Debug
+show the defined debug messages
Double_t StringToDouble(std::string in)
Gets a double from a string.
Int_t StringToInteger(std::string in)
Gets an integer from a string.