#ifndef UTILS_ORR_H #define UTILS_ORR_H #include "datatypes.h" #include "HistPlotter.h" #include "Geometry_orr.h" //contains orruba geometry constants #include #include #include #include #include #include #include //#include #include #include #include #include #include #include #include #include #include "TMath.h" #include "counters.h" static named_counter oc("named orruba counters"); inline float get_filesize(std::string filename) { struct stat st; stat(filename.c_str(), &st); return st.st_size; } class orruba_params { /* * */ public: int chnum=DEFAULT_NULL; //!< global channel number std::string type = "-"; int id=DEFAULT_NULL; int layer=DEFAULT_NULL; int frontback=DEFAULT_NULL; int updown=DEFAULT_NULL; int subid=DEFAULT_NULL; int leftright=DEFAULT_NULL; float ped=DEFAULT_NULL; float offset=DEFAULT_NULL; float gain=DEFAULT_NULL; float gain2=DEFAULT_NULL; //for use with sx3's }; class sx3_geometry_scalefactors { public: //If sx3 has L, R being the left and right extremities, we choose add, stretch here such that // x_mm = (x_raw+add)*stretch; so add=abs(L), stretch=75/(abs(L)+R) float add[4]; float stretch[4]; }; class qqq5_finegains { public: std::array,32> front; //front.at(30).first = slope at clkpos 0, ring 30 for E front layer //front.at(30).second = intercept for the same as above std::array,4> back; }; class sx3_fbgains { public: //Order of indices is [pad][strip] float padoffsets[4][4]; float padgains[4][4]; float stripLoffsets[4][4]; float stripLgains[4][4]; float stripRoffsets[4][4]; float stripRgains[4][4]; }; //Metadata ORRUBA needs to know about itself, to be configured at the start extern std::array o_params; extern std::array sx3_xtalk_gains; //every sx3 needs to be gainmatched as a frontL-back, frontR-back pair (pad strip pair) extern std::array sx3gs; extern std::array qqq5_fg_dE, qqq5_fg_E; class type19Raw { public: long int timestamp; std::vector ch; std::vector val; type19Raw() : timestamp(0), ch(50,0), val(50,0) {} //Reserve 50 for size of these vectors, initial value of zero void print() const { /* print() Prints type19Raw's contents to stdout for monitoring */ std::cout << "------" << std::endl; for(unsigned int ii=0; ii back[4]; std::vector frontL[4]; std::vector frontR[4]; double ts = DEFAULT_NULL; //Easy lookup of final calibrated event. Only filled for valid cases, assumed for now to be 1L, 1R, 1B float frontX=DEFAULT_NULL; float frontXmm=DEFAULT_NULL; float frontE=DEFAULT_NULL; float backE=DEFAULT_NULL; int stripF=DEFAULT_NULL; int stripB=DEFAULT_NULL; float frontEL=DEFAULT_NULL; float frontER=DEFAULT_NULL; float phi=DEFAULT_NULL; // std::set valid_front_chans; std::set valid_back_chans; std::set unmatched_front_chans; //every front channel is unmatched and invalid at first. when it gets matched, it gets removed and sent to valid bool foundevent=false; bool valid=false;//valid will be set to false in all cases where we have ambiguity int flags=-1;//flags settable to different types of values to indicate different invalid situations void fillevent(const std::string& position, const int subchannel, const float value); //make 'const' what functions don't need to change, helps with performance void validate(const sx3_fbgains&, const sx3_geometry_scalefactors&); }; class qqq5 { public: //Holds all information in an event, including ped subtraction+scaling. front[2].at(0) will have the largest energy seen in ch2, if any //TODO: Convert to std::array std::vector back[4]; std::vector front[32]; double ts = DEFAULT_NULL; float selftheta=DEFAULT_NULL,selfrho=DEFAULT_NULL; //Easy lookup of the final calibrated event. Only filled for valid cases. double frontE=DEFAULT_NULL; double backE=DEFAULT_NULL; int frontch; int backch; std::pair adj_front_strips = {-1,-1}; std::pair adj_back_strips = {-1,-1}; std::set valid_front_chans; //list of channels that fire. can inspect size() of these to see if there are front/back events std::set valid_back_chans; // we use std::set since it makes for very readable code bool foundevent=false; bool valid=false; //valid will be set to false in all cases where we have ambiguity int flags=-1; //flags settable to different types of values to indicate different invalid situations void fillevent(const std::string& position, const int subchannel, const float value); //make 'const' what functions don't need to change, helps with performance void validate(); }; struct orrubaevent { //Every clean, valid charged-particle event will have these four parts float dE=DEFAULT_NULL; //!< true energy-loss in the dE layer. Found by gainmatching ADC readout to alpha data float E=DEFAULT_NULL; //!< energy deposited in the E layer. When summed with dE, gives true energy in keV deposited by the particle in ORRUBA float dE_PID = DEFAULT_NULL; //!< dE scaled for dE-layer's thickness, reducing the spread due to angular straggling by explicitly accounting for it. This will give a sharper pid plot that can be gated on better float dE_linPID = DEFAULT_NULL; //!< dE_PID, but linearized using the prescription described in, say, PhysRevC.90.034601 (2014). dE_linPID = ((dE+E)^a-E^a)^(1/a) where a ~ 1.68 is chosen empirically float Theta=DEFAULT_NULL; //!< Laboratory polar angle of event in radians, deprecated float Phi=DEFAULT_NULL; //!< Lab azimuthal angle of event in radians, deprecated //Helpful indices to make dE-E plots std::string type; //!< "endcap" vs "barrel" //!< Identify the position of the detector in the barrel, usually in accordance with the channel map: say we might learn detector is at "Quad 4" or "clk_pos 10", together with 'type'. Useful with HistPlotter class int position=DEFAULT_NULL; int subchdE_1=DEFAULT_NULL, subchdE_2=DEFAULT_NULL; //!< Identify the subchannels corresponding to the two sides of the dE detector. To avoid confusion, 1=strip(sx3), ring(qqq) and 2=pad(sx3), wedge(qqq) int subchE_1=DEFAULT_NULL, subchE_2=DEFAULT_NULL; //!< Identify the subchannels corresponding to the two sides of the E detector. Same convention as above float x=DEFAULT_NULL,y=DEFAULT_NULL,z=DEFAULT_NULL; //!< Laboratory x,y,z coordinates of the event from the E layer float r0=DEFAULT_NULL,theta0=DEFAULT_NULL,phi0=DEFAULT_NULL; //!< vector elements from hit to origin for E layer float r1=DEFAULT_NULL,theta1=DEFAULT_NULL,phi1=DEFAULT_NULL; //!< vector elements from hit to origin for dE layer }; /*TODO: * There will be some use for a class such that it stores PhysicsEvent = * Once the 'orrubaevent' structs are made, it should be callable. like std::vector getPhysicsFromVertices(Kinematics dpkin, std::vector orvec);? * should the physics just go sit in orrubaevent? maybe orruba2024 class can have a kinematics object in it? */ class orruba2024 { private: //Class expected to be changed for each version of the analysis code public: bool found_trk, found_trkpresc, found_tdcq, found_s800e1, found_s800trg, found_rf, found_gt, found_si, found_siup; bool found_de, found_e, found_qqq, found_sx3;//orruba long long timestamp=DEFAULT_NULL; std::vector o_rawvec; std::array uendcapE; std::array uendcapdE; std::array ubarrelE; std::array ubarreldE; std::array dbarrelE; //Results after post-processing, including possible multiplicities std::vector events; double target_z_offset; //void initialize(const std::string & filename1, const std::string& filename2, const std::string& filename3); float tdc_trk = DEFAULT_NULL; float tdc_trksi = DEFAULT_NULL; //trackerpr+si stops are combined into one channel float tdc_trkp = DEFAULT_NULL; float tdc_q = DEFAULT_NULL; float tdc_s800e1 = DEFAULT_NULL; float tdc_s800trg = DEFAULT_NULL; float tdc_rf = DEFAULT_NULL; float tdc_rf_unwrap = DEFAULT_NULL; float tdc_gt = DEFAULT_NULL; float tdc_si = DEFAULT_NULL; float tdc_siup = DEFAULT_NULL; orruba2024(const std::vector& orvec); void postprocess(); //generates 'events', and performs validations on freshly entered data. performs fine gainmatching for front-back-pairs void print() const { std::cout << Form("TDCs\n trk:%1.4f\ntrkp:%1.4f\nq:%1.4f\ns800e1:%1.4f\ns800trg:%1.4f\nrf:%1.4f\nrfuw:%1.4f\ngt:%1.4f\nsi:%1.4f\nsiup:%1.4f\n-----\nevents_size:%lu\ntimestamp:%lld\nfound_de:%d, found_e:%d\n-------\n-------\n", tdc_trk, tdc_trkp, tdc_q, tdc_s800e1, tdc_s800trg, tdc_rf, tdc_rf_unwrap, tdc_gt, tdc_si, tdc_siup, events.size(), timestamp, found_de, found_e) << std::endl; } }; class trackingdet { public: double timestamp=DEFAULT_NULL; //TODO: Convert all to std::array std::vector xwires[MAXNWIRES_TRACK]; std::vector ywires[MAXNWIRES_TRACK]; std::vector xwiresf[MAXNWIRES_TRACK]; std::vector ywiresf[MAXNWIRES_TRACK]; std::vector xwiresf_nn[MAXNWIRES_TRACK]; std::vector ywiresf_nn[MAXNWIRES_TRACK]; std::vector xtimes[MAXNWIRES_TRACK]; std::vector ytimes[MAXNWIRES_TRACK]; std::vector xtimesf[MAXNWIRES_TRACK]; std::vector ytimesf[MAXNWIRES_TRACK]; std::vector cathode; int multx; //how many x-wires fired? int multy; //how many y-wires fired? int multxf; //how many filtered x-wires fired? int multyf; //how many filtered y-wires fired? int multxt; //how many x-tdcwires fired? int multyt; //how many y-tdcwires fired? int multxtf; //how many x-tdcwires fired in window? int multytf; //how many y-tdcwires fired in window? float tot_cathode=0; float tot_x=0; float tot_y=0; float tot_anode=0; //list of x and y wires fired above energy threshold, within timing gate window std::set list_ywires; std::set list_xwires; std::set list_ytwires; std::set list_xtwires; //position of the vertex estimated by up to 2 neighbouring wires firing together within window double xpos=DEFAULT_NULL; double ypos=DEFAULT_NULL; bool clean_event = false; int maxnx=-124, maxny=-124; int nnx = 0; //nearest neighbour x wires set this to +/- 1 if present w.r.t. wire maxnx int nny = 0; //nearest neighbour y wires set this to +/- 1 if present w.r.t wire maxny bool clean_event_no_timing = false; bool clean_single_xy_event = false; bool clean_single_xy_event_no_timing = false; void Reset() { /*** Resets all data members. **/ cathode.clear(); for(int i=0; i& orvec); }; const float alpha = 0.0; int matchchantype(unsigned short chan, const std::array& index, const std::string& label); void initialize_orruba(const std::string & filename1, const std::string& filename2, const std::string& filename3, const std::string& filename4);//, int parse_orruba_data(const unsigned short* buffer, int32_t length, type19Raw& oraw_event); #endif