#include "SabreDetector.h" #include #include using namespace std; /* Distances in meters, angles in radians. The channel arrays have four points, one for each corner. The corners are as follows, as if looking BACK along beam (i.e. from the target's pov): 0---------------------1 | | | | y | | ^ | | | | | | 3---------------------2 -----> x (z is hence positive along beam direction) The channel numbers, also as looking back from target pov, are: >> rings are 0 -- 15 from inner to outer: 15 ------------------- 14 ------------------- 13 ------------------- . . . 2 ------------------- 1 ------------------- 0 ------------------- >> wedges are 0 -- 7 moving counterclockwise: 7 6 ... 1 0 | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | ***note that these are for ARRAY storage, and may not necessarily correspond to the PHYSICAL channels; this will need to be taken into account if used in actual data analysis -- kgh, March 2020 */ SabreDetGeometry::SabreDetGeometry(double iRinner_flat, double iRouter_flat, double ideltaPhi_flat, double ibeamPhi_central, double itiltFromVertical, double idistFromTarget, double xoffset, double yoffset) : NUMRINGS(16), NUMWEDGES(8) { rbc = 0; //ring bottom channel rtc = NUMRINGS-1; //ring top channel wrc = 0; //wedge right channel wlc = NUMWEDGES-1; //wedge left channel Rinner_flat = iRinner_flat; Router_flat = iRouter_flat; deltaR_flat = iRouter_flat - iRinner_flat; deltaR_flat_ring = deltaR_flat/NUMRINGS; deltaPhi_flat = ideltaPhi_flat; deltaPhi_flat_wedge = deltaPhi_flat/NUMWEDGES; beamPhi_central = ibeamPhi_central; tiltFromVertical = itiltFromVertical; //this distance from target is from the CENTRAL point of //the detector, i.e. the center of the "circle" which the //detector forms. NOTE: these are all assumed to be negative! ZdistFromTarget = idistFromTarget; XdistFromTarget = xoffset; YdistFromTarget = yoffset; random = new TRandom3(); random->SetSeed(); ringch_flat_cart = new CartCoords*[NUMRINGS]; wedgech_flat_cart = new CartCoords*[NUMWEDGES]; ringch_tilted_cart = new CartCoords*[NUMRINGS]; wedgech_tilted_cart = new CartCoords*[NUMWEDGES]; for (int i=0; i= 0 && ich < NUMRINGS) ? true : false); } bool SabreDetGeometry::CheckWedgeChannel(int ich) { return ((ich >= 0 && ich < NUMWEDGES) ? true: false); } bool SabreDetGeometry::CheckCorner(int icn) { return ((icn >= 0 && icn < 4) ? true : false); } bool SabreDetGeometry::CheckBothRing(int ich, int icn) { return (CheckRingChannel(ich)&&CheckCorner(icn)); } bool SabreDetGeometry::CheckBothWedge(int ich, int icn) { return (CheckWedgeChannel(ich)&&CheckCorner(icn)); } /*Method by which the coordinates of a hit in a wedge/ring pixel are calculated. *Currently, takes the center of the pixel as the value of a pixel hit, could be altered *to take a uniformly sampled random point with in the pixel */ CartCoords SabreDetGeometry::GetCoordinates(int ringch, int wedgech) { if(!CheckRingChannel(ringch) || !CheckWedgeChannel(wedgech)) { CartCoords temp; temp.x = 0; temp.y = 0; temp.z = 0; return temp; } //define pixel by its center (half way between top and bottom radius, halfway between left and right phi) //EDIT GWM: July 2020 change to randomize the location within the sabre pixel double rcenter = Rinner_flat + deltaR_flat_ring*(ringch + random->Uniform(0.0, 1.0)); double phi_center = deltaPhi_flat/2.0-(wedgech + random->Uniform(0.0, 1.0))*deltaPhi_flat_wedge; CartCoords PixelCenter; PixelCenter.x = rcenter*sin(phi_center); PixelCenter.y = rcenter*cos(phi_center); PixelCenter.z = 0; //return coords in final orientation return TransformVector(PixelCenter); } CartCoords SabreDetGeometry::TransformVector(CartCoords vector) { CartCoords xrot_vector, xzrot_vector, xzrot_t_vector; std::cout<<"Starting coords -- x: "< phi_min && phi < phi_max) { passed = true; } else { return false; } std::cout<<" passed phi "<Router_flat || xy_radius phi_min && phi_in_detector < phi_max) { wedgechan = i; break; } } if(wedgechan == -1) return temp; CartCoords innerPosition_flat, innerPosition_tilt; CartCoords outerPosition_flat, outerPosition_tilt; double r_inner, r_outer; double theta_min, theta_max; //Since we passed phi, use the phi coordinate to calculate the point at the "top" and //bottom of the detector at the given phi, then transform to the lampshade frame. for(int i=0; i=theta_min) { ringchan = i; break; } } if(ringchan == -1) return temp; return GetCoordinates(ringchan, wedgechan); } //Coordinate functions double CartCoords::GetTheta() { double r = std::sqrt(std::pow(x, 2.) + std::pow(y, 2.) + std::pow(z, 2.)); return std::acos(z/r); } double CartCoords::GetR() { return std::sqrt(std::pow(x, 2.) + std::pow(y, 2.) + std::pow(z, 2.)); } double CartCoords::GetPhi() { /*double r = std::sqrt(std::pow(x, 2.) + std::pow(y, 2.)); if((x >= 0 && y >= 0) || (x <= 0 && y >= 0)) return std::acos(x/r); else if((x <= 0 && y <= 0) || (x >= 0 && y <= 0)) return (2.0*M_PI - std::acos(x/r)); else return 0.0;*/ double phi = std::atan2(y, x); if(phi<0) phi += M_PI*2.0; return phi; } double CartCoords::GetDetectorPhi() { /*double r = std::sqrt(std::pow(x, 2.) + std::pow(y, 2.)); if((x >= 0 && y >= 0) || (x <= 0 && y >= 0)) return std::acos(x/r); else if((x <= 0 && y <= 0) || (x >= 0 && y <= 0)) return (2.0*M_PI - std::acos(x/r)); else return 0.0;*/ double phi = std::atan2(x, y); if(phi<0) phi += M_PI*2.0; return phi; }