Main Page | Modules | Namespace List | Class Hierarchy | Alphabetical List | Data Structures | File List | Namespace Members | Data Fields | Globals | Related Pages

NPtGainAlgorithm.cpp

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

Generated on Thu Dec 15 21:14:30 2005 for SCT DAQ/DCS Software - C++ by doxygen 1.3.5