ResponseCurve.cpp

00001 #include "ResponseCurve.h"
00002 #include "ChipConfiguration.h"
00003 
00004 #include "TF1.h"
00005 #include <iostream>
00006 #include <sstream>
00007 using namespace std;
00008 
00009 namespace SctData {
00010     ResponseCurve& ResponseCurve::operator=(const ResponseCurve& r) throw(){
00011     shared_ptr<TF1> f=r.getFunction();
00012     getFunction()->SetParameters(f->GetParameter(0), f->GetParameter(1), f->GetParameter(2));
00013     return *this;
00014     }
00015     
00016     bool ResponseCurve::operator==(const ResponseCurve& r) const throw(){
00017     shared_ptr<TF1> f1=getFunction();
00018         shared_ptr<TF1> f2=r.getFunction(); 
00019     if (r.getCurveName() != this->getCurveName()) return false;
00020     for (int i=0; i<3; ++i){
00021         if (f1->GetParameter(i)!=f2->GetParameter(i)) return false;
00022     }
00023     return true;
00024     }
00025  
00026    ResponseCurve::~ResponseCurve() throw() {
00027         //std::cout << "In ~ResponseCurve() " << __FILE__ << " " << __LINE__ << std::endl;
00028     this->ptr_inverse = shared_ptr<TF1>();
00029     //std::cout << "I have just reset the ptr_inverse.   Now I am going to throw!" << std::endl;
00030     this->ptr_function = shared_ptr<TF1>();
00031     //std::cout << "I have just reset the ptr_function" << std::endl;
00032    }
00033 
00034     ResponseCurve::ResponseCurve(auto_ptr<TF1> f) throw(LogicError) : 
00035     ptr_function(f), ptr_inverse() {
00036     if (ptr_function.get()==0) throw InvariantViolatedError("ResponseCurve constructor couldn't make TF1", __FILE__, __LINE__);
00037     }
00038 
00039     ResponseCurveMap& ResponseCurveMap::getMap() throw() {
00040     static ResponseCurveMap* bertha = new ResponseCurveMap();
00041     return *bertha;
00042     }
00043     
00044     bool ResponseCurveMap::addToMap(const string& curveName, const int index, ResponseCurve& mode) throw() {
00045     //check that this className isn't already in the map
00046     if (nameMap.find(curveName) != nameMap.end()) return false;
00047     //if the index is already taken, just return
00048     if (indexMap.find(index) != indexMap.end()) return false;
00049     
00050     nameMap[curveName] = index;
00051     indexMap[index] = &mode;
00052     return true;
00053     }
00054     
00055     int ResponseCurveMap::getIndex(const string& curvename) const throw(LogicError){
00056     if (nameMap.find(curvename)==nameMap.end()) {
00057         ostringstream os; os <<"ResponseCurveMap::get couldn't find curve `"<< curvename<<"'";
00058         cerr << os.str() << endl;
00059         cerr << "There are " << nameMap.size() << " known response curve names: ";
00060         for (map<string, int>::const_iterator it = nameMap.begin();
00061          it != nameMap.end() ; 
00062          ++it)
00063         {
00064         cerr << (*it).first << endl;
00065         }
00066         throw InvalidArgumentError(os.str(), __FILE__, __LINE__);
00067     }
00068     return (*nameMap.find(curvename)).second;
00069     }
00070     
00071     auto_ptr<ResponseCurve> ResponseCurveMap::get(const string& curvename) const throw(LogicError) {
00072     return get(getIndex(curvename));
00073     }
00074     
00075     auto_ptr<ResponseCurve> ResponseCurveMap::get(const int index) const throw(LogicError) {
00076     if (indexMap.find(index)==indexMap.end()) {
00077         ostringstream os; os <<"ResponseCurveMap::get couldn't find index `"<< index<<"'";
00078         cerr << os.str() << endl;
00079         cerr << "There are " << indexMap.size() << " known response curve indices: ";
00080         for (map<int, ResponseCurve*>::const_iterator it =indexMap.begin();
00081          it != indexMap.end() ; 
00082          ++it)
00083         {
00084         cerr << (*it).first << endl;
00085         }
00086         throw InvalidArgumentError(os.str(), __FILE__, __LINE__);
00087     }
00088     return (*indexMap.find(index)).second->create();
00089     }
00090 
00091     auto_ptr<ResponseCurve> ResponseCurveMap::get(const ChipConfiguration& chip) const throw(LogicError) {
00092     auto_ptr<ResponseCurve> rc = ResponseCurveMap::getMap().get(chip.getRcFunctionIndex()) ;
00093     for (unsigned ipar=0; ipar<3; ++ipar){
00094         rc->getFunction()->SetParameter(ipar,chip.getRcParam(ipar));
00095     }
00096     return rc;
00097     }
00098 
00099   std::string notTheSameName(const char * part) {
00100     std::ostringstream s;
00101     s << part;
00102     static unsigned int ReneBrunMustDie = 0;
00103     s << (ReneBrunMustDie++);
00104     return s.str();
00105   };
00106 
00107 //Linear
00108     LinearResponseCurve::LinearResponseCurve() throw(LogicError) : 
00109     ResponseCurve(auto_ptr<TF1>(new TF1(notTheSameName("LinearResponseCurve").c_str(), linFn, 0, 1, 3))) {
00110     m_deb = rand();
00111     //std::cout << "In LinearResponseCurve() for m_deb="<<m_deb<<std::endl;
00112     }
00113 
00114     LinearResponseCurve::~LinearResponseCurve() throw() {
00115     //std::cout << "In ~LinearResponseCurve() for m_deb="<<m_deb<<std::endl;
00116     };
00117     
00118     shared_ptr<TF1> LinearResponseCurve::getInverseFunction() const throw(LogicError) {
00119     if (ptr_inverse.get()==0) {
00120         shared_ptr<TF1> inv(new TF1("InverseLinearResponseCurve",invLinFn, 0, 1, 3));
00121         ptr_inverse=inv;
00122         if (ptr_inverse.get()==0) throw InvariantViolatedError("LinearResponseCurve::getInverseFunction() failed", __FILE__, __LINE__);
00123     }
00124     shared_ptr<TF1> f=getFunction();
00125     ptr_inverse->SetParameters(f->GetParameter(0), f->GetParameter(1), f->GetParameter(2));
00126     return ptr_inverse;
00127     }
00128     
00129     bool LinearResponseCurve::inMap = ResponseCurveMap::getMap().addToMap("LinearResponseCurve",4, *new LinearResponseCurve());
00130     
00131     auto_ptr<ResponseCurve> LinearResponseCurve::create() const throw() {
00132     return auto_ptr<ResponseCurve> ( new LinearResponseCurve() );
00133     }
00134     
00135     double LinearResponseCurve::getGain(const double charge) const throw() {
00136     return getFunction()->GetParameter(1);
00137     }
00138 
00139     double LinearResponseCurve::linFn(double *x, double *par) throw() {
00140     return par[0] + par[1]*x[0];
00141     }
00142     double LinearResponseCurve::invLinFn(double *x, double *par) throw() {
00143     return (x[0]-par[0])/par[1];
00144     }
00145 
00146 //Exponential
00147     ExponentialResponseCurve::ExponentialResponseCurve() throw(LogicError): 
00148     ResponseCurve(auto_ptr<TF1>( new TF1(notTheSameName("ExponentialResponseCurve").c_str(), expFn, 0, 1, 3)))
00149     {
00150     getFunction()->SetParameters(1800,8,-800);
00151     }
00152     
00153 
00154     shared_ptr<TF1> ExponentialResponseCurve::getInverseFunction() const throw(LogicError){
00155     if (ptr_inverse.get()==0) {
00156         shared_ptr<TF1> inv( new TF1("InverseExponentialResponseCurve", invExpFn, 0, 1, 3));
00157         ptr_inverse=inv;
00158         if (ptr_inverse.get()==0) throw InvariantViolatedError("ExponentialResponseCurve::getInverseFunction() failed", __FILE__, __LINE__);
00159     }
00160     shared_ptr<TF1> f=getFunction();
00161     ptr_inverse->SetParameters(f->GetParameter(0), f->GetParameter(1), f->GetParameter(2));
00162     return ptr_inverse;
00163     }
00164 
00165     bool ExponentialResponseCurve::inMap = ResponseCurveMap::getMap().addToMap("ExponentialResponseCurve", 3, *new ExponentialResponseCurve());
00166     
00167     auto_ptr<ResponseCurve> ExponentialResponseCurve::create() const throw() {
00168     return auto_ptr<ResponseCurve> (new ExponentialResponseCurve() );
00169     }
00170     
00171     double ExponentialResponseCurve::getGain(const double charge) const throw() {
00172     if (getFunction()->GetParameter(1)==0)
00173         return 0.;
00174     double temp = exp(-charge/getFunction()->GetParameter(1));
00175     return getFunction()->GetParameter(0) * pow(1+temp,-2) * temp / getFunction()->GetParameter(1);
00176     }
00177     
00178     double ExponentialResponseCurve::expFn(double *x, double *par) throw() {
00179     return par[2] + par[0]/(1. + exp(-x[0]/par[1]));
00180     }
00181     double ExponentialResponseCurve::invExpFn(double *x, double *par) throw() {
00182     return -par[1] * log(par[0]/(x[0]-par[2])-1);
00183     }
00184     
00185 //Grillo
00186     GrilloResponseCurve::GrilloResponseCurve() throw (LogicError) :
00187     ResponseCurve(auto_ptr<TF1>(new TF1(notTheSameName("GrilloResponseCurve").c_str(), grilloFn, 0, 1, 3))){
00188     getFunction()->SetParameters(70, 40, 0.067);
00189     }
00190     
00191     shared_ptr<TF1> GrilloResponseCurve::getInverseFunction() const throw(LogicError){
00192     if (ptr_inverse.get()==0) {
00193         shared_ptr<TF1> inv(new TF1("InverseGrilloResponseCurve",invGrilloFn, 0, 1, 3));
00194         ptr_inverse=inv;    
00195         if (ptr_inverse.get()==0) throw InvariantViolatedError("GrilloResponseCurve::getInverseFunction() failed", __FILE__, __LINE__);
00196     }
00197     shared_ptr<TF1> f=getFunction();
00198     ptr_inverse->SetParameters(f->GetParameter(0), f->GetParameter(1), f->GetParameter(2));
00199     return ptr_inverse;
00200     }
00201 
00202     bool GrilloResponseCurve::inMap = ResponseCurveMap::getMap().addToMap("GrilloResponseCurve", 2, *new GrilloResponseCurve());
00203 
00204     auto_ptr<ResponseCurve> GrilloResponseCurve::create() const throw() {
00205     return auto_ptr<ResponseCurve> (new GrilloResponseCurve()) ;
00206     }
00207 
00208     double GrilloResponseCurve::getGain(const double charge) const throw() {
00209     return getFunction()->GetParameter(1) * pow(1 + pow(getFunction()->GetParameter(2) * charge, 2), -3./2.);
00210     }
00211     double GrilloResponseCurve::grilloFn(double *x, double *par) throw() {
00212     double numerator=x[0] * par[1]*par[2];
00213     if (numerator==0) return 0.;
00214     double sq=x[0]*par[1]; sq=sq*sq;
00215     return par[0] + numerator/sqrt(sq+par[2]*par[2]);
00216     }
00217     double GrilloResponseCurve::invGrilloFn(double *x, double *par) throw() {
00218     double a1=x[0]-par[0]; a1=a1*a1;
00219     double a2=par[2]*par[2];
00220     return 1./par[1] * sqrt( (a1*a2) / (a1+a2) );
00221     }
00222 
00223 //Quadratic
00224     QuadraticResponseCurve::QuadraticResponseCurve() throw(LogicError) : 
00225     ResponseCurve( auto_ptr<TF1>(new TF1(notTheSameName("QuadraticResponseCurve").c_str(), quadFn, 0, 1, 3))) {
00226     getFunction()->SetParameters(70,50,0);
00227     }
00228     
00229     shared_ptr<TF1> QuadraticResponseCurve::getInverseFunction() const throw(LogicError){
00230     if (ptr_inverse.get()==0) {
00231         shared_ptr<TF1> inv( new TF1("InverseQuadraticResponseCurve",invQuadFn, 0, 1, 3));
00232         ptr_inverse=inv;
00233         if (ptr_inverse.get()==0) throw InvariantViolatedError("QuadraticResponseCurve::getInverseFunction() failed", __FILE__, __LINE__);
00234     }
00235     shared_ptr<TF1> f=getFunction();
00236     ptr_inverse->SetParameters(f->GetParameter(0), f->GetParameter(1), f->GetParameter(2));
00237     return ptr_inverse;
00238     }
00239 
00240     bool QuadraticResponseCurve::inMap = ResponseCurveMap::getMap().addToMap("QuadraticResponseCurve", 1, *new QuadraticResponseCurve());
00241     
00242     auto_ptr<ResponseCurve> QuadraticResponseCurve::create() const throw() {
00243     return auto_ptr<ResponseCurve> (new QuadraticResponseCurve()) ;
00244     }
00245 
00246     double QuadraticResponseCurve::getGain(const double charge) const throw() {
00247     return getFunction()->GetParameter(1) + 2.0*charge*getFunction()->GetParameter(2);
00248     }
00249 
00250     double QuadraticResponseCurve::quadFn(double *x, double *par) throw() {
00251     return par[0] + x[0] * (par[1] + par[2]*x[0]);
00252     }
00253     double QuadraticResponseCurve::invQuadFn(double *x, double *par) throw() {
00254     return ( -par[1] - sqrt( par[1]*par[1] - 4 * par[2] * (par[0]-x[0]))) / (2 * par[2]);
00255     }
00256 }

Generated on Mon Feb 6 14:01:25 2006 for SCT DAQ/DCS Software - C++ by  doxygen 1.4.6