1 #include <mdet/Channel.h>
3 #include <mdet/MHierarchyInfo.h>
5 #include <utl/AugerUnits.h>
7 #include <fwk/RandomEngineRegistry.h>
15 #include <CLHEP/Random/RandGauss.h>
17 #include <boost/math/tools/roots.hpp>
18 #include <boost/math/tools/tuple.hpp>
19 using boost::math::tools::eps_tolerance;
20 using boost::math::tools::toms748_solve;
36 bool operator()(
const C& r1,
const C& r2) {
38 return r1.fTime < r2.fTime;
43 bool IsEqual(
double a,
double b,
double eps)
45 return std::fabs(a - b) < eps *
std::max( std::fabs(a), std::fabs(b));
49 class EqualPredicate {
51 EqualPredicate(
double e) : fEps(e) {
53 bool operator()(
double a,
double b) {
54 return IsEqual(a, b, fEps);
61 template <
class T,
class F>
62 class MyFunctionObject {
66 T operator()(T
const& t ) {
67 return fFctor(t) - fThr;
90 template<
class BackInsertionSequence,
class Thr,
class Fctor>
91 void RootFinder( MyFunctionObject<Thr,Fctor>& func, BackInsertionSequence& roots,
double s,
double e,
double f_min,
double f_max,
int nest,
double relTol) {
95 using namespace boost::math;
98 int digits = std::numeric_limits<double>::digits;
100 int get_digits = (digits * 3) /4;
102 const boost::uintmax_t maxit = 100;
103 boost::uintmax_t it = maxit;
105 eps_tolerance<double> tol(get_digits);
108 std::pair<double, double> bracket_root = toms748_solve(func, s, e, f_min, f_max, tol, it);
110 double r = bracket_root.first + (bracket_root.second - bracket_root.first)/2;
118 if ( (s <= r || IsEqual(r, s, relTol)) && (r <= e || IsEqual(r, e, relTol)) ) {
120 roots.push_back( r ) ;
121 if ( !IsEqual(r, s, relTol) && !IsEqual(r, e, relTol ) ) {
122 RootFinder( func, roots, s, r, func(s), func(r), nest+1, relTol);
123 RootFinder( func, roots, r, e, func(r), func(r), nest+1, relTol);
146 Register(fInvertingInputResistance);
147 Register(fFeedbackResistance);
149 Register(fLowCutoffFrequency);
150 Register(fHighCutoffFrequency);
151 Register(fThreshold);
152 Register(fResponseTime);
153 Register(fDiscriminatorLowLevel);
154 Register(fDiscriminatorHiLevel);
156 Register(fAbsoluteError);
157 Register(fInitialIntervalLength);
158 Register(fIterationsNumber);
159 Register(fMaxNumberOfErrors);
160 Register(fSignalShiftMean);
161 Register(fSignalShiftStdDev);
313 const std::complex<double> _1(1, 0);
314 const std::complex<double> i(0, 1);
315 return _1 + i * (freq / freqLimit);
324 const std::complex<double> openLoopGain =
GetDCGain() / fDenominator;
393 double o = prevOutput;
427 double currEnd = currStart + gap;
428 double shift = 0.1*gap;
432 MyFunctionObject<double,Proxy<Callable> > functor(thr,f);
435 for ( ; currEnd <=
fEndTime; currStart += gap, currEnd = currStart+gap ) {
437 double f_min = functor( currStart-shift ) ;
438 double f_max = functor( currEnd ) ;
441 RootFinder( functor,
fRawRoots, currStart-shift, currEnd, f_min, f_max, 0, relTol);
442 }
catch(
const std::exception& e) {
457 RawRootsContainer::iterator last = std::unique_copy(
461 EqualPredicate(relTol)
478 for (RawRootsContainer::const_iterator i =
fRawRoots.begin(), e =
fRawRoots.end(); i != e; ++i) {
481 const double delta = r.
fTime - prevTime;
483 const double halfTime = ( prevTime + r.
fTime ) / 2;
530 if (fRoots.empty()) {
531 double delta = t - fBeginTime;
535 return ComputeOutput(fBeginTime, delta, fChannel.GetDiscriminatorLowLevel());
548 RootIterator i = std::lower_bound(fRoots.begin(), fRoots.end(), key, comp);
553 if (i == fRoots.end()) {
555 deltaTime = t - fRoots.back().fTime;
556 prevOutput = fRoots.back().fOutput;
557 }
else if (i == fRoots.begin()) {
559 deltaTime = t - fBeginTime;
561 prevOutput = fChannel.GetDiscriminatorLowLevel();
566 deltaTime = t - prev->fTime;
567 prevOutput = prev->fOutput;
570 return ComputeOutput(t, deltaTime, prevOutput);
574 template<
class Iterator>
593 double borderTime = 0;
594 if (OverThreshold(time))
602 double prevTime = time;
603 for (Iterator i = beg; i != end; ++i) {
607 double test = (prevTime + t) / 2;
608 if (OverThreshold(test)) {
610 borderTime = prevTime;
624 double earliestTime = ComputeBorderTime(fRoots.begin(), fRoots.end(), fBeginTime);
626 double latestTime = ComputeBorderTime(fRoots.rbegin(), fRoots.rend(), fEndTime);
627 return latestTime - earliestTime;
634 return (*fInputPulse)(x[0]) - fChannel.GetThreshold();
double ComputeOutput(double signReferenceTime, double deltaTime, double prevOutput) const
Compute final output for a give time difference.
AtThresholdConstIterator AtThresholdBegin() const
Begin iterator over times.
static const char *const kComponentName
utl::Validated< double > fSlewRate
utl::Validated< double > fResponseTime
utl::Validated< double > fSignalShiftStdDev
utl::Validated< double > fLowCutoffFrequency
RandomEngineType & GetEngine()
utl::Validated< double > fDiscriminatorLowLevel
const Channel & fChannel
The channel where to apply the discrimination.
bool OverThreshold(double t) const
Check input agains threshold.
static const char *const kComponentsNames[13]
det::DetectorComponent< C, MManagerProvider > Type
Type specializing det::DetectorComponent for Muon hierarchy.
double GetInitialIntervalLength() const
Lenght of the intervals (in time) in which divide the whole interval where roots are looked for...
void Init()
Perform initialization.
unsigned int GetMaxNumberOfErrors() const
Maximum number of errors admited without loggin when solving the equation threshold == input...
RawRootsContainer fRawRoots
Plain root value (only times).
double ComputeSignalShift() const
Computes a signal shift value according this Channel's characteristics (and, particularly, to the distribution of these values).
static const char *const kComponentsIds[13]
double GetFeedbackResistance() const
The resistance within the feedback loop.
Helper class encapsulating the discriminator response logic.
Electronic front-end for the modules.
double ComputeBorderTime(Iterator beg, Iterator end, double time) const
Helper templated function to calculate the times that define the total span.
double fTransitionTime
Maximum time required to switch between states.
virtual ~Callable()
The deletion of the objects will be made through a Callable*.
T & GetData(P< T > &d, const std::string &p) const
Common utility function for configuration.
RootContainer fRoots
Once and for all calculate the roots given the input pulse.
double GetResponseTime() const
Response time of the discriminator associated with the channel.
double GetHighCutoffFrequency() const
Hi end of frequency response.
utl::Validated< double > fThreshold
utl::Validated< double > fSignalShiftMean
double GetDCGain() const
A dimensionless quantity signaling the DC gain.
double GetSlewRate() const
Voltage change per time unit.
Channel(int cId, const det::VManager::IndexMap &parentMap, const FrontEnd &parent)
Constructs the electronic channel.
double fTime
The x value (that's the root of the equation input == threshold).
Wraps the random number engine used to generate distributions.
std::complex< double > ComputeTransfer(double freq) const
Computes the circuit transfer function at the given frequency.
utl::Validated< int > fMaxNumberOfErrors
static const char *const kComponentId
utl::Validated< int > fIterationsNumber
double fOutput
The y value (that's the output voltage while in the associated time).
Templated specialization of the mdet::Channel::Discriminator::Callable interface. ...
utl::Validated< double > fAbsoluteError
RawRootsContainer::const_iterator AtThresholdConstIterator
Iterator over the times when the input signal reaches the threshold level.
double GetDiscriminatorLowLevel() const
Target voltage when the signal is lower than the threshold.
utl::Validated< double > fDCGain
double GetSignalShiftMean() const
Retrieves the mean shift.
double GetSignalShiftStdDev() const
The standard deviation of the shift.
double fBeginTime
Define the relevant interval start time.
double GetOverThresholdTimeSpan() const
Return the total time span over the discrimination threshold.
double GetInvertingInputResistance() const
The resistance attached to the inverting input.
unsigned int GetIterationsNumber() const
Number of iterations allowed for the root finding procedures.
AtThresholdConstIterator AtThresholdEnd() const
End iterator over times.
std::map< std::string, std::string > IndexMap
const std::unique_ptr< Callable > fInputPulse
The input pulse where to apply the discrimination.
double GetLowCutoffFrequency() const
Low end of frequency response.
double GetAbsoluteError() const
Absolute error for root finding.
utl::Validated< double > fFeedbackResistance
double operator()(double t) const
Evaluate the discriminator output given the input pulse.
std::complex< double > ComputeFrequencyFactor(double freq, double freqLimit) const
Helper method to compute the factor (in the transfer function) that depends on frequency.
RootContainer::const_iterator RootIterator
Iterator over our roots struct.
double ApplySaturation(double v) const
Compute the final output for a given difference agains the threshold.
utl::Validated< double > fHighCutoffFrequency
utl::Validated< double > fInvertingInputResistance
utl::Validated< double > fInitialIntervalLength
double GetThreshold() const
Discrimination threshold.
double fEndTime
Define the relevant interval final time.
utl::Validated< double > fDiscriminatorHiLevel
Discriminator(const Discriminator &d)
Copy.
double GetDiscriminatorHiLevel() const
Target voltage when the signal is higher than the threshold.