Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2024-04-06 11:58:05

0001 #ifndef CalibCalorimetry_HcalAlgos_QIE8Simulator_h_
0002 #define CalibCalorimetry_HcalAlgos_QIE8Simulator_h_
0003 
0004 #include "CalibCalorimetry/HcalAlgos/interface/ConstantStepOdeSolver.h"
0005 #include "CalibCalorimetry/HcalAlgos/interface/AbsElectronicODERHS.h"
0006 
0007 //
0008 // This class is needed mostly in order to represent the charge
0009 // to ADC conversion inside the QIE8 chip
0010 //
0011 class QIE8Simulator {
0012 public:
0013   static const unsigned maxlen = HcalInterpolatedPulse::maxlen;
0014 
0015   // In case the default constructor is used, "setRHS" method must be
0016   // called before running the simulation
0017   QIE8Simulator();
0018 
0019   // Constructor which includes a proper model
0020   QIE8Simulator(const AbsElectronicODERHS& model,
0021                 unsigned chargeNode,
0022                 bool interpolateCubic = false,
0023                 double preampOutputCut = -1.0e100,
0024                 double inputGain = 1.0,
0025                 double outputGain = 1.0);
0026 
0027   void setRHS(const AbsElectronicODERHS& rhs, unsigned chargeNode, bool interpolateCubic = false);
0028 
0029   inline const AbsElectronicODERHS& getRHS() const {
0030     const AbsODERHS* ptr = solver_.getRHS();
0031     if (!ptr)
0032       throw cms::Exception("In QIE8Simulator::getRHS: RHS is not set");
0033     return *(static_cast<const AbsElectronicODERHS*>(ptr));
0034   }
0035 
0036   // Simple inspectors
0037   inline double getInputGain() const { return inputGain_; }
0038   inline double getOutputGain() const { return outputGain_; }
0039   inline unsigned long getRunCount() const { return runCount_; }
0040   inline double getPreampOutputCut() const { return preampOutputCut_; }
0041 
0042   // Examine preamp  model parameters
0043   inline unsigned nParameters() const { return getRHS().nParameters(); }
0044   inline double getParameter(const unsigned which) const { return getRHS().getParameter(which); }
0045 
0046   // Set gains
0047   inline void setInputGain(const double g) {
0048     inputGain_ = g;
0049     validateGain();
0050   }
0051   inline void setOutputGain(const double g) {
0052     outputGain_ = g;
0053     validateGain();
0054   }
0055 
0056   // Set preamp initial conditions
0057   void setInitialConditions(const double* values, const unsigned len);
0058   void zeroInitialConditions();
0059 
0060   // Set preamp model parameters
0061   inline void setParameter(const unsigned which, const double p) { modifiableRHS().setParameter(which, p); }
0062   inline void setLeadingParameters(const double* values, const unsigned len) {
0063     modifiableRHS().setLeadingParameters(values, len);
0064   }
0065 
0066   // Set the minimum value for the preamp output
0067   inline void setPreampOutputCut(const double p) { preampOutputCut_ = p; }
0068 
0069   // Set the input pulse
0070   template <class Signal>
0071   inline void setInputSignal(const Signal& inputSignal) {
0072     modifiableRHS().setInputPulse(inputSignal);
0073     modifiableRHS().inputPulse() *= inputGain_;
0074   }
0075 
0076   // Get the input pulse
0077   inline const HcalInterpolatedPulse& getInputSignal() const { return getRHS().inputPulse(); }
0078 
0079   // Set the input pulse data. This will not modify
0080   // signal begin and end times.
0081   template <class Real>
0082   inline void setInputShape(const Real* values, const unsigned len) {
0083     modifiableRHS().inputPulse().setShape(values, len);
0084     modifiableRHS().inputPulse() *= inputGain_;
0085   }
0086 
0087   // Scale the input pulse by some constant factor
0088   inline void scaleInputSignal(const double s) { modifiableRHS().inputPulse() *= s; }
0089 
0090   // Manipulate input pulse amplidude
0091   inline double getInputAmplitude() const { return getRHS().inputPulse().getPeakValue() / inputGain_; }
0092 
0093   inline void setInputAmplitude(const double a) { modifiableRHS().inputPulse().setPeakValue(a * inputGain_); }
0094 
0095   // Manipulate input pulse total charge
0096   inline double getInputIntegral() const { return getRHS().inputPulse().getIntegral() / inputGain_; }
0097 
0098   inline void setInputIntegral(const double d) { modifiableRHS().inputPulse().setIntegral(d * inputGain_); }
0099 
0100   // Manipulate input pulse timing
0101   inline double getInputStartTime() const { return getRHS().inputPulse().getStartTime(); }
0102 
0103   inline void setInputStartTime(const double newStartTime) { modifiableRHS().inputPulse().setStartTime(newStartTime); }
0104 
0105   // Run the simulation. Parameters are as follows:
0106   //
0107   // dt        -- Simulation time step.
0108   //
0109   // tstop     -- At what time to stop the simulation. The actual
0110   //              stopping time will be the smaller of this parameter and
0111   //              dt*(maxlen - 1). The simulation always starts at t = 0.
0112   //
0113   // tDigitize -- When to start producing ADC counts. This argument
0114   //              must be non-negative.
0115   //
0116   // TS, lenTS -- Array (and its length) where ADC counts will be
0117   //              placed on exit.
0118   //
0119   // This method returns the number of "good" ADC time slices -- the
0120   // ones that completely covered by the simulation interval.
0121   //
0122   unsigned run(double dt, double tstop, double tDigitize, double* TS, unsigned lenTS);
0123 
0124   // Inspect simulation results
0125   double lastStopTime() const;
0126   double totalIntegratedCharge(double t) const;
0127   double preampPeakTime() const;
0128 
0129   // The following methods with simply return 0.0 in case
0130   // there are no corresponding nodes in the circuit
0131   double preampOutput(double t) const;
0132   double controlOutput(double t) const;
0133 
0134   // Time slice width in nanoseconds
0135   static inline double adcTSWidth() { return 25.0; }
0136 
0137 private:
0138   inline AbsElectronicODERHS& modifiableRHS() {
0139     AbsODERHS* ptr = solver_.getRHS();
0140     if (!ptr)
0141       throw cms::Exception("In QIE8Simulator::modifiableRHS: no RHS");
0142     return *(static_cast<AbsElectronicODERHS*>(ptr));
0143   }
0144 
0145   inline double getCharge(const double t) const {
0146     double q;
0147     if (integrateToGetCharge_)
0148       q = solver_.interpolateIntegrated(chargeNode_, t, useCubic_);
0149     else
0150       q = solver_.interpolateCoordinate(chargeNode_, t, useCubic_);
0151     return q;
0152   }
0153 
0154   void validateGain() const;
0155 
0156   RK4 solver_;
0157   std::vector<double> initialConditions_;
0158   std::vector<double> historyBuffer_;
0159   double preampOutputCut_;
0160   double inputGain_;
0161   double outputGain_;
0162   unsigned long runCount_;
0163   unsigned chargeNode_;
0164   bool integrateToGetCharge_;
0165   bool useCubic_;
0166 };
0167 
0168 #endif  // CalibCalorimetry_HcalAlgos_QIE8Simulator_h_