2024-02-02 15:08:50 -05:00
|
|
|
#ifndef ClassSX3_h
|
|
|
|
#define ClassSX3_h
|
|
|
|
|
|
|
|
#include <cstdio>
|
|
|
|
#include <TMath.h>
|
|
|
|
#include <TVector3.h>
|
2024-04-15 13:29:57 -04:00
|
|
|
#include <TRandom.h>
|
2024-02-02 15:08:50 -05:00
|
|
|
|
|
|
|
class SX3{
|
|
|
|
public:
|
2024-02-02 15:40:43 -05:00
|
|
|
SX3(){Clear();};
|
2024-02-02 15:08:50 -05:00
|
|
|
~SX3(){}
|
|
|
|
|
|
|
|
short GetID() const {return id;}
|
|
|
|
short GetChUp() const {return chUp;}
|
|
|
|
short GetChDn() const {return chDn;}
|
|
|
|
short GetChBk() const {return chBk;}
|
|
|
|
|
|
|
|
TVector3 GetHitPos() const {return hitPos;}
|
2024-02-02 19:13:28 -05:00
|
|
|
TVector3 GetHitPosWithSigma(double sigmaY_mm, double sigmaZ_mm);
|
2024-02-02 15:08:50 -05:00
|
|
|
|
|
|
|
double GetZFrac() const {return zFrac;} // range from -0.5 to 0.5
|
|
|
|
|
|
|
|
void Clear();
|
|
|
|
void ConstructGeo();
|
|
|
|
void FindSX3Pos(TVector3 pos, TVector3 direction, bool verbose = false);
|
|
|
|
void CalSX3Pos(unsigned short ID, unsigned short chUp, unsigned short chDown, unsigned short chBack, float eUp, float eDown);
|
|
|
|
|
2024-02-02 15:40:43 -05:00
|
|
|
double GetNumDet() const {return numDet;}
|
|
|
|
double GetWidth() const {return width;}
|
|
|
|
double GetLength() const {return length;}
|
2024-02-02 15:08:50 -05:00
|
|
|
TVector3 GetDnL(short id) const {return SDn[id].first; } // lower strip ID
|
|
|
|
TVector3 GetDnH(short id) const {return SDn[id].second; } // higher strip ID
|
|
|
|
TVector3 GetUpL(short id) const {return SUp[id].first; } // lower strip ID
|
|
|
|
TVector3 GetUpH(short id) const {return SUp[id].second; } // higher strip ID
|
|
|
|
|
|
|
|
TVector3 GetDnMid(short id) const { return (SDn[id].first + SDn[id].second)*0.5;}
|
|
|
|
TVector3 GetUpMid(short id) const { return (SUp[id].first + SUp[id].second)*0.5;}
|
|
|
|
|
|
|
|
double GetDetPhi(short id) const { return (SUp[id].second - SUp[id].first).Phi();}
|
|
|
|
|
|
|
|
void Print(){
|
|
|
|
if( id == -1 ){
|
|
|
|
printf("Did not hit any SX3.\n");
|
|
|
|
}else{
|
|
|
|
printf("ID: %d, U,D,B: %d %d %d| zFrac : %.2f\n", id, chUp, chDn, chBk, zFrac);
|
|
|
|
printf("Hit Pos: %.2f, %.2f, %.2f\n", hitPos.X(), hitPos.Y(), hitPos.Z());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// void CalZFrac(){
|
|
|
|
// zFrac = (eUp - eDn)/(eUp + eDn);
|
|
|
|
// }
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
2024-02-02 15:40:43 -05:00
|
|
|
const int numDet = 12;
|
|
|
|
const float radius = 88;
|
|
|
|
const float width = 40;
|
|
|
|
const float length = 75;
|
|
|
|
const float gap = 46;
|
|
|
|
|
2024-02-02 15:08:50 -05:00
|
|
|
short id; // -1 when no hit
|
|
|
|
short chUp;
|
|
|
|
short chDn;
|
|
|
|
short chBk;
|
|
|
|
|
|
|
|
double zFrac; // from +1 (downstream) to -1 (upstream)
|
|
|
|
|
|
|
|
double eUp;
|
|
|
|
double eDn;
|
|
|
|
double eBk;
|
|
|
|
|
|
|
|
TVector3 hitPos;
|
|
|
|
|
|
|
|
std::vector<std::pair<TVector3,TVector3>> SDn; // coners of the SX3 0-11, z = mid point
|
|
|
|
std::vector<std::pair<TVector3,TVector3>> SUp; // coners of the SX3 12-23, z = mid point
|
|
|
|
std::vector<TVector3> SNorml; // normal of the SX3 (outward)
|
|
|
|
|
|
|
|
|
|
|
|
std::pair<double, double> Intersect(TVector3 p1, TVector3 p2, TVector3 q1, TVector3 q2, bool verbose){
|
|
|
|
|
|
|
|
//see https://nukephysik101.wordpress.com/2023/12/30/intersect-between-2-line-segments/
|
|
|
|
//zero all z-component
|
|
|
|
TVector3 a0 = p1; a0.SetZ(0);
|
|
|
|
TVector3 a1 = p2; a1.SetZ(0);
|
|
|
|
|
|
|
|
TVector3 b0 = q1; b0.SetZ(0);
|
|
|
|
TVector3 b1 = q2; b1.SetZ(0);
|
|
|
|
|
|
|
|
double A = ((b0-b1).Cross(a0-a1)).Mag();
|
|
|
|
|
|
|
|
double h = ((b0-a0).Cross(b1-a0)).Z()/ A;
|
|
|
|
double k = ((a1-b0).Cross(a0-b0)).Z()/ A;
|
|
|
|
|
|
|
|
if( verbose ) printf(" ----h, k : %f, %f\n", h, k);
|
|
|
|
|
2024-04-15 13:29:57 -04:00
|
|
|
return std::pair<double,double>(h,k);
|
2024-02-02 15:08:50 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
inline void SX3::Clear(){
|
|
|
|
id = -1;
|
|
|
|
chUp = -1;
|
|
|
|
chDn = -1;
|
|
|
|
chBk = -1;
|
|
|
|
zFrac = TMath::QuietNaN();
|
|
|
|
|
|
|
|
eUp = TMath::QuietNaN();
|
|
|
|
eDn = TMath::QuietNaN();
|
|
|
|
eBk = TMath::QuietNaN();
|
2024-02-02 15:40:43 -05:00
|
|
|
|
|
|
|
SDn.clear();
|
|
|
|
SUp.clear();
|
2024-02-02 15:08:50 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
inline void SX3::ConstructGeo(){
|
|
|
|
TVector3 sa, sb, sc, sn;
|
|
|
|
|
2024-02-02 15:40:43 -05:00
|
|
|
for(int i = 0; i < numDet; i++){
|
|
|
|
sa.SetXYZ( radius, -width/2, gap/2 + length/2 );
|
|
|
|
sb.SetXYZ( radius, width/2, gap/2 + length/2 );
|
|
|
|
|
2024-02-09 14:27:59 -05:00
|
|
|
double rot = TMath::TwoPi() / numDet * (i - 0.5) - TMath::PiOver2();
|
2024-02-02 15:08:50 -05:00
|
|
|
|
|
|
|
sa.RotateZ( rot );
|
|
|
|
sb.RotateZ( rot );
|
2024-04-15 13:29:57 -04:00
|
|
|
SDn.push_back(std::pair<TVector3,TVector3>(sa,sb));
|
2024-02-02 15:08:50 -05:00
|
|
|
|
2024-02-02 15:40:43 -05:00
|
|
|
sc.SetXYZ( radius, -width/2, gap/2 );
|
2024-02-02 15:08:50 -05:00
|
|
|
sc.RotateZ( rot );
|
|
|
|
|
|
|
|
sn = ((sc-sa).Cross(sb-sa)).Unit();
|
|
|
|
SNorml.push_back(sn);
|
|
|
|
|
2024-02-02 15:40:43 -05:00
|
|
|
sa.SetXYZ( radius, -width/2, -gap/2 - length/2 );
|
|
|
|
sb.SetXYZ( radius, width/2, -gap/2 - length/2 );
|
2024-02-02 15:08:50 -05:00
|
|
|
|
|
|
|
sa.RotateZ( rot );
|
|
|
|
sb.RotateZ( rot );
|
2024-04-15 13:29:57 -04:00
|
|
|
SUp.push_back(std::pair<TVector3,TVector3>(sa,sb));
|
2024-02-02 15:08:50 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
inline void SX3::FindSX3Pos(TVector3 pos, TVector3 direction, bool verbose){
|
|
|
|
|
|
|
|
id = -1;
|
2024-02-02 15:40:43 -05:00
|
|
|
for( int i = 0 ; i < numDet; i++){
|
2024-02-02 15:08:50 -05:00
|
|
|
|
|
|
|
if(verbose) printf(" %d ", i);
|
|
|
|
std::pair<double, double> frac = Intersect( pos, pos + direction, SDn[i].first, SDn[i].second, verbose);
|
|
|
|
|
|
|
|
|
|
|
|
if( frac.second < 0 || frac.second > 1 ) continue;
|
|
|
|
hitPos = pos + frac.first * direction;
|
|
|
|
|
|
|
|
double dis = hitPos.Dot(SNorml[i]);
|
|
|
|
|
|
|
|
if(verbose) {
|
|
|
|
printf("reduced distance : %f\n", dis);
|
2024-02-02 15:40:43 -05:00
|
|
|
printf(" %d*", (i+1)%numDet);
|
|
|
|
Intersect( pos, pos + direction, SDn[(i+1)%numDet].first, SDn[(i+1)%numDet].second, verbose);
|
2024-02-02 15:08:50 -05:00
|
|
|
}
|
|
|
|
|
2024-02-02 15:40:43 -05:00
|
|
|
if( TMath::Abs(dis - radius) > 0.1 ) continue;
|
2024-02-02 15:08:50 -05:00
|
|
|
|
|
|
|
chDn = 2 * TMath::Floor(frac.second * 4);
|
|
|
|
chUp = chDn + 1;
|
|
|
|
|
|
|
|
double zPos = hitPos.Z();
|
2024-02-02 15:40:43 -05:00
|
|
|
if( (gap/2 < zPos && zPos < gap/2 + length ) || (-gap/2 - length < zPos && zPos < -gap/2 ) ){
|
2024-02-02 15:08:50 -05:00
|
|
|
|
|
|
|
id = zPos > 0 ? i : i + 12;
|
|
|
|
|
2024-02-02 15:40:43 -05:00
|
|
|
zFrac = zPos > 0 ? (zPos - gap/2. - length/2.)/length : (zPos - ( - gap/2. - length/2.) )/length ;
|
2024-02-02 15:08:50 -05:00
|
|
|
|
|
|
|
chBk = TMath::Floor( (zFrac + 0.5) * 4 ) + 8;
|
|
|
|
|
|
|
|
if( verbose) Print();
|
|
|
|
return ;
|
|
|
|
|
|
|
|
}else{
|
|
|
|
if( verbose ) printf(" zPos out of sensitive region\n");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if( verbose) Print();
|
|
|
|
}
|
|
|
|
|
2024-02-02 19:13:28 -05:00
|
|
|
inline TVector3 SX3::GetHitPosWithSigma(double sigmaY_mm, double sigmaZ_mm){
|
|
|
|
|
2024-02-05 16:44:44 -05:00
|
|
|
double phi = SNorml[id%numDet].Phi();
|
2024-02-02 19:13:28 -05:00
|
|
|
|
|
|
|
TVector3 haha = hitPos;
|
|
|
|
haha.RotateZ(-phi);
|
2024-02-05 16:44:44 -05:00
|
|
|
|
2024-02-02 19:13:28 -05:00
|
|
|
double y = haha.Y() + gRandom->Gaus(0, sigmaY_mm);
|
2024-02-05 16:44:44 -05:00
|
|
|
if( sigmaY_mm < 0 ){
|
|
|
|
double deltaW = width/4;
|
|
|
|
y = TMath::Floor((haha.Y()-deltaW)/deltaW)*deltaW + deltaW*1.5; // when ever land on each strip, set the position to be center of the strip.
|
|
|
|
if( y >= 25 ) y = 15;
|
|
|
|
}
|
|
|
|
|
2024-02-02 19:13:28 -05:00
|
|
|
double z = haha.Z() + gRandom->Gaus(0, sigmaZ_mm);
|
2024-02-05 16:44:44 -05:00
|
|
|
if( sigmaZ_mm < 0 ){
|
|
|
|
haha.Z();
|
|
|
|
double delta = length/4;
|
|
|
|
int sign = z > 0 ? 1 : -1;
|
|
|
|
z = TMath::Floor( (abs(z)-gap/2)/delta )*delta + 0.5 * delta + gap/2;
|
|
|
|
if( z >= 107.375 ) z = 88.625;
|
|
|
|
z = sign * z;
|
|
|
|
}
|
2024-02-02 19:13:28 -05:00
|
|
|
|
|
|
|
haha.SetY(y);
|
|
|
|
haha.SetZ(z);
|
|
|
|
haha.RotateZ(phi);
|
|
|
|
|
|
|
|
return haha;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2024-02-02 15:08:50 -05:00
|
|
|
|
|
|
|
inline void SX3::CalSX3Pos(unsigned short ID, unsigned short chUp, unsigned short chDown, unsigned short chBack, float eUp, float eDown){
|
|
|
|
|
|
|
|
hitPos.Clear();
|
|
|
|
|
2024-04-15 13:29:57 -04:00
|
|
|
|
2024-02-02 15:08:50 -05:00
|
|
|
if( (chUp - chDown) != 1 || (chDown % 2) != 0) return ;
|
|
|
|
|
2024-02-02 15:40:43 -05:00
|
|
|
int reducedID = ID % numDet;
|
2024-02-02 15:08:50 -05:00
|
|
|
|
|
|
|
TVector3 sa, sb;
|
|
|
|
|
2024-02-02 15:40:43 -05:00
|
|
|
if( ID < numDet ){ //down
|
2024-02-02 15:08:50 -05:00
|
|
|
sa = SDn[reducedID].second;
|
|
|
|
sb = SDn[reducedID].first;
|
|
|
|
}else{
|
|
|
|
sa = SUp[reducedID].second;
|
|
|
|
sb = SUp[reducedID].first;
|
|
|
|
}
|
|
|
|
|
|
|
|
hitPos.SetX( (sb.X() - sa.X()) * chUp/8 + sa.X());
|
|
|
|
hitPos.SetY( (sb.Y() - sa.Y()) * chUp/8 + sa.Y());
|
|
|
|
|
|
|
|
if( eUp == 0 || eDown == 0 ){
|
2024-02-02 15:40:43 -05:00
|
|
|
hitPos.SetZ( sa.Z() + (2*(chBk - 7)-1) * length / 8 );
|
2024-02-02 15:08:50 -05:00
|
|
|
}else{
|
|
|
|
double frac = (eUp - eDown)/(eUp + eDown); // from +1 (downstream) to -1 (upstream)
|
2024-02-02 15:40:43 -05:00
|
|
|
double zPos = sa.Z() + length * frac/2;
|
2024-02-02 15:08:50 -05:00
|
|
|
hitPos.SetZ( zPos );
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
#endif
|