NoiseOccupancyAlgorithm.cpp

00001 #include "NoiseOccupancyAlgorithm.h"
00002 #include "AnalysisAlgorithmMap.h"
00003 #include "AnalysisService.h"
00004 #include "OpeTool.h"
00005 #include "SctData/Stat.h"
00006 #include "SctData/NoiseOccupancyTestResult.h"
00007 #include "SctData/OccupancyProjector.h"
00008 #include "SctData/FitScanResult.h"
00009 #include "SctData/FitObject.h"
00010 #include "SctData/ResponseCurve.h"
00011 #include "SctData/StandardDefects.h"
00012 #include "SctData/ConfigurationVariable.h"
00013 #include "Sct/UnsupportedOperationError.h"
00014 #include <Sct/AbcdScans.h>
00015 #include <TH1.h>
00016 #include <TGraphAsymmErrors.h>
00017 #include <string>
00018 
00019 using namespace std;
00020 using namespace boost;
00021 using namespace SctData;
00022 using namespace Sct;
00023 
00024 namespace SctAnalysis {
00025     
00026     NoiseOccupancyAlgorithm::~NoiseOccupancyAlgorithm() throw() {}
00027 
00028     shared_ptr<AnalysisAlgorithm> NoiseOccupancyAlgorithm::clone(shared_ptr<const TestData> testData, const string& moduleName) const throw() {
00029     return shared_ptr<AnalysisAlgorithm>(new NoiseOccupancyAlgorithm(testData, moduleName, *this));
00030     }
00031 
00032     bool NoiseOccupancyAlgorithm::inMap = AnalysisAlgorithmMap::instance().setAlgorithm("NoiseOccupancyTest", auto_ptr<AnalysisAlgorithm>(new NoiseOccupancyAlgorithm()));
00033  
00034     //----------------------------------------------------------------------
00035     
00036     void NoiseOccupancyAlgorithm::loadData() {
00037     loadAllRaws();
00038     loadAllFits();
00039     }
00040     
00041     bool NoiseOccupancyAlgorithm::canAnalyze() const {
00042     return hasAllFits() && hasAllRaws();
00043     }
00044     
00045     shared_ptr<SctData::TestResult> NoiseOccupancyAlgorithm::createTestResult() const {
00046     return shared_ptr<TestResult>(new NoiseOccupancyTestResult());
00047     }
00048 
00049     void NoiseOccupancyAlgorithm::analyze() {
00050         debug=false;
00051         shared_ptr<NoiseOccupancyTestResult> result = dynamic_pointer_cast<NoiseOccupancyTestResult>(getTestResult());
00052     const SctData::ConfigurationVariable& scanVariable = getRaw(0)->getHeader().getVariable();
00053     result->setScanVariable(scanVariable);
00054     const ModuleConfiguration config=getRaw(0)->getConfiguration();
00055     
00056     m_scanVariable = SctData::ConfigurationVariableIOHelper::getTypeRep(scanVariable);
00057     
00058     //cout << " NoiseOccupancyAlgorithm::analyze()" << endl;
00059     //Loop over chips
00060     for (unsigned int ichip=0; ichip<nChipModule; ++ichip) {
00061         // get an raw result occupany projector 
00062         OccupancyProjector opr(*getRaw(0) );
00063         
00064         DefectList& fitdefects=getFit(0)->getDefects();
00065         
00066         // if the fit defects aren't so bad that they exclude the whole module, then veto from them:
00067         if (fitdefects.defectSeverityAffectingElement(ModuleElement::Module()) < SERIOUS ) opr.vetoSeriousDefects(fitdefects);
00068         
00069         // get the chip configuration
00070         const ChipConfiguration& chipconfig=config.getChipConfiguration(ichip);
00071         // get the new defects
00072         DefectList& defects = result->getDefects();
00073         result->getChipResult(ichip) = analyzeChip(ichip, opr, chipconfig, defects);
00074 
00075         const float fittedOffset = getFit(0)->getChipFit(ichip).getParameter(1);
00076         switch(m_scanVariable) {
00077         case ST_VTHR:
00078         result->getChipResult(ichip).offset = fittedOffset;
00079         break;
00080         case ST_TTHR:
00081         result->getChipResult(ichip).offset = fittedOffset + config.getChipConfiguration(ichip).getTrimTarget()*2.5;
00082         break;
00083         case ST_QTHR: {
00084         auto_ptr<ResponseCurve> rc = ResponseCurveMap::getMap().get(config.getChipConfiguration(ichip));
00085         result->getChipResult(ichip).offset = rc->getFunction()->Eval(fittedOffset);
00086             }
00087         break;
00088         default: {
00089             ostringstream oss;
00090         oss << "Internal Error: NoiseOccupancy Algorithm doesn't know how to deal with scan of type : " << m_scanVariable;
00091         throw Sct::UnsupportedOperationError(oss.str(), __FILE__, __LINE__);
00092             }
00093         }
00094     }
00095     OpeTool tool;
00096     shared_ptr<SctData::OpeResult> ope = tool.analyzeModule(*getRaw(0));
00097     result->setOpeResult(ope);
00098     result->setPassed(true);
00099 
00100     // Check the badness parameter above a threshold of -20 and report badness if maxbadness > 2
00101     if (ope.get()) {
00102       for (unsigned int ichip=0; ichip<nChipModule; ++ichip) {
00103         SctData::ChipOpeResult& chipOpe=ope->getChipResult(ichip);
00104         if (chipOpe.badmax > 2.0) {
00105           result->getDefects().addDefect(Defect(StandardDefects::BAD_OPE, ModuleElement::Chip(ichip)));
00106           result->setProblem(true);
00107         }
00108       }
00109     }
00110     }
00111     
00112 
00113     
00114     ChipNOResult NoiseOccupancyAlgorithm::analyzeChip(const unsigned ichip, const OccupancyProjector& opr, const ChipConfiguration& chipconfig, DefectList& defects) {
00115     
00116     auto_ptr<TH1> occ = opr.getOccupancy("temp", ModuleElement::Chip(ichip)) ;
00117     auto_ptr<ResponseCurve> rc = ResponseCurveMap::getMap().get(chipconfig);
00118     shared_ptr<TF1> invFn = rc->getInverseFunction();
00119     
00120     if (debug) cout << "Config RC: " << (int)chipconfig.getRcFunctionIndex() << " params: " << chipconfig.getRcParam(0) << "  " << chipconfig.getRcParam(1) << "  " << chipconfig.getRcParam(2) << endl;
00121     if (debug) cout << "RC: " << rc->getIndex() << " params: " << rc->getFunction()->GetParameter(0) << "  " << rc->getFunction()->GetParameter(1) << "  " << rc->getFunction()->GetParameter(2) << endl;
00122 
00123     int ttbin=-1; //< trim target bin
00124     int fcbin=-1; //< 1 fC bin
00125 
00126     const float mVstep=2.5;  // number of mv per threshold step
00127     const float trimTargetmV=chipconfig.getTrimTarget()*mVstep;
00128 
00129     if (m_scanVariable==ST_VTHR){
00130       ttbin = occ->GetXaxis()->FindBin(chipconfig.getTrimTarget()*mVstep);
00131       fcbin = occ->GetXaxis()->FindBin(rc->getFunction()->Eval(1.));
00132     }else if(m_scanVariable==ST_TTHR){
00133       ttbin = occ->GetXaxis()->FindBin(0.);
00134       fcbin = occ->GetXaxis()->FindBin(rc->getFunction()->Eval(1.)-trimTargetmV);
00135     }else if(m_scanVariable==ST_QTHR){
00136       ttbin = occ->GetXaxis()->FindBin(invFn->Eval(trimTargetmV));
00137       fcbin = occ->GetXaxis()->FindBin(1.);
00138     }else{
00139       ostringstream oss;
00140       oss << "Internal Error: NoiseOccupancy Algorithm doesn't know how to deal with scan of type : " << m_scanVariable;
00141       throw Sct::UnsupportedOperationError(oss.str(), __FILE__, __LINE__);
00142     }
00143 
00144     if (debug) cout << "TrimTarget: " << chipconfig.getTrimTarget()*2.5 << " mV, bin: " << ttbin << " Occ: " << occ->GetBinContent(ttbin) << endl;
00145     if (debug) cout << "1fC: " << rc->getFunction()->Eval(1.) << " mV, bin: " << fcbin << " Occ: " << occ->GetBinContent(fcbin) << endl;
00146     
00147     // Construct TGraph of log occupancy against thr^2
00148     // project raw data from scan 0 of the test
00149     // Construction of TGraphAsymmetricErrors in this way because root is so 
00150     // inefficient at re-allocating memory for graphs
00151     double x[occ->GetNbinsX()];
00152     double xUpperErr[occ->GetNbinsX()];
00153     double xLowerErr[occ->GetNbinsX()];
00154     double yUpperErr[occ->GetNbinsX()];
00155     double yLowerErr[occ->GetNbinsX()];
00156     double y[occ->GetNbinsX()];
00157     unsigned int nBins = 0;
00158     
00159     double factor = 1;//11.3;  //warning - Should be 1.  Use 11.3 to simulate SCTDAQ
00160     
00161     for(int bin=1; bin<=occ->GetNbinsX(); ++bin){
00162         //We only want the "bottom" half of the threshold scan (threshold > 0.5)
00163         if (occ->GetBinContent(bin) > 0 && occ->GetBinContent(bin) < 0.5 ) {
00164         y[nBins] = log(occ->GetBinContent(bin));            
00165         yUpperErr[nBins] = log(occ->GetBinContent(bin) + factor*occ->GetBinError(bin)) - y[nBins];
00166         if (occ->GetBinContent(bin) - factor*occ->GetBinError(bin) > 0) {
00167             yLowerErr[nBins] = y[nBins] - log(occ->GetBinContent(bin) - factor*occ->GetBinError(bin));
00168         } else {
00169             yLowerErr[nBins] = yUpperErr[nBins];//occ->GetBinContent(bin);
00170             //yLowerErr[nBins] = 50;
00171             //cout << yLowerErr[nBins] << endl;         
00172         } 
00173         
00174         //Convert into fC:
00175         switch(m_scanVariable) {
00176           // Fix by BD and PWP for integer stepping problem
00177         case ST_VTHR:
00178             x[nBins] = invFn->Eval((int)((occ->GetBinCenter(bin)+1.25)/2.5)*2.5);
00179             break;
00180         case ST_TTHR:
00181           x[nBins] = invFn->Eval((int)((occ->GetBinCenter(bin)+1.25)/2.5)*2.5+trimTargetmV);
00182             break;
00183         case ST_QTHR:
00184             x[nBins] = invFn->Eval((int)(((rc->getFunction()->Eval(occ->GetBinCenter(bin)))+1.25)/2.5)*2.5);
00185             //    cout << "start="<<(occ->GetBinCenter(bin))<<" end="<<x[nBins]<<endl;
00186             break;
00187         default:
00188             ostringstream oss;
00189             oss << "Internal Error: NoiseOccupancy Algorithm doesn't know how to deal with scan of type : " << m_scanVariable;
00190             throw Sct::UnsupportedOperationError(oss.str(), __FILE__, __LINE__);
00191         }
00192         
00193         x[nBins] *= x[nBins];
00194         xUpperErr[nBins] = xLowerErr[nBins] = 0;            
00195                 
00196         nBins++;
00197         }
00198     }
00199 
00200         auto_ptr<TF1> f = NoiseOccupancyTestResult::createFitFunction();
00201 
00202         //Check for a dead chip (which hasnt been caused by vetoing due to other serious defect!)
00203         if (nBins == 0 && defects.defectSeverityEncompassingElement(ModuleElement::Chip(ichip)) < SERIOUS ) {
00204             defects.addDefect(Defect(StandardDefects::DEAD, ModuleElement::Chip(ichip)));
00205             shared_ptr<TGraphAsymmErrors> g( new TGraphAsymmErrors());
00206             return ChipNOResult(g, shared_ptr<TF1>(f), 0, 0);
00207         }
00208 
00209     shared_ptr<TGraphAsymmErrors> g( new TGraphAsymmErrors(nBins, x, y, xLowerErr, xUpperErr, yLowerErr, yUpperErr));
00210 
00211     //We don't usually use FitStrategy because there is no asymm errors method. However since ROOT v 4.03/04 seems to core dump with this method, we use it AJB
00212     AnalysisService::instance().getFitStrategy().fitTGraphAsymmErrors(*g, *f);
00213 //  AnalysisService::instance().getFitStrategy().fitTGraphAsymmErrors(*g, *f);
00214     //g->Print();
00215     //f->Print();
00216     //g->Fit(f.get(), "NQR");
00217 
00218     // Calculate mean and RMS NO at 1fC for channels in this chip
00219     Stats<double> occAtOnefC(nChannelChip);
00220     for (unsigned ichan=0; ichan < nChannelChip ; ++ichan ){
00221         unsigned channelInModule = ichip*nChannelChip + ichan;
00222 
00223         // get chip projection:
00224         char name[10];
00225         sprintf(name,"temp%d",channelInModule);
00226         auto_ptr<TH1> occChannel = opr.getOccupancy(name, ModuleElement::Channel(channelInModule)) ;
00227         
00228         // find 1 fC point - gets threshold in mV
00229         int bin = 0;
00230         switch(m_scanVariable) {
00231         case ST_VTHR: {
00232         double vthr = rc->getFunction()->Eval(1.);
00233         bin = occChannel->GetXaxis()->FindBin(vthr);
00234             } break;
00235         case ST_TTHR: {
00236         double vthr = rc->getFunction()->Eval(1.);
00237         bin = occChannel->GetXaxis()->FindBin(vthr-trimTargetmV);       
00238             } break;
00239         case ST_QTHR:
00240         bin = occChannel->GetXaxis()->FindBin(1.0);
00241         break;
00242         default:
00243         ostringstream oss;
00244         oss << "Internal Error: NoiseOccupancy Algorithm doesn't know how to deal with scan of type : " << m_scanVariable;
00245         throw Sct::UnsupportedOperationError(oss.str(), __FILE__, __LINE__);
00246         }       
00247         
00248         //cout << "Thr bin="<<bin<<endl;
00249         occAtOnefC.modifyAt(ichan).value = occChannel->GetBinContent(bin);
00250         
00251         //cout << ichip << "\t " << ichan << "\t" << occAtOnefC.getAt(ichan).value << endl;
00252         
00253         // check for defects:
00254         if (occAtOnefC.getAt(ichan).value > StandardDefects::NO_HI.getParameter() ){
00255         defects.addDefect(Defect(StandardDefects::NO_HI, ModuleElement::Channel(channelInModule)));
00256                 occAtOnefC.modifyAt(ichan).valid=false;
00257         }
00258     }
00259     double mean = occAtOnefC.mean();
00260     //cout << "NoiseOcc mean = " << mean << endl;
00261     double rms  = sqrt( occAtOnefC.var() );
00262     
00263     return ChipNOResult(g,shared_ptr<TF1>(f),mean,rms);
00264     }
00265 } // end of namespace SctAnalysis

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