/* * PairFinderTask.cpp * * Created on: Jul 22, 2014 * Author: Roman Klasen, klasen@kph.uni-mainz.de */ #include "LmdPairFinderTask.h" #include #include #include #include #include #include #include #include #include ClassImp(LmdPairFinderTask); //simple pixel hit, maybe not even necessary struct pixelHit{ int _sensorId; double _col; double _row; double x() const{ return _col; } pixelHit(int idVal, double colVal, double rowVal){ _sensorId = idVal; _col=colVal; _row=rowVal; } pixelHit(){ _col=-1; _row=-1; _sensorId=-1; } }; /* * contains multiple pixelHits that form a cluster. most routines are for checking, * if two separate pixelHits belong to the same cluster */ struct pixelCluster{ int _sensorId; double centerCol, centerRow;//,centerZ; double clusterSize; vector pixelHits; bool clusterReady; pixelCluster(){ _sensorId=-1; centerCol=-1; centerRow=-1;//centerZ=-1; clusterSize=-1; clusterReady=false; } pixelCluster(const pixelHit &hit){ _sensorId=hit._sensorId; pixelHits.push_back(hit); centerCol=-1; centerRow=-1;//centerZ=-1; clusterSize=-1; clusterReady=false; } pixelCluster(const pixelCluster& copy){ _sensorId=copy._sensorId; for(int i=0; ipixelHits.size(); i++){ _col1 = this->pixelHits[i]._col; _row1 = this->pixelHits[i]._row; for(int j=0; j0){ deltax=deltax+1; } if(deltax<0){ deltax=deltax-1; } double deltay=(pixelHits[i]._row-pixelHits[j]._row); if(deltay>0){ deltay=deltay+1; } if(deltay<0){ deltay=deltay-1; } tempDistance = sqrt(deltax*deltax + deltay*deltay); clusterSize=max(clusterSize, tempDistance); } } } clusterReady=true; } void printPixels(){ for(int i=0; iGetObject(fInBranchName); if (!mcPixels) { std::cout << "-W- LmdPairFinder::Init: "<< "ERROR, branch name not found!" << std::endl; return kERROR; } dimension = PndLmdDim::Instance(); dimension->Read_transformation_matrices("/geometry/trafo_matrices_lmd.dat",true); dimension->Read_transformation_matrices("/geometry/trafo_matrices_lmd_misaligned.dat",false); if(sortByModule){ cout << "====== STORING SORTED =========" << endl; /* * initialize multiple TClonesArrays and register them */ int moduleID; const char *moduleIDchar; //std::stringstream moduleIDstrm; // half can be 0 or 1 for(unsigned int iHalf=0; iHalf < 2; iHalf++){ // plane can be 0, 1, 2, 3 for(unsigned int iPlane=0; iPlane < 4; iPlane++){ // module can be 0, 1, 2, 3, 4 for(unsigned int iModule=0; iModule<5; iModule++){ /* * TODO: maybe outsource these two ModuleID generators to PndLmdDim.h */ //moduleIDstrm << iHalf << iPlane << iModule; //moduleID = makeModuleID(iHalf, iPlane, iModule); moduleID = dimension->makeModuleID(iHalf, iPlane, iModule); moduleIDchar = dimension->makeModuleIDchar(iHalf, iPlane, iModule); hitPairMap[moduleID] = new TClonesArray("PndLmdHitPair"); ioman->Register(moduleIDchar, "PndLmd", hitPairMap[moduleID], kTRUE); cerr << "HOLA! I maed dis: " << moduleIDchar << endl; //delete moduleIDchar; //ioman->Register(moduleIDstrm.str().c_str(), "PndLmd", hitPairMap[moduleID], kTRUE); //moduleIDstrm.str(""); } } } } else{ cout << "====== STORING UNSORTED =========" << endl; hitPairArray = new TClonesArray("PndLmdHitPair"); ioman->Register("PndLmdHitPair", "PndLmd", hitPairArray, kTRUE); } //maxDistance=160e-4; std::cout << "LmdPairFinder::Init(): Initialization successful." << std::endl; return kSUCCESS; } void LmdPairFinderTask::SetBranchNames() { std::cout << "branch names set to " << fInBranchName << std::endl; } InitStatus LmdPairFinderTask::ReInit() { return InitStatus(); } /* * Main SensorHit filter. It stores the sensor row and column info to a PndLmdHitPair object, * filters for valid hit pairs and stores the decoded hit in LMD coordinate system to the HitPair. * The HitPair contains BOTH original row and col hits as well as LMD xyz Coordinates (as TVector3) */ void LmdPairFinderTask::Exec(Option_t* opt) { //clear temporary array for next event if(sortByModule){ //clear hit count map for next event typedef std::map::iterator it_type1; typedef std::map::iterator it_type2; for(it_type1 iterator = hitCountMap.begin(); iterator != hitCountMap.end(); iterator++) { iterator->second = 0; } for(it_type2 iterator = hitPairMap.begin(); iterator != hitPairMap.end(); iterator++) { iterator->second->Clear(); } } else{ hitPairArray->Clear(); } Int_t nPixels = mcPixels->GetEntriesFast(); noOfEvents++; //no pixel hits? no wörk! if(nPixels <1){ eventMissedAllPlanes++; return; } sumOfPixelHits +=nPixels; int hitSensorId, col, row; int sortedHits=0; //display some kind of progress if((noOfEvents%10000)==0){ cout << "processed " << noOfEvents << endl; } //make firing pixels to clusters vector clusters; //read pixel hits from root file for(int i_Pixel=0; i_PixelAt(i_Pixel); hitSensorId = mcPixel->GetSensorID(); col = mcPixel->GetPixelColumn(); row = mcPixel->GetPixelRow(); //skip decoding errors if(col < 0 | row < 0){ continue; } else{ clusters.push_back(pixelCluster(pixelHit(hitSensorId, col, row))); } } //DEBUG ONLY /* for(int iCluster=0; iCluster * output vector * * algorithm: Hierarchical Clustering Algorithm, see https://en.wikipedia.org/wiki/Hierarchical_clustering * start by putting every pixel hit in a separate cluster (done above). * then merge every two clusters that are close enough (1-2 pixels, may be open to adjustment). * terminate if no more clusters can be merged or after N iterations for N pixel hits. * all remaining clusters contain every pixel hit. */ bool actionDone; for(int iRounds=0; iRounds 1){ hitsClustered++; //FIXME: get from config file if(clusters[i].clusterSize > 3){ clusters.erase(clusters.begin()+i); /* * this is important! when you erase cluster i, cluster i+1 becomes cluster i, but i becomes i+1. * that means, cluster i (former i+1) never gets checked in the first line of the outer for loop! */ i--; } } else{ hitsSinglePixel++; } } /* for(int i=0; iDecode_hit(fid, col1,row1, true); const TVector3 backHit = dimension->Decode_hit(bid, col2, row2, true); //dont't store in lmd local const TVector3 frontInLMD = dimension->Transform_global_to_lmd_local(frontHit, false, true); const TVector3 backInLMD = dimension->Transform_global_to_lmd_local(backHit, false, true); pair.setHit1(frontHit); pair.setHit2(backHit); pair.setModuleId(dimension->makeModuleID(fid, bid)); pair.setOverlapId(dimension->makeOverlapID(fid, bid)); } bool LmdPairFinderTask::isSuitable(PndLmdHitPair &candidate) { if(!candDistanceIsGood(candidate)){ distanceTooHigh++; return false; } int fhalf, fplane, fmodule, fside, fdie, fsensor; int bhalf, bplane, bmodule, bside, bdie, bsensor; dimension->Get_sensor_by_id(candidate.getId1(), fhalf, fplane, fmodule, fside, fdie, fsensor); dimension->Get_sensor_by_id(candidate.getId2(), bhalf, bplane, bmodule, bside, bdie, bsensor); if(fplane!=bplane){ return false; } switch(fplane){ case 0: plane0++; break; case 1: plane1++; break; case 2: plane2++; break; case 3: plane3++; break; default: //should never happen, can only indicate decoding error cerr << "WARNING: hit was deemed suitable but plane number is " << fplane << endl; cerr << "This should not happen!" << endl; } if(bside < fside){ candidate.swapHits(); } noOfGoodPairs++; return true; } //depends only on PndLmdDim, so should work bool LmdPairFinderTask::candHitsOverlappingArea(PndLmdHitPair &candidate) { int firstSensorId, secondSensorId; firstSensorId=candidate.getId1(); secondSensorId=candidate.getId2(); return candHitsOverlappingArea(firstSensorId, secondSensorId); } //depends only on PndLmdDim, so should work bool LmdPairFinderTask::candHitsOverlappingArea(Int_t firstSensorId, Int_t secondSensorId) { //same sensor hit? if(firstSensorId==secondSensorId){ return false; } int fhalf, fplane, fmodule, fside, fdie, fsensor; int bhalf, bplane, bmodule, bside, bdie, bsensor; /* * TODO: the new PndLmdDim.h also supports checks for overlapping-ness. * Maybe use this in the future. */ dimension->Get_sensor_by_id(firstSensorId, fhalf, fplane, fmodule, fside, fdie, fsensor); dimension->Get_sensor_by_id(secondSensorId, bhalf, bplane, bmodule, bside, bdie, bsensor); //the necessities for overlapping, must be on same half, plane, module and other side if(bhalf != fhalf){ return false; } if(bplane != fplane){ return false; } if(bmodule != fmodule){ return false; } if(bside == fside){ return false; } //0to5 if(fdie == 0 && fsensor == 0 && bdie == 0 && bsensor == 0){ return true; } //3to8 if(fdie == 1 && fsensor == 1 && bdie == 1 && bsensor == 1){ return true; } //4to9 if(fdie == 1 && fsensor == 2 && bdie == 1 && bsensor == 2){ return true; } //3to6 if(fdie == 1 && fsensor == 1 && bdie == 0 && bsensor == 1){ return true; } //1to8 if(fdie == 0 && fsensor == 1 && bdie == 1 && bsensor == 1){ return true; } //2to8 if(fdie == 0 && fsensor == 2 && bdie == 1 && bsensor == 1){ return true; } //2to9 if(fdie == 0 && fsensor == 2 && bdie == 1 && bsensor == 2){ return true; } //3to7 if(fdie == 1 && fsensor == 1 && bdie == 0 && bsensor == 2){ return true; } //4to7 if(fdie == 1 && fsensor == 2 && bdie == 0 && bsensor == 2){ return true; } //all other checks are negative? then the sensors don't overlap! return false; } bool LmdPairFinderTask::candDistanceIsGood(PndLmdHitPair &candidate) { //FIXME: this distance must be set in parameter file! currently is 2 pixels //use distance squared double distance = candidate.getDistance(); if(distance > maxDistance){ return false; } return true; } void LmdPairFinderTask::Reset() { }