Mixed Data Coincidence Analysis Software 1.0
A program to analyze files produced by the EventMixer software.
analysis.cc
Go to the documentation of this file.
00001 #include "analysis.hh"
00002 
00003 CommandLineInterpreter * decodeInput(int argc, char **argv)
00004 {
00005   list<CommandLineArgument> myArguments;
00006   myArguments.push_back(CommandLineArgument("tolerance",1));
00007   myArguments.push_back(CommandLineArgument("mixedFile",1));
00008   myArguments.push_back(CommandLineArgument("gammaFile",1));
00009   myArguments.push_back(CommandLineArgument("coincidenceFile",1));
00010   myArguments.push_back(CommandLineArgument("minA",1));
00011   myArguments.push_back(CommandLineArgument("maxA",1));
00012   myArguments.push_back(CommandLineArgument("minZ",1));
00013   myArguments.push_back(CommandLineArgument("maxZ",1));
00014   myArguments.push_back(CommandLineArgument("geEpsilon",1));
00015   myArguments.push_back(CommandLineArgument("betaEpsilon",1));
00016   myArguments.push_back(CommandLineArgument("numberOfTubes",1));
00017   myArguments.push_back(CommandLineArgument("numberPerRow",1));
00018   myArguments.push_back(CommandLineArgument("maxDecayWait",1));
00019   myArguments.push_back(CommandLineArgument("dominationFactor", 1));
00020   myArguments.push_back(CommandLineArgument("gLow", 1));
00021   myArguments.push_back(CommandLineArgument("gHigh", 1));
00022   myArguments.push_back(CommandLineArgument("bgTolerance",1));
00023   myArguments.push_back(CommandLineArgument("decayCut",1));
00024   myArguments.push_back(CommandLineArgument("detectorCount", 0));
00025   myArguments.push_back(CommandLineArgument("failInfo", 0));
00026   myArguments.push_back(CommandLineArgument("help",0));
00027   myArguments.push_back(CommandLineArgument("forceCorrect",0));
00028   myArguments.push_back(CommandLineArgument("multiImplant",1));
00029   myArguments.push_back(CommandLineArgument("timeDistributionFile",1));
00030   CommandLineInterpreter * myInterpreter = new CommandLineInterpreter(argc, argv, myArguments);
00031  
00032   if(!myInterpreter->readFlaggedCommand("help").empty() || myInterpreter->readFlaggedCommand("mixedFile").empty() || myInterpreter->readFlaggedCommand("gammaFile").empty())
00033     {
00034       cout << "The following arguments are valid for the analysis program:" << endl;
00035       cout << setiosflags(ios::left);
00036       cout << setw(5) << " " << setw(40) << "-multiImplant <integer value>" << "Allow multiple implantation and cross-associate decays." << endl;
00037       cout << setw(5) << " " << setw(40) << "-detectorCount" << "Count coincidences for different scintillators." << endl;
00038       cout << setw(5) << " " << setw(40) << "-failInfo" << "Print info about failed ID:s"<< endl;
00039       cout << setw(5) << " " << setw(40) << "-forceCorrect" << "Force output graphs to contain correct lines instead of actual identified lines."<< endl;
00040       cout << setw(5) << " " << setw(40) << "-tolerance <double value>" << "Gamma tolerance for identification." << endl;
00041       cout << setw(5) << " " << setw(40) << "-mixedFile <file name>" << "File containing mixed data to analyze." << endl;
00042       cout << setw(5) << " " << setw(40) << "-gammaFile <file name>" << "File containing gamma lines for isotopes, to use for identification" << endl;
00043       cout << setw(5) << " " << setw(40) << "-coincidenceFile <file name>" << "File to output coincidence gamma energies to." << endl;
00044       cout << setw(5) << " " << setw(40) << "-minA <integer value>" << "Minimum A to include in analysis." << endl;
00045       cout << setw(5) << " " << setw(40) << "-maxA <integer value>" << "Maximum A to include in analysis." << endl;
00046       cout << setw(5) << " " << setw(40) << "-minZ <integer value>" << "Minimum Z to include in analysis." << endl;
00047       cout << setw(5) << " " << setw(40) << "-maxZ <integer value>" << "Maximum Z to include in analysis." << endl;
00048       cout << setw(5) << " " << setw(40) << "-gLow <double value>" << "Only count Ge energies above this limit (in MeV)." << endl;
00049       cout << setw(5) << " " << setw(40) << "-gHigh <double value>" << "Only cound Ge energies below this limit (in MeV)." << endl;
00050       cout << setw(5) << " " << setw(40) << "-geEpsilon <double value>" << "Detector epsilon (treshold energy) for Ge detector. Default 50 keV." << endl;
00051       cout << setw(5) << " " << setw(40) << "-betaEpsilon <double value>" << "Detector epsilon (treshold energy) for beta detector. Default 500 keV." << endl;
00052       cout << setw(5) << " " << setw(40) << "-numberOfTubes <integer value>" << "Number of scintillator tubes in detector. Default 40" << endl;
00053       cout << setw(5) << " " << setw(40) << "-numberPerRow <integer value>" << "Number of tubes per row for scintillator count printing. Default 10" << endl;
00054       cout << setw(5) << " " << setw(40) << "-maxDecayWait <double value>" << "Maximum wait time for decay before deeming it timeout. Default 1E10 ns." << endl;
00055       cout << setw(5) << " " << setw(40) << "-decayCut <double value>" << "Maximum wait time for decay before not accepting implants. Default value 1E10 ns." << endl;
00056       cout << setw(5) << " " << setw(40) << "-dominationFactor <double value>" << "Factor to determine when a decay in a tube is so dominating that detections in other tubes can be ignored." << endl;
00057       cout << setw(5) << " " << setw(40) << "-timeDistributionFile <file name>" << "File do dump peak time distributions to. Requires -coincidenceFile." << endl; 
00058       cout << setw(5) << " " << setw(40) << "-bgTolerance <double value>" << "Size around the peaks that background will be measured in order to determine if we have a real peak." << endl;
00059       cout << setw(5) << " " << setw(40) << "-help" << "Displays this help message." << endl;
00060       exit(0);
00061     }
00062   return myInterpreter;
00063 }
00064 
00065 string nsToReadableTime(double time)
00066 {
00067   double second = 1E9;
00068   double minute = 60*second;
00069   double hour = 60*minute;
00070   double day = 24*hour;
00071   double month = 30*day;
00072   double year = 12*month;
00073   stringstream ss;
00074   if(((int)(time/year))>0)
00075     {
00076       ss << ((int)(time/year)) << "year" << (((int)(time/year))>1?"s":"");
00077       time-=year*((int)(time/year));
00078       ss << " ";
00079     }
00080   if(((int)(time/month))>0)
00081     {
00082       ss << ((int)(time/month)) << "month" << (((int)(time/month))>1?"s":"");
00083       time-=month*((int)(time/month));
00084       ss << " ";
00085     }
00086   if(((int)(time/day))>0)
00087     {
00088       ss << ((int)(time/day)) << "day" << (((int)(time/day))>1?"s":"");
00089       time-=day*((int)(time/day));
00090       ss << " ";
00091     }
00092   if(((int)(time/hour))>0)
00093     {
00094       ss << ((int)(time/hour)) << "hour" << (((int)(time/hour))>1?"s":"");
00095       time-=hour*((int)(time/hour));
00096       ss << " ";
00097     }
00098   if(((int)(time/minute))>0)
00099     {
00100       ss << ((int)(time/minute)) << "minute" << (((int)(time/minute))>1?"s":"");
00101       time-=minute*((int)(time/minute));
00102       ss << " ";
00103     }
00104   if(((int)(time/second))>0)
00105     {
00106       ss << ((int)(time/second)) << "second" << (((int)(time/second))>1?"s":"");
00107       time-=second*((int)(time/second));
00108        ss << " ";
00109     }
00110   return ss.str();
00111 }
00112 
00113 void printDetectorCount(CoincidenceFinder * F, int numberPerRow)
00114 {
00115   vector<int> count = F->getDetectorCount();
00116   int rowbreak = 0;
00117   cout << "Detector count:" << endl;
00118   cout << setfill(' ');
00119   for(vector<int>::iterator it = count.begin(); it!=count.end(); it++)
00120     {
00121       cout << setw(5) << *it << " ";
00122       if(++rowbreak>=numberPerRow)
00123         {
00124           rowbreak=0;
00125           cout << endl;
00126         }
00127     }
00128   cout << endl;
00129 }
00130 
00131 void printStatistics(CoincidenceFinder * F)
00132 {
00133   //For statistic purposes.
00134   cout << "====================";
00135   cout << "Statistics:";
00136   cout << "====================";
00137   cout << endl;
00138   cout << setiosflags(ios::left);
00139   cout << setfill('_');
00140   cout << setw(50) << "# events processed:" << F->getNoHits() << endl;
00141   cout << setw(50) << "Time of last implantation: " << nsToReadableTime(F->getTimeSpan()) << endl;
00142   cout << "Classification of events:" << endl;
00143   cout << setw(50) << "---># implantations:" << F->getNoImplantations() << endl;
00144   cout << setw(50) << "# Correct implantations:" << F->getNoCorrectImplantations() << endl;
00145   cout << setw(50) << "# Double hits:" << F->getNoDoubleHit() << endl;
00146   cout << setw(50) << "---># decays:" << F->getNoDecays() << endl;
00147   cout << setw(50) << "# Non-associated decays:" << F->getNoNonAssociatedDecays() << endl;
00148   cout << setw(50) << "# Decays without Ge-hit:" << F->getNoGeHit() << endl;
00149   cout << setw(50) << "# Correctly connected implant-decay:" << F->getNoCorrConnected() << endl;
00150   cout << setw(50) << "# Incorrectly connected implant-decay:" << F->getNoErrConnected() << endl;
00151   cout << setw(50) << "---># other:" << F->getNoOther() << endl;
00152   cout << setw(50) << "# Destroyed by other:" << F->getNoDestroyedByOther() << endl;
00153   cout << endl;
00154   cout << "Reasons for other-classification:" << endl;
00155   cout << setw(50) << "Particle went through FSP and BSP:" << F->getFailureReason(0) << endl;
00156   cout << setw(50) << "Particle through FSP but no implant:" << F->getFailureReason(1) << endl;
00157   cout << setw(50) << "Particle through FSP but implant in several tubes:" << F->getFailureReason(2) << endl;
00158   cout << setw(50) << "Particle not through SP, and no tube:" << F->getFailureReason(3) << endl;
00159   cout << setw(50) << "Particle not through SP, and several tubes:" << F->getFailureReason(4) << endl;
00160   cout << setw(50) << "Particle through BSP, not FSP, no tube:" << F->getFailureReason(5) << endl;
00161   cout << setw(50) << "Particle through BSP, not FSP, several tubes:" << F->getFailureReason(6) << endl;
00162   cout << setw(50) << "Particle through BSP, not FSP, one tube:" << F->getFailureReason(7) << endl;
00163 
00164   cout << endl;
00165   
00166   cout << setw(50) << "Found coincidences:" << F->getNoFoundCoincidences() << endl; 
00167   cout << setw(50) << "# correct:" << F->getNoCorrCoincidence() << endl;
00168   cout << setw(50) << "Ratio:" << (float)F->getNoCorrCoincidence()/((float)F->getNoFoundCoincidences())*100 << "%" <<  endl;
00169   
00170   cout << endl;
00171 }
00172 
00173 void printSettings(Settings * toPrint)
00174 {
00175   cout << "++++++++++++++++";
00176   cout << "Analysis settings:";
00177   cout << "++++++++++++++++";
00178   cout << endl;
00179   cout << setiosflags(ios::left);
00180   cout << setfill('_');
00181   cout << setw(50) << "Coincidence file:" << toPrint->coincidenceFile << endl;
00182   cout << setw(50) << "Time distribution file:" << toPrint->timeDistributionFile << endl;
00183   cout << setw(50) << "Mix file (data to analyze):" << toPrint->mixedFile << endl;
00184   cout << setw(50) << "Gamma data file:" << toPrint->gammaFile << endl;
00185   cout << endl;
00186   cout << setw(50) << "Tolerance (MeV):" << toPrint->tolerance << endl;
00187   cout << setw(50) << "Background tolerance (MeV):" << toPrint->bgTolerance << endl;
00188   cout << setw(50) << "#Multi-implantations allowed:" << toPrint->multiImplant << endl;
00189   cout << setw(50) << "Number of scintillator tubes:" << toPrint->nTubes << endl;
00190   cout << setw(50) << "Number of tubes per row:" << toPrint->nTubesPerRow << endl;
00191   cout << setw(50) << "Ge detector epsilon (MeV):" << toPrint->geEpsilon << endl;
00192   cout << setw(50) << "Beta detector epsilon (MeV):" << toPrint->betaEpsilon << endl;
00193   cout << setw(50) << "Domination ratio:" << toPrint->dRatio << endl;
00194   cout << setw(50) << "Minimum Ge energy (MeV):" << toPrint->minGe << endl;
00195   cout << setw(50) << "Maximum Ge energy (MeV):" << toPrint->maxGe << endl;
00196   cout << setw(50) << "Maximum decay wait (ns):" << toPrint->maxDecayWait << endl;
00197   cout << setw(50) << "Decay cut (ns):" << toPrint->decayCut << endl;
00198   cout << setw(50) << "Force correct identification:" << (toPrint->forceCorrect?"yes":"no") << endl;
00199   cout << setw(50) << "A range:" << toPrint->minA << "-" << toPrint->maxA << endl;
00200   cout << setw(50) << "Z range:" << toPrint->minZ << "-" << toPrint->maxZ << endl;
00201   cout << setw(50) << "Display detector count:" << (toPrint->detectorCount?"yes":"no") << endl;
00202   cout << setw(50) << "Display info about ID failures:" << (toPrint->failInfo?"yes":"no") << endl;
00203   cout << endl;
00204 }
00205 
00206 Settings * initSettings(CommandLineInterpreter * myInterpreter)
00207 {
00208   Settings * S = new Settings();
00209   S->tolerance = 0.003; //MeV
00210   if(myInterpreter->readFlaggedCommand("tolerance").size()==1)
00211     S->tolerance = atof(myInterpreter->readFlaggedCommand("tolerance").front().c_str());
00212   S->bgTolerance = 0.05; //MeV
00213   
00214   S->multiImplant = myInterpreter->readFlaggedCommand("multiImplant").size()==1?atoi(myInterpreter->readFlaggedCommand("multiImplant").front().c_str()):1;
00215   
00216   S->nTubes = myInterpreter->readFlaggedCommand("numberOfTubes").size()==1?
00217     atoi(myInterpreter->readFlaggedCommand("numberOfTubes").front().c_str()):40;
00218   S->nTubesPerRow = myInterpreter->readFlaggedCommand("numberPerRow").size()==1?
00219     atoi(myInterpreter->readFlaggedCommand("numberPerRow").front().c_str()):10;
00220 
00221   S->geEpsilon = myInterpreter->readFlaggedCommand("geEpsilon").size()==1?atof(myInterpreter->readFlaggedCommand("geEpsilon").front().c_str()):5E-2;
00222   S->betaEpsilon = myInterpreter->readFlaggedCommand("betaEpsilon").size()==1?atof(myInterpreter->readFlaggedCommand("betaEpsilon").front().c_str()):5E-1;
00223 
00224   S->dRatio = myInterpreter->readFlaggedCommand("dominationFactor").size()==1?atof(myInterpreter->readFlaggedCommand("dominationFactor").front().c_str()):1E3;
00225   S->minGe = myInterpreter->readFlaggedCommand("gLow").size()==1?atof(myInterpreter->readFlaggedCommand("gLow").front().c_str()):5E-1;
00226   
00227   S->maxGe = myInterpreter->readFlaggedCommand("gHigh").size()==1?atof(myInterpreter->readFlaggedCommand("gHigh").front().c_str()):3E0;
00228   
00229   S->maxDecayWait=  myInterpreter->readFlaggedCommand("maxDecayWait").size()==1?atof(myInterpreter->readFlaggedCommand("maxDecayWait").front().c_str()):1E10;
00230   
00231   S->decayCut=  myInterpreter->readFlaggedCommand("decayCut").size()==1?atof(myInterpreter->readFlaggedCommand("decayCut").front().c_str()):1E20;
00232 
00233   S->mixedFile = myInterpreter->readFlaggedCommand("mixedFile").size()==1?(myInterpreter->readFlaggedCommand("mixedFile").front()):("");
00234   S->forceCorrect = !myInterpreter->readFlaggedCommand("forceCorrect").empty();
00235 
00236   S->gammaFile =myInterpreter->readFlaggedCommand("gammaFile").size()==1?(myInterpreter->readFlaggedCommand("gammaFile").front()):("");
00237   S->minA = ((myInterpreter->readFlaggedCommand("minA").size()==1)?atoi(myInterpreter->readFlaggedCommand("minA").front().c_str()):(-1000));
00238   S->maxA = ((myInterpreter->readFlaggedCommand("maxA").size()==1)?atoi(myInterpreter->readFlaggedCommand("maxA").front().c_str()):(1000));
00239   S->minZ = ((myInterpreter->readFlaggedCommand("minZ").size()==1)?atoi(myInterpreter->readFlaggedCommand("minZ").front().c_str()):(-1000));
00240   S->maxZ = ((myInterpreter->readFlaggedCommand("maxZ").size()==1)?atoi(myInterpreter->readFlaggedCommand("maxZ").front().c_str()):(1000));
00241 
00242   S->coincidenceFile = myInterpreter->readFlaggedCommand("coincidenceFile").size()==1?(myInterpreter->readFlaggedCommand("coincidenceFile").front()):("");
00243 
00244   S->detectorCount = !myInterpreter->readFlaggedCommand("detectorCount").empty();
00245 
00246   S->timeDistributionFile = (myInterpreter->readFlaggedCommand("timeDistributionFile").size()==1)?(myInterpreter->readFlaggedCommand("timeDistributionFile").front()):"";
00247   S->failInfo = !myInterpreter->readFlaggedCommand("failInfo").empty();
00248 
00249   return S;
00250 }
00251 
00252 int main(int argc, char **argv)
00253 {
00254   CommandLineInterpreter * myInterpreter = decodeInput(argc, argv);
00255   Settings * S = initSettings(myInterpreter);
00256   printSettings(S);
00257 
00258   FileEventParser * myEventParser = new FileEventParser((char*)S->mixedFile.c_str(), S->nTubes, S->betaEpsilon, S->dRatio);
00259 
00260   list<pair<EventHit*, EventHit*> > foundCoincidences;
00261 
00262   CoincidenceFinder * myFinder = new CoincidenceFinder(myEventParser, S->maxDecayWait, S->nTubes, S->geEpsilon, S->minGe, S->maxGe, S->multiImplant, S->decayCut);
00263 
00264 
00265   while(myFinder->hasMoreCoincidences())    
00266     {
00267       foundCoincidences.push_back(myFinder->getNextCoincidence());
00268     }
00269 
00270   printStatistics(myFinder);
00271 
00272 
00273   if(S->coincidenceFile.size()>0)
00274     {
00275       FILE * coinFile = fopen(S->coincidenceFile.c_str(),"w");
00276       list<pair<EventHit*, EventHit*> > deletable(foundCoincidences);
00277       FILE * tFile = NULL;
00278       if(S->timeDistributionFile.size()>0)
00279         {
00280           tFile = fopen(S->timeDistributionFile.c_str(),"w");
00281         }
00282 
00283       if(coinFile!=NULL)
00284         {
00285           int count = 0;
00286           while(!deletable.empty())
00287             {
00288               ++count;
00289               GammaEnergyChart * myEnergyChart = 
00290                 new GammaEnergyChart((char*)S->gammaFile.c_str(), S->minA, S->maxA, S->minZ, S->maxZ, S->tolerance, S->bgTolerance);
00291               
00292               GammaIdentifier * myIdentifier = new GammaIdentifier(myEnergyChart, S->tolerance, S->minGe, S->maxGe, S->bgTolerance, S->forceCorrect);
00293               int A = deletable.front().first->A;
00294               int Z = deletable.front().first->Z;
00295               for(list<pair<EventHit*, EventHit*> >::iterator it =  deletable.begin(); it!=deletable.end(); it++)
00296                 {
00297                   
00298                   if(it->first->A==A && it->first->Z==Z)
00299                     {
00300                       myIdentifier->addCoincidence(*it);
00301                       it=deletable.erase(it);
00302                       --it;
00303                     }
00304                 }
00305               fprintf(coinFile,"%s\n",myIdentifier->getMATLABstring(count).c_str());
00306               if(tFile!=NULL)
00307                 {
00308                   fprintf(tFile,"%s\n",myIdentifier->getPeakString().c_str());
00309                 }
00310               
00311               delete myIdentifier;
00312               delete myEnergyChart;
00313             }
00314         }
00315     }
00316   
00317   if(S->detectorCount)
00318     {
00319       printDetectorCount(myFinder, S->nTubesPerRow);
00320     }
00321 
00322   if(S->failInfo)
00323     {
00324       cout << "The failed ID:s:" << endl << endl;
00325       for(list<pair<EventHit*, EventHit*> >::iterator it =  foundCoincidences.begin(); it!=foundCoincidences.end(); it++)
00326         {
00327           if(it->first->eventno!=it->second->eventno)
00328             {
00329               cout << "Time diff (ms): " << (it->second->time - it->first->time)/1E6 << endl;
00330               cout << it->first->toString();
00331               cout << it->second->toString() << endl;
00332               cout << endl;
00333             }
00334         }
00335     }
00336 
00337 
00338   set<EventHit*> toDelete;
00339   //Clean up.
00340   for(list<pair<EventHit*, EventHit*> >::iterator it =  foundCoincidences.begin(); it!=foundCoincidences.end(); it++)
00341     {
00342       toDelete.insert(it->first);
00343       toDelete.insert(it->second);
00344     }
00345   //we have to check as so not make a multiple-delete... that would indeed be bad.
00346   for(set<EventHit*>::iterator it = toDelete.begin(); it!=toDelete.end(); it++)
00347     {
00348       delete *it;
00349     }
00350 
00351   delete myEventParser;
00352   return 0;
00353 }
 All Classes Files Functions Variables Defines

Back to the main page of the Precalibrated Ion Beam Identification Detector project

Created by Rikard Lundmark