![]() |
Mixed Data Coincidence Analysis Software 1.0
A program to analyze files produced by the EventMixer software.
|
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 }