Main Page | Modules | Namespace List | Class Hierarchy | Alphabetical List | Data Structures | File List | Namespace Members | Data Fields | 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 <boost/shared_ptr.hpp>
00013 
00014 using namespace Sct;
00015 using namespace SctData;
00016 using namespace boost;
00017 
00018 using std::auto_ptr;
00019 
00020 namespace SctAnalysis {
00021     
00022 
00023 shared_ptr<AnalysisAlgorithm> NPtGainAlgorithm::clone(const TestData& testData, const string& moduleName) const throw() {
00024     return shared_ptr<AnalysisAlgorithm>(new NPtGainAlgorithm(testData, moduleName, *this));
00025 }
00026     
00027 shared_ptr<ResponseCurve> NPtGainAlgorithm::getResponseCurve(unsigned int nPts) throw(LogicError){
00028     if (nPts <= 3) {
00029     return shared_ptr<ResponseCurve> (new LinearResponseCurve());
00030     } else {
00031     return shared_ptr<ResponseCurve> (new ExponentialResponseCurve());
00032     }   
00033 }
00034     
00035 void NPtGainAlgorithm::setResponseCurve(auto_ptr<ResponseCurve> rc) throw() {
00036     static shared_ptr<ResponseCurve> s_responseCurve=shared_ptr<ResponseCurve>(rc.release());
00037 }
00038 
00039 bool NPtGainAlgorithm::inMap = AnalysisAlgorithmMap::instance().setAlgorithm("NPtGainTest", auto_ptr<AnalysisAlgorithm>(new NPtGainAlgorithm()));
00040 
00041 shared_ptr<SctData::TestResult> NPtGainAlgorithm::createTestResult() const {
00042     shared_ptr<NPtGainTestResult> result (new NPtGainTestResult());
00043     result->setChipDataSize(nChipModule);
00044     result->setChannelDataSize(nChannelModule);
00045     
00046     return result;
00047 }
00048 
00049 void NPtGainAlgorithm::loadData() {
00050     loadAllFits();
00051 }
00052 
00053 bool NPtGainAlgorithm::canAnalyze() const {
00054     return hasAllFits();
00055 }
00056 
00057 void NPtGainAlgorithm::analyze() {
00058     shared_ptr<NPtGainTestResult> result = dynamic_pointer_cast<NPtGainTestResult> ( getTestResult() );
00059     result->setScanVariable(getFit(0)->getHeader().getVariable());  
00060     try{
00061     result->setSpecialScanPointValue(2.0);
00062     } catch (Sct::Throwable& e){
00063     e.sendToMrs(MRS_ERROR);
00064     }
00065     
00066     //Reset counters
00067     nOnePointTrimmed = 0;
00068     nTwoPointTrimmed = 0;
00069     
00070     //Do chips
00071     for (unsigned int i=0; i<nChipModule; ++i) {
00072         setupGraph(i, ModuleElement::Chip(i), &FitScanResult::getChipFit, *result, result->getChipData(i), true);
00073         doFit(i, &FitScanResult::getChipFit, *result, result->getChipData(i));
00074     }
00075 
00076     //Do channels
00077     for (unsigned int i=0; i<nChannelModule; ++i) {
00078     ModuleElement element = ModuleElement::Channel(i);
00079         setupGraph(i, element, &FitScanResult::getChannelFit, *result, result->getChannelData(i), true);
00080     //Note - make sure we do this after we have setup the graph - that way we don't cause any problems with missing data
00081     //And we can check later if necessary
00082     if (getFit(0)->getConfiguration().channelIsMasked(i)) continue; 
00083     
00084         doFit(i, &FitScanResult::getChannelFit, *result, result->getChannelData(i));
00085         doDefect(element, result->getDefects(), 
00086          result->getChannelData(i), result->getChipData(i/nChannelChip));
00087     }
00088     
00089     doSlopes(*result);
00090 
00091     //mergeDefects();
00092     
00093     //Check for defects - fail if more than 15 defective channels or more than 7 consecutive defective channels
00094     const DefectList::DefectCollection& defects = result->getDefects().getAllDefects();
00095     bool passed = true;
00096     unsigned int totalChannels = 0;
00097     for (DefectList::DefectCollection::const_iterator i=defects.begin(); i!=defects.end(); ++i) {
00098         // DODGY defects don't count towards failure of module
00099         if (i->getPrototype().getSeverity() > DODGY) {
00100             totalChannels += i->getModuleElement().getNChannels();
00101             if (i->getModuleElement().getNChannels()>7) {
00102                 passed = false;
00103                 break;
00104             }
00105         }
00106     }
00107     if (totalChannels > 15) passed = false;
00108     
00109     //Add comment about number of channels trimmed
00110     if (nOnePointTrimmed != 0) {
00111     ostringstream oss;
00112     oss << nOnePointTrimmed << " channels had 1 point trimmed from fit";
00113     result->addComment(oss.str());
00114     }
00115     if (nTwoPointTrimmed != 0) {
00116     ostringstream oss;
00117     oss << nTwoPointTrimmed << " channels had 2 (or more) points trimmed from fit";
00118     result->addComment(oss.str());
00119     }
00120     
00121     result->setPassed(passed);
00122 }
00123  
00124 //Setup the graphs - also prune points
00125 void NPtGainAlgorithm::setupGraph(unsigned int id, const ModuleElement& element, getFitFunction fitFunc, NPtGainTestResult& test, NPtGainTestResultData& testData, bool trimPoints) throw(LogicError) {
00126     
00127     unsigned int lastPoint = test.getNScans()-1;
00128     //Filter out points above 5fC if they are broad and we have more than 5 points
00129     if (trimPoints && test.getNScans() > 5) {
00130     double sigmaCut = 0;
00131     for (unsigned int i=0; i<test.getNScans(); ++i) {
00132         sigmaCut+= (getFit(i).get()->*fitFunc)(id).getParameter("Sigma");
00133     }
00134     sigmaCut *= 1.5/test.getNScans();   //We want 1.5*mean sigma
00135     //cout << "Sigma Cut set to: " << sigmaCut << endl;
00136     for (unsigned int i=test.getNScans() - 1; i>4; --i) {
00137         //cout << "Point: " << i << " sigma: " << (getFit(i).get()->*fitFunc)(id).getParameter("Sigma") << " TestPoint: " << test.getTestPointAt(i) << endl;
00138         const DefectList& defects = getFit(i)->getDefects();
00139         if (test.getTestPointAt(i) > 5 && ((getFit(i).get()->*fitFunc)(id).getParameter("Sigma") > sigmaCut || 
00140                            defects.defectSeverityAffectingElement(element) >= SERIOUS)) {
00141         lastPoint = i-1;
00142         }
00143     }
00144     
00145     //Note we should only record trimed points for chips... 
00146     if (lastPoint != test.getNScans() - 1) {
00147         if (element.isChip()) {
00148         ostringstream oss;
00149         oss << "Points trimed from response curve for chip: " << id << ". Last point " << lastPoint << " with charge " << test.getTestPointAt(lastPoint);
00150         test.addComment(oss.str());
00151         } else {    //Element is a channel
00152         if (lastPoint+1-test.getNScans() == 1) ++nOnePointTrimmed;
00153         else ++nTwoPointTrimmed;
00154         }
00155     }
00156     }
00157     
00158     mergeDefects(test, element, lastPoint);
00159 
00160     shared_ptr<TGraph> g (new TGraph(lastPoint+1));
00161     if (!g)
00162         throw InvariantViolatedError("NPtGainTestResult::setupGraph couldn't make TGraph", __FILE__, __LINE__);
00163     
00164     
00165     for (unsigned int j = 0; j <= lastPoint; ++j) {
00166         // Cal charge register is set in RodDaq/Dsp/Sct/Code/ABCDConfig.c
00167         // find out which chip from the module element
00168         unsigned ichip=element.getFirst()/nChannelChip;
00169     const ChipConfiguration& chipconfig = getFit(j)->getConfiguration().getChipConfiguration(ichip);
00170     // get the cal charge register value
00171         const unsigned char cal = chipconfig.getCalCharge();
00172     // convert this to fC, taking into account the calibration factor:
00173         const float qcal= static_cast<float>(cal)*0.0625*chipconfig.getCalFactor();
00174         g->SetPoint(j, qcal, (getFit(j).get()->*fitFunc)(id).getParameter("Mean"));
00175     //if (element.getFirst()%nChannelChip==0){
00176     //  std::cout << "Chip " << element.getFirst()/nChannelChip << " Point (" << j << ") value requested = " << test.getTestPointAt(j)
00177     //      << " register = " << (int)cal 
00178     //      << " step = " << 0.0625*chipconfig.getCalFactor()
00179     //      << " actual value = " << qcal << std::endl; 
00180     //}
00181     }
00182     testData.graph = g;
00183 
00184     shared_ptr<ResponseCurve> r=getResponseCurve(test.getNScans());
00185     testData.rc = r;    
00186 }
00187 
00188 void NPtGainAlgorithm::mergeDefects(NPtGainTestResult& test, const ModuleElement& element, unsigned int lastPoint) {
00189     for (unsigned int i=0; i<lastPoint; ++i) {
00190     auto_ptr<DefectList> defects = getFit(i)->getDefects().getDefectsEncompassingElement(element);
00191     const DefectList::DefectCollection& allDefects = defects->getAllDefects();
00192     for (DefectList::DefectCollection::const_iterator it=allDefects.begin(); it!=allDefects.end(); ++it) {
00193         test.getDefects().addDefect(Defect(it->getPrototype(), element));
00194     }
00195     }
00196 }
00197 
00198 void NPtGainAlgorithm::doFit(unsigned int id, getFitFunction fitFunc, NPtGainTestResult& test,
00199                               NPtGainTestResultData& testData) throw(LogicError) {
00200     //testData.graph->Fit(&testData.rc->getFunction(), "NQ", "", 0, 10);
00201     // replaced below with generalised fitting, 17/7/03 Alan Barr
00202 
00203     testData.rc->getFunction()->SetRange(0,10);
00204     AnalysisService::instance().getFitStrategy().fitTGraph(*testData.graph, *testData.rc->getFunction() );
00205     
00206     testData.gain = testData.rc->getGain(test.getSpecialScanPointValue());
00207 
00208     shared_ptr<const FitScanResult> specialFit = getFit(test.getSpecialScanIndex());
00209     //6250 is a magic number that converts noise to ENC
00210     if (testData.gain != 0) testData.noise = 6250 * (specialFit.get()->*fitFunc)(id).getParameter("Sigma") / testData.gain;
00211     else  testData.noise = 0;
00212     testData.offset= testData.rc->getFunction()->Eval(0.);
00213 }
00214 
00215 void NPtGainAlgorithm::doDefect(const ModuleElement& element, DefectList& defects, 
00216                 const NPtGainTestResultData& data,
00217                 const NPtGainTestResultData& comparisonData) throw(LogicError) {
00218     
00219     if (data.gain < StandardDefects::VLO_GAIN.getParameter() * comparisonData.gain)
00220         defects.addDefect(Defect(StandardDefects::VLO_GAIN, element));
00221     
00222     if (data.gain < StandardDefects::LO_GAIN.getParameter() * comparisonData.gain)
00223         defects.addDefect(Defect(StandardDefects::LO_GAIN, element));
00224     else if (data.gain > StandardDefects::HI_GAIN.getParameter() * comparisonData.gain)
00225         defects.addDefect(Defect(StandardDefects::HI_GAIN, element));
00226 
00227     if (data.offset < StandardDefects::LO_OFFSET.getParameter())
00228         defects.addDefect(Defect(StandardDefects::LO_OFFSET, element));
00229     else if (data.offset > StandardDefects::HI_OFFSET.getParameter())
00230         defects.addDefect(Defect(StandardDefects::HI_OFFSET, element));
00231 
00232     if (data.noise < StandardDefects::UNBONDED.getParameter())
00233         defects.addDefect(Defect(StandardDefects::UNBONDED, element));
00234     else if (data.noise < StandardDefects::PARTBONDED.getParameter())
00235         defects.addDefect(Defect(StandardDefects::PARTBONDED, element));
00236     else if (data.noise > StandardDefects::NOISY.getParameter() * comparisonData.noise)
00237         defects.addDefect(Defect(StandardDefects::NOISY, element));
00238     
00239     if (data.noise > StandardDefects::V_NOISY.getParameter() * comparisonData.noise)
00240         defects.addDefect(Defect(StandardDefects::V_NOISY, element));
00241 }
00242 
00243   void NPtGainAlgorithm::doSlopes(NPtGainTestResult& r){
00244     shared_ptr<TGraph> noise  = r.getNoiseGraph();
00245     shared_ptr<TGraph> gain   = r.getGainGraph();
00246     shared_ptr<TGraph> offset = r.getOffsetGraph();
00247 
00248     //std::cout << "Noise" << std::endl;
00249     doSlopes(noise,  r.noiseSlope);
00250 
00251     //std::cout << "Gain" << std::endl;
00252     doSlopes(gain,   r.gainSlope);
00253 
00254     //std::cout << "Offset" << std::endl;
00255     doSlopes(offset, r.offsetSlope);
00256   }
00257 
00258   void NPtGainAlgorithm::doSlopes(shared_ptr<TGraph> graph, vector<float>& result){
00259     result.resize(nChipModule);
00260     // linear least squares:
00261     for (unsigned ichip=0; ichip<nChipModule; ++ichip){
00262       float xbar=0.;
00263       float x2bar=0.;
00264       float ybar=0.;
00265       float xybar=0.;
00266       for (unsigned ichan = 0; ichan<nChannelChip; ++ichan) {
00267     double x=0;
00268     double y=0;
00269     int bin=ichip*nChannelChip + ichan + 1;
00270     graph->GetPoint(bin, x, y);
00271     xbar  += x;
00272     ybar  += y;
00273     x2bar += x*x;
00274     xybar += x*y;
00275       }
00276       const float det = nChannelChip*x2bar - xbar*xbar;
00277       if (det>0) {
00278     result[ichip]= (nChannelChip*xybar - xbar*ybar) / det * nChannelChip;
00279       }
00280       //std::cout << ichip << " = " << result[ichip] << std::endl;
00281     }
00282   }
00283 
00284 }

Generated on Thu Feb 3 17:37:38 2005 for SCT DAQ/DCS Software - C++ by doxygen 1.3.5