00001 #include "NPtGainAlgorithm.h"
00002 #include "AnalysisAlgorithmMap.h"
00003 #include "AnalysisService.h"
00004 #include "Sct/SctParameters.h"
00005 #include "SctData/NPtGainTestResult.h"
00006 #include "SctData/FitScanResult.h"
00007 #include "SctData/FitObject.h"
00008 #include "SctData/ResponseCurve.h"
00009 #include "SctData/StandardDefects.h"
00010 #include "SctData/ModuleConfiguration.h"
00011 #include "SctData/ChipConfiguration.h"
00012 #include "Sct/SctNames.h"
00013 #include "Sct/ConfigurationException.h"
00014 #include "CalibrationController/IS/TestData.h"
00015 #include "sctConf/configuration.h"
00016 #include <boost/shared_ptr.hpp>
00017
00018 using namespace Sct;
00019 using namespace SctData;
00020 using namespace boost;
00021
00022 using std::auto_ptr;
00023 using std::ostringstream;
00024
00025 namespace SctAnalysis {
00026
00027 unsigned NPtGainAlgorithm::NPtGainAlgorithm::s_configurationWarnings=0;
00028
00029 shared_ptr<AnalysisAlgorithm> NPtGainAlgorithm::clone(shared_ptr<const TestData> testData, const string& moduleName) const throw() {
00030 return shared_ptr<AnalysisAlgorithm>(new NPtGainAlgorithm(testData, moduleName, *this));
00031 }
00032
00033 NPtGainAlgorithm::NPtGainAlgorithm(shared_ptr<const TestData> testData, const string& moduleName, const AnalysisAlgorithm& alg) throw() : AnalysisAlgorithm(testData, moduleName, alg) , m_mur_type(SctConfiguration::UNKNOWN), m_endcap_type(SctConfiguration::ENDCAP_UNKNOWN){
00034 bool error=false;
00035 string error_message="unknown problem";
00036 const unsigned max_warnings=5;
00037
00038 try{
00039 boost::shared_ptr<SctConfiguration::Configuration> config=AnalysisService::instance().getConfiguration();
00040 if (!config.get()) throw ConfigurationException("Configuration not available", __FILE__, __LINE__);
00041 unsigned mur=0, mod=0, quadrant=0, number=0;
00042 int disk=0;
00043 config->translateFromSN(moduleName, mur, mod);
00044 m_mur_type=config->getMURType(mur);
00045 if (m_mur_type==SctConfiguration::ENDCAP){
00046 config->translateToEndcap(mur, mod, disk, quadrant, number);
00047 m_endcap_type= SctConfiguration::getEndcapType(disk, number);
00048 }
00049 }catch(std::exception& e){
00050 error=true;
00051 error_message=e.what();
00052 }catch(CORBA::Exception& e){
00053 error=true;
00054 error_message="Corba exception : ";
00055 error_message+=e._name();
00056 error_message+=" ... probably could not find configuration service";
00057 }catch(...){
00058 error=true;
00059 }
00060 if (error){
00061
00062 if (s_configurationWarnings<max_warnings){
00063 ostringstream msg;
00064 if (s_configurationWarnings==max_warnings-1){
00065 msg << "NO MORE WARNINGS OF THIS TYPE WILL BE PRINTED:\n";
00066 }
00067 msg << "NPtGainAlgorithm (AnalysisService) could not find geometry-dependant expected noise levels for test "
00068 << testData->testName
00069 << " run:" << testData->runNumber << " scan:" << testData->startScanNumber
00070 << " module:" << moduleName
00071 << " Problem in configuration look-up: "
00072 << error_message;
00073 Sct::SctNames::Mrs() << MRS_TEXT(msg.str()) << "CONFIG_LOOKUP_FAIL" << MRS_WARNING << ENDM;
00074 s_configurationWarnings++;
00075 }
00076 }
00077 }
00078
00079 shared_ptr<ResponseCurve> NPtGainAlgorithm::getResponseCurve(unsigned int nPts) throw(LogicError){
00080 if (nPts <= 3) {
00081 return shared_ptr<ResponseCurve> (new LinearResponseCurve());
00082 } else {
00083 return shared_ptr<ResponseCurve> (new ExponentialResponseCurve());
00084 }
00085 }
00086
00087 void NPtGainAlgorithm::setResponseCurve(auto_ptr<ResponseCurve> rc) throw() {
00088 static shared_ptr<ResponseCurve> s_responseCurve=shared_ptr<ResponseCurve>(rc.release());
00089 }
00090
00091 bool NPtGainAlgorithm::inMap = AnalysisAlgorithmMap::instance().setAlgorithm("NPtGainTest", auto_ptr<AnalysisAlgorithm>(new NPtGainAlgorithm()));
00092
00093 shared_ptr<SctData::TestResult> NPtGainAlgorithm::createTestResult() const {
00094 shared_ptr<NPtGainTestResult> result (new NPtGainTestResult());
00095 result->setChipDataSize(nChipModule);
00096 result->setChannelDataSize(nChannelModule);
00097
00098 return result;
00099 }
00100
00101 void NPtGainAlgorithm::loadData() {
00102 loadAllFits();
00103 }
00104
00105 bool NPtGainAlgorithm::canAnalyze() const {
00106 return hasAllFits();
00107 }
00108
00109 void NPtGainAlgorithm::analyze() {
00110 shared_ptr<NPtGainTestResult> result = dynamic_pointer_cast<NPtGainTestResult> ( getTestResult() );
00111 result->setScanVariable(getFit(0)->getHeader().getVariable());
00112 try{
00113 result->setSpecialScanPointValue(2.0);
00114 } catch (Sct::Throwable& e){
00115 e.sendToMrs(MRS_ERROR);
00116 }
00117
00118
00119 nOnePointTrimmed = 0;
00120 nTwoPointTrimmed = 0;
00121
00122
00123 for (unsigned int i=0; i<nChipModule; ++i) {
00124 setupGraph(i, ModuleElement::Chip(i), &FitScanResult::getChipFit, *result, result->getChipData(i), true);
00125 doFit(i, &FitScanResult::getChipFit, *result, result->getChipData(i));
00126 }
00127
00128
00129 for (unsigned int i=0; i<nChannelModule; ++i) {
00130 ModuleElement element = ModuleElement::Channel(i);
00131 setupGraph(i, element, &FitScanResult::getChannelFit, *result, result->getChannelData(i), true);
00132
00133
00134 if (getFit(0)->getConfiguration().channelIsMasked(i)) continue;
00135
00136 doFit(i, &FitScanResult::getChannelFit, *result, result->getChannelData(i));
00137 doDefect(element, result->getDefects(),
00138 result->getChannelData(i), result->getChipData(i/nChannelChip));
00139 }
00140
00141 doSlopes(*result);
00142
00143
00144
00145
00146 const DefectList::DefectCollection& defects = result->getDefects().getAllDefects();
00147 bool passed = true;
00148 unsigned int totalChannels = 0;
00149 for (DefectList::DefectCollection::const_iterator i=defects.begin(); i!=defects.end(); ++i) {
00150
00151 if (i->getPrototype().getSeverity() > DODGY) {
00152 totalChannels += i->getModuleElement().getNChannels();
00153 if (i->getModuleElement().getNChannels()>7) {
00154 passed = false;
00155 break;
00156 }
00157 }
00158 }
00159 if (totalChannels > 15) passed = false;
00160
00161
00162 if (nOnePointTrimmed != 0) {
00163 ostringstream oss;
00164 oss << nOnePointTrimmed << " channels had 1 point trimmed from fit";
00165 result->addComment(oss.str());
00166 }
00167 if (nTwoPointTrimmed != 0) {
00168 ostringstream oss;
00169 oss << nTwoPointTrimmed << " channels had 2 (or more) points trimmed from fit";
00170 result->addComment(oss.str());
00171 }
00172
00173 result->setPassed(passed);
00174 }
00175
00176
00177 void NPtGainAlgorithm::setupGraph(unsigned int id, const ModuleElement& element, getFitFunction fitFunc, NPtGainTestResult& test, NPtGainTestResultData& testData, bool trimPoints) throw(LogicError) {
00178
00179 unsigned int lastPoint = test.getNScans()-1;
00180
00181 if (trimPoints && test.getNScans() > 5) {
00182 double sigmaCut = 0;
00183 for (unsigned int i=0; i<test.getNScans(); ++i) {
00184 sigmaCut+= (getFit(i).get()->*fitFunc)(id).getParameter("Sigma");
00185 }
00186 sigmaCut *= 1.5/test.getNScans();
00187
00188 for (unsigned int i=test.getNScans() - 1; i>4; --i) {
00189
00190 const DefectList& defects = getFit(i)->getDefects();
00191 if (test.getTestPointAt(i) > 5 && ((getFit(i).get()->*fitFunc)(id).getParameter("Sigma") > sigmaCut ||
00192 defects.defectSeverityAffectingElement(element) >= SERIOUS)) {
00193 lastPoint = i-1;
00194 }
00195 }
00196
00197
00198 if (lastPoint != test.getNScans() - 1) {
00199 if (element.isChip()) {
00200 ostringstream oss;
00201 oss << "Points trimed from response curve for chip: " << id << ". Last point " << lastPoint << " with charge " << test.getTestPointAt(lastPoint);
00202 test.addComment(oss.str());
00203 } else {
00204 if (lastPoint+1-test.getNScans() == 1) ++nOnePointTrimmed;
00205 else ++nTwoPointTrimmed;
00206 }
00207 }
00208 }
00209
00210 mergeDefects(test, element, lastPoint);
00211
00212 shared_ptr<TGraph> g (new TGraph(lastPoint+1));
00213 if (!g)
00214 throw InvariantViolatedError("NPtGainTestResult::setupGraph couldn't make TGraph", __FILE__, __LINE__);
00215
00216
00217 for (unsigned int j = 0; j <= lastPoint; ++j) {
00218
00219
00220 unsigned ichip=element.getFirst()/nChannelChip;
00221 const ChipConfiguration& chipconfig = getFit(j)->getConfiguration().getChipConfiguration(ichip);
00222
00223 const unsigned char cal = chipconfig.getCalCharge();
00224
00225 const float qcal= static_cast<float>(cal)*0.0625*chipconfig.getCalFactor();
00226 g->SetPoint(j, qcal, (getFit(j).get()->*fitFunc)(id).getParameter("Mean"));
00227
00228
00229
00230
00231
00232
00233 }
00234 testData.graph = g;
00235
00236 shared_ptr<ResponseCurve> r=getResponseCurve(test.getNScans());
00237 testData.rc = r;
00238 }
00239
00240 void NPtGainAlgorithm::mergeDefects(NPtGainTestResult& test, const ModuleElement& element, unsigned int lastPoint) {
00241 for (unsigned int i=0; i<lastPoint; ++i) {
00242 auto_ptr<DefectList> defects = getFit(i)->getDefects().getDefectsEncompassingElement(element);
00243 const DefectList::DefectCollection& allDefects = defects->getAllDefects();
00244 for (DefectList::DefectCollection::const_iterator it=allDefects.begin(); it!=allDefects.end(); ++it) {
00245 test.getDefects().addDefect(Defect(it->getPrototype(), element));
00246 }
00247 }
00248 }
00249
00250 void NPtGainAlgorithm::doFit(unsigned int id, getFitFunction fitFunc, NPtGainTestResult& test,
00251 NPtGainTestResultData& testData) throw(LogicError) {
00252
00253
00254
00255 testData.rc->getFunction()->SetRange(0,10);
00256 AnalysisService::instance().getFitStrategy().fitTGraph(*testData.graph, *testData.rc->getFunction() );
00257
00258 testData.gain = testData.rc->getGain(test.getSpecialScanPointValue());
00259
00260 shared_ptr<const FitScanResult> specialFit = getFit(test.getSpecialScanIndex());
00261
00262 if (testData.gain != 0) testData.noise = 6250 * (specialFit.get()->*fitFunc)(id).getParameter("Sigma") / testData.gain;
00263 else testData.noise = 0;
00264 testData.offset= testData.rc->getFunction()->Eval(0.);
00265 }
00266
00267 void NPtGainAlgorithm::doDefect(const ModuleElement& element, DefectList& defects,
00268 const NPtGainTestResultData& data,
00269 const NPtGainTestResultData& comparisonData) throw(LogicError) {
00270
00271 if (data.gain < StandardDefects::VLO_GAIN.getParameter() * comparisonData.gain){
00272 defects.addDefect(Defect(StandardDefects::VLO_GAIN, element));
00273 }
00274 if (data.gain < StandardDefects::LO_GAIN.getParameter() * comparisonData.gain){
00275 defects.addDefect(Defect(StandardDefects::LO_GAIN, element));
00276 } else if (data.gain > StandardDefects::HI_GAIN.getParameter() * comparisonData.gain){
00277 defects.addDefect(Defect(StandardDefects::HI_GAIN, element));
00278 }
00279
00280 if (data.offset < StandardDefects::LO_OFFSET.getParameter()) {
00281 defects.addDefect(Defect(StandardDefects::LO_OFFSET, element));
00282 } else if (data.offset > StandardDefects::HI_OFFSET.getParameter()) {
00283 defects.addDefect(Defect(StandardDefects::HI_OFFSET, element));
00284 }
00285
00286 bool short_module = ( m_mur_type==SctConfiguration::ENDCAP &&
00287 ( m_endcap_type==SctConfiguration::ENDCAP_SHORT_MIDDLE
00288 || m_endcap_type==SctConfiguration::ENDCAP_INNER) );
00289
00290 if (data.noise < StandardDefects::UNBONDED.getParameter()) {
00291 defects.addDefect(Defect(StandardDefects::UNBONDED, element));
00292 } else if (data.noise < StandardDefects::PARTBONDED.getParameter() && !short_module) {
00293 defects.addDefect(Defect(StandardDefects::PARTBONDED, element));
00294 } else if (data.noise > StandardDefects::NOISY.getParameter() * comparisonData.noise) {
00295 defects.addDefect(Defect(StandardDefects::NOISY, element));
00296 }
00297
00298 if (data.noise > StandardDefects::V_NOISY.getParameter() * comparisonData.noise) {
00299 defects.addDefect(Defect(StandardDefects::V_NOISY, element));
00300 }
00301 }
00302
00303 void NPtGainAlgorithm::doSlopes(NPtGainTestResult& r){
00304 shared_ptr<TGraph> noise = r.getNoiseGraph();
00305 shared_ptr<TGraph> gain = r.getGainGraph();
00306 shared_ptr<TGraph> offset = r.getOffsetGraph();
00307
00308
00309 doSlopes(noise, r.noiseSlope);
00310
00311
00312 doSlopes(gain, r.gainSlope);
00313
00314
00315 doSlopes(offset, r.offsetSlope);
00316 for (unsigned ichip=0; ichip<nChipModule; ++ichip){
00317 if (abs(r.noiseSlope[ichip]) > 0.7 || r.noiseSlope[ichip] < -1.2){
00318 r.getDefects().addDefect(Defect(StandardDefects::NOISE_SLOPE, ModuleElement::Chip(ichip)));
00319 }
00320 if (abs(r.gainSlope[ichip])>StandardDefects::GAIN_SLOPE.getParameter()){
00321 r.getDefects().addDefect(Defect(StandardDefects::GAIN_SLOPE, ModuleElement::Chip(ichip)));
00322 }
00323 if (abs(r.offsetSlope[ichip])>StandardDefects::OFFSET_SLOPE.getParameter()){
00324 r.getDefects().addDefect(Defect(StandardDefects::OFFSET_SLOPE, ModuleElement::Chip(ichip)));
00325 }
00326
00327 }
00328
00329 }
00330
00331 void NPtGainAlgorithm::doSlopes(shared_ptr<TGraph> graph, Sct::RangedVector<float>& result){
00332 result.resize(nChipModule);
00333
00334 for (unsigned ichip=0; ichip<nChipModule; ++ichip){
00335 double xsum=0.;
00336 double x2sum=0.;
00337 double ysum=0.;
00338 double xysum=0.;
00339 unsigned n=0;
00340 for (unsigned ichan = 0; ichan<nChannelChip; ++ichan) {
00341 double x=0;
00342 double y=0;
00343 int bin=ichip*nChannelChip + ichan;
00344 graph->GetPoint(bin, x, y);
00345 if (y>0.0001){
00346 xsum += x;
00347 ysum += y;
00348 x2sum += x*x;
00349 xysum += x*y;
00350 ++n;
00351 }
00352 }
00353 const double det = ( n*x2sum ) - ( xsum*xsum );
00354 if (det>0) {
00355 result[ichip]= (n*xysum - xsum*ysum) / det;
00356 }else{
00357 result[ichip]=0.;
00358 }
00359 }
00360 }
00361
00362 }