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
00028 this->ptr_inverse = shared_ptr<TF1>();
00029
00030 this->ptr_function = shared_ptr<TF1>();
00031
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
00046 if (nameMap.find(curveName) != nameMap.end()) return false;
00047
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
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
00112 }
00113
00114 LinearResponseCurve::~LinearResponseCurve() throw() {
00115
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
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
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
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 }