#include "hpiontrackerhitf.h"
#include "hpiontrackerdef.h"
#include "hpiontrackercal.h"
#include "hpiontrackerhit.h"
#include "hpiontrackerdetector.h"
#include "hpiontrackerhitfpar.h"
#include "hpiontrackergeompar.h"
#include "../base/geometry/hgeomtransform.h"
#include "hades.h"
#include "hcategory.h"
#include "hdebug.h"
#include "hevent.h"
#include "hiterator.h"
#include "hruntimedb.h"
#include "hspectrometer.h"
#include <iomanip>
#include <iostream>
#include <algorithm>
#include <vector>
#include <cmath>
#include <stdlib.h>
#include <string.h>
using namespace std;
#define PR(x) std::cout << "++DEBUG: " << #x << " = |" << x << "| (" << __FILE__ << ", " << __LINE__ << ")\n";
#define PRh(x) std::cout << "++DEBUG: " << #x << " = hex |" << std::hex << x << std::dec << "| (" << __FILE__ << ", " << __LINE__ << ")\n";
typedef std::vector< StripData > strips_vec;
typedef std::vector<HitCanData> hitcan;
struct ClusterCand
{
strips_vec hits;
};
struct ClusterData
{
Int_t strip;
Float_t pos;
Float_t time;
Float_t charge;
};
struct hit
{
hitcan h[2];
};
struct HitsData
{
Float_t posX;
Float_t timeX;
Float_t chargeX;
Float_t posY;
Float_t timeY;
Float_t chargeY;
Float_t time_avg;
Float_t charge_avg;
void calcAvgs()
{
Float_t qtot = chargeX + chargeY;
time_avg = (timeX * chargeX + timeY*chargeY)/qtot;
charge_avg = (chargeX + chargeY) / 2.0;
}
};
Bool_t hit_sort_c(StripData a, StripData b)
{
return a.second.second < b.second.second;
}
typedef std::vector< ClusterCand > clus_cand_vec;
typedef std::vector< ClusterData > clusters_vec;
typedef std::vector< HitsData > hits_vec;
ClassImp (HPionTrackerHitF)
HPionTrackerHitF::HPionTrackerHitF (void)
{
pCalCat = NULL;
pHitCat = NULL;
iter = NULL;
pHitfpar = NULL;
pGeompar = NULL;
}
HPionTrackerHitF::HPionTrackerHitF (const Text_t * name, const Text_t * title, Bool_t skip)
: HReconstructor (name, title)
{
pCalCat = NULL;
pHitCat = NULL;
iter = NULL;
pHitfpar = NULL;
pGeompar = NULL;
}
HPionTrackerHitF::~HPionTrackerHitF (void)
{
if (NULL != iter)
{
delete iter;
iter = NULL;
}
}
Bool_t HPionTrackerHitF::init (void)
{
HPionTrackerDetector * det = (HPionTrackerDetector *) gHades->getSetup()->getDetector ("PionTracker");
if (!det)
{
Error ("init", "No PionTracker found.");
return kFALSE;
}
pHitfpar = (HPionTrackerHitFPar *) gHades->getRuntimeDb()->getContainer ("PionTrackerHitFPar");
if (!pHitfpar) return kFALSE;
pGeompar = (HPionTrackerGeomPar *) gHades->getRuntimeDb()->getContainer ("PionTrackerGeomPar");
if (!pGeompar) return kFALSE;
pCalCat = gHades->getCurrentEvent()->getCategory (catPionTrackerCal);
if (!pCalCat)
{
Error ("init()", "HPionTrackerCal category not available!");
return kFALSE;
}
iter = (HIterator *) pCalCat->MakeIterator();
loccal.set (2, 0, 0);
pHitCat = det->buildCategory (catPionTrackerHit);
if (!pHitCat) return kFALSE;
loc.set(2, 0, 0);
fActive = kTRUE;
return kTRUE;
}
Int_t HPionTrackerHitF::execute (void)
{
HPionTrackerCal * pCal = NULL;
HPionTrackerHit * pHit = NULL;
const Int_t modules = pHitfpar->getNumModules();
strips_vec fired_strips[modules];
strips_vec can_strips[modules];
for (Int_t entry = 0; entry < pCalCat->getEntries(); ++entry)
{
if (NULL == (pCal = static_cast<HPionTrackerCal *> (pCalCat->getObject (entry))))
{
Error ("execute", "Pointer to HPionTrackerCal object == NULL, returning");
return -1;
}
Int_t module = pCal->getModule();
Int_t strip = pCal->getStrip();
size_t mult = pCal->getMultiplicity();
Float_t win_l = pHitfpar->getTimeWindowOffset(module);
Float_t win_u = pHitfpar->getTimeWindowWidth(module) + win_l;
for (size_t i = 0; i < mult; ++i)
{
Float_t hit_t;
Float_t hit_c;
pCal->getTimeAndCharge(i, hit_t, hit_c);
if ( (hit_t < win_l) or (hit_t > win_u))
continue;
std::pair<Int_t, Float_t> pinner(strip, hit_c);
StripData stripdat(hit_t,pinner);
fired_strips[module].push_back(stripdat);
}
}
hit hits;
hits.h[0].clear();
hits.h[1].clear();
for (Int_t m1 = 0; m1 < modules; ++m1)
{
for (UInt_t h1 = 0; h1 < fired_strips[m1].size(); ++h1)
{
Float_t stripdiff1=fired_strips[m1][h1].second.first-fired_strips[m1][h1+1].second.first;
Float_t stripdiff2=fired_strips[m1][h1].second.first-fired_strips[m1][h1+2].second.first;
if(abs(stripdiff1)==1)
{
if(abs(stripdiff2)==2)
{
Int_t av_strip=fired_strips[m1][h1+1].second.first;
Float_t av_time=(fired_strips[m1][h1].first+fired_strips[m1][h1+1].first+fired_strips[m1][h1+2].first)/3.;
Float_t av_charge=(fired_strips[m1][h1].second.second+fired_strips[m1][h1+1].second.second+fired_strips[m1][h1+2].second.second)/3.;
std::pair<Int_t, Float_t> stripper(av_strip, av_charge);
StripData stripcandat(av_time,stripper);
can_strips[m1].push_back(stripcandat);
h1++;
}
else
{
Int_t av_strip=fired_strips[m1][h1].second.first;
Float_t av_time=(fired_strips[m1][h1].first+fired_strips[m1][h1+1].first)/2.;
Float_t av_charge=(fired_strips[m1][h1].second.second+fired_strips[m1][h1+1].second.second)/2.;
std::pair<Int_t, Float_t> stripper(av_strip, av_charge);
StripData stripcandat(av_time,stripper);
can_strips[m1].push_back(stripcandat);
}
h1++;
}
else
{
std::pair<Int_t, Float_t> stripper(fired_strips[m1][h1].second.first,fired_strips[m1][h1].second.second);
StripData stripcandat(fired_strips[m1][h1].first,stripper);
can_strips[m1].push_back(stripcandat);
}
}
}
for (Int_t m1 = 0; m1 < modules; ++m1)
{
Float_t clus_time_diff = pHitfpar->getClusterDistT(m1);
Float_t charge_diff = pHitfpar->getChargeThresh(m1);
for (Int_t m2 = m1+1; m2< modules; ++m2)
{
for (UInt_t h1 = 0; h1 < can_strips[m1].size(); ++h1)
{
for (UInt_t h2 = 0; h2 < can_strips[m2].size(); ++h2)
{
Float_t difft = can_strips[m1][h1].first-can_strips[m2][h2].first;
if (difft > (-1. * clus_time_diff) and difft < clus_time_diff)
{
Float_t diffc = can_strips[m1][h1].second.second-can_strips[m2][h2].second.second;
Float_t radius = sqrt(diffc*diffc + difft * difft);
if (m1 == 0 and m2 == 1)
{
Float_t chargethr_u = charge_diff;
Float_t chargethr_l = -1.0 * charge_diff;
if (can_strips[m1][h1].second.second != HPionTrackerCal::InvalidAdc() and can_strips[m2][h2].second.second != HPionTrackerCal::InvalidAdc() )
{
if( diffc >= chargethr_l and diffc <= chargethr_u)
{
Float_t avg_t = (can_strips[m1][h1].first+can_strips[m2][h2].first)/2.;
Float_t avg_c = (can_strips[m1][h1].second.second+can_strips[m2][h2].second.second)/2.;
HitCanData can;
can.radtimecharge = radius;
can.posX = can_strips[m1][h1].second.first;
can.timeX = can_strips[m1][h1].first;
can.chargeX = can_strips[m1][h1].second.second;
can.eventnrX = h1;
can.posY = can_strips[m2][h2].second.first;
can.timeY = can_strips[m2][h2].first;
can.chargeY = can_strips[m2][h2].second.second;
can.eventnrY = h2;
can.timeavg = avg_t;
can.chargeavg = avg_c;
hits.h[0].push_back(can);
}
}
else
{ Float_t avg_t = (can_strips[m1][h1].first+can_strips[m2][h2].first)/2.;
Float_t avg_c = (can_strips[m1][h1].second.second+can_strips[m2][h2].second.second)/2.;
HitCanData can;
can.radtimecharge = radius;
can.posX = can_strips[m1][h1].second.first;
can.timeX = can_strips[m1][h1].first;
can.chargeX = can_strips[m1][h1].second.second;
can.eventnrX = h1;
can.posY = can_strips[m2][h2].second.first;
can.timeY = can_strips[m2][h2].first;
can.chargeY = can_strips[m2][h2].second.second;
can.eventnrY = h2;
can.timeavg = avg_t;
can.chargeavg = avg_c;
hits.h[0].push_back(can);
}
}
if (m1 == 2 and m2 == 3)
{
Float_t chargethr_u = charge_diff;
Float_t chargethr_l = -1.0 * charge_diff;
if (can_strips[m1][h1].second.second != HPionTrackerCal::InvalidAdc() and can_strips[m2][h2].second.second != HPionTrackerCal::InvalidAdc())
{
if( diffc >= chargethr_l and diffc <= chargethr_u)
{
Float_t avg_t = (can_strips[m1][h1].first+can_strips[m2][h2].first)/2.;
Float_t avg_c = (can_strips[m1][h1].second.second+can_strips[m2][h2].second.second)/2.;
HitCanData can;
can.radtimecharge = radius;
can.posX = can_strips[m1][h1].second.first;
can.timeX = can_strips[m1][h1].first;
can.chargeX = can_strips[m1][h1].second.second;
can.eventnrX = h1;
can.posY = can_strips[m2][h2].second.first;
can.timeY = can_strips[m2][h2].first;
can.chargeY = can_strips[m2][h2].second.second;
can.eventnrY = h2;
can.timeavg = avg_t;
can.chargeavg = avg_c;
hits.h[1].push_back(can);
}
}
else
{
Float_t avg_t = (can_strips[m1][h1].first+can_strips[m2][h2].first)/2.;
Float_t avg_c = (can_strips[m1][h1].second.second+can_strips[m2][h2].second.second)/2.;
HitCanData can;
can.radtimecharge = radius;
can.posX = can_strips[m1][h1].second.first;
can.timeX = can_strips[m1][h1].first;
can.chargeX = can_strips[m1][h1].second.second;
can.eventnrX = h1;
can.posY = can_strips[m2][h2].second.first;
can.timeY = can_strips[m2][h2].first;
can.chargeY = can_strips[m2][h2].second.second;
can.eventnrY = h2;
can.timeavg = avg_t;
can.chargeavg = avg_c;
hits.h[1].push_back(can);
}
}
}
}
}
}
}
std::sort(hits.h[1].begin(), hits.h[1].end(), HPionTrackerHitF::sortfunction);
std::sort(hits.h[0].begin(), hits.h[0].end(), HPionTrackerHitF::sortfunction);
for (Int_t p = 0; p < 2; ++p)
{
for (UInt_t h1 = 0; h1 < hits.h[p].size(); ++h1)
{
if (hits.h[p][h1].chargeX == HPionTrackerCal::InvalidAdc())
continue;
int eventnrX_ref = hits.h[p][h1].eventnrX;
int eventnrY_ref = hits.h[p][h1].eventnrY;
for (UInt_t h2 = h1+1; h2 < hits.h[p].size(); ++h2)
{
int eventnrX = hits.h[p][h2].eventnrX;
int eventnrY = hits.h[p][h2].eventnrY;
if (eventnrX_ref == eventnrX or eventnrY_ref == eventnrY)
{
hits.h[p].erase(hits.h[p].begin()+h2);
--h2;
}
}
}
}
for (Int_t p = 0; p < pHitfpar->getNumPlanes(); ++p)
{
Int_t planeX, planeY;
pHitfpar->getPlanePair(p, planeX, planeY);
HPionTrackerDetGeomPar * dgeo = pGeompar->getDetector(p);
HGeomTransform gt = dgeo->getLabTransform();
Int_t plane_hit_cnt = 0;
loc[0] = p;
for (size_t i = 0; i < hits.h[p].size(); ++i)
{
loc[1] = plane_hit_cnt++;
pHit = (HPionTrackerHit*)pHitCat->getObject(loc);
if (!pHit)
{
pHit = (HPionTrackerHit *)pHitCat->getSlot(loc);
if (pHit)
{
pHit = new(pHit) HPionTrackerHit;
pHit->setPlaneHit(p, loc[1]);
pHit->setTimeAndCharge(hits.h[p][i].timeX, hits.h[p][i].chargeX, hits.h[p][i].timeY, hits.h[p][i].chargeY);
pHit->setLocalPos(hits.h[p][i].posX, hits.h[p][i].posY);
HGeomVector v1(
dgeo->getStripPos(hits.h[p][i].posX),
dgeo->getStripPos(hits.h[p][i].posY),
0);
HGeomVector v2 = gt.getTransVector() + gt.getRotMatrix() * v1;
pHit->setLabPos(v2.getX(), v2.getY(), v2.getZ());
}
else
{
Error("execute()", "Can't get slot plane=%i, cnt=%i for hit %lu",
loc[0], loc[1], i+1);
return 0;
}
}
else
{
Error("execute()", "Slot already exists for plane=%i, cnt=%i", loc[0], loc[1]);
return -1;
}
}
}
return 0;
}