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
00067 nOnePointTrimmed = 0;
00068 nTwoPointTrimmed = 0;
00069
00070
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
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
00081
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
00092
00093
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
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
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
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
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();
00135
00136 for (unsigned int i=test.getNScans() - 1; i>4; --i) {
00137
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
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 {
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
00167
00168 unsigned ichip=element.getFirst()/nChannelChip;
00169 const ChipConfiguration& chipconfig = getFit(j)->getConfiguration().getChipConfiguration(ichip);
00170
00171 const unsigned char cal = chipconfig.getCalCharge();
00172
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
00176
00177
00178
00179
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
00201
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
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
00249 doSlopes(noise, r.noiseSlope);
00250
00251
00252 doSlopes(gain, r.gainSlope);
00253
00254
00255 doSlopes(offset, r.offsetSlope);
00256 for (unsigned ichip=0; ichip<nChipModule; ++ichip){
00257 if (r.noiseSlope[ichip]>StandardDefects::NOISE_SLOPE.getParameter()){
00258 r.getDefects().addDefect(Defect(StandardDefects::NOISE_SLOPE, ModuleElement::Chip(ichip)));
00259 }
00260 if (r.gainSlope[ichip]>StandardDefects::GAIN_SLOPE.getParameter()){
00261 r.getDefects().addDefect(Defect(StandardDefects::GAIN_SLOPE, ModuleElement::Chip(ichip)));
00262 }
00263 if (r.offsetSlope[ichip]>StandardDefects::OFFSET_SLOPE.getParameter()){
00264 r.getDefects().addDefect(Defect(StandardDefects::OFFSET_SLOPE, ModuleElement::Chip(ichip)));
00265 }
00266
00267 }
00268
00269 }
00270
00271 void NPtGainAlgorithm::doSlopes(shared_ptr<TGraph> graph, Sct::RangedVector<float>& result){
00272 result.resize(nChipModule);
00273
00274 for (unsigned ichip=0; ichip<nChipModule; ++ichip){
00275 double xsum=0.;
00276 double x2sum=0.;
00277 double ysum=0.;
00278 double xysum=0.;
00279 unsigned n=0;
00280 for (unsigned ichan = 0; ichan<nChannelChip; ++ichan) {
00281 double x=0;
00282 double y=0;
00283 int bin=ichip*nChannelChip + ichan;
00284 graph->GetPoint(bin, x, y);
00285 if (y>0.0001){
00286 xsum += x;
00287 ysum += y;
00288 x2sum += x*x;
00289 xysum += x*y;
00290 ++n;
00291 }
00292 }
00293 const double det = ( n*x2sum ) - ( xsum*xsum );
00294 if (det>0) {
00295 result[ichip]= (n*xysum - xsum*ysum) / det;
00296 }else{
00297 result[ichip]=0.;
00298 }
00299 }
00300 }
00301
00302 }