00001
00002
00003
00004
00005
00006
00007
00009
00010 #include "GeometryUtilities.hh"
00011
00012 namespace larutil{
00013
00014 GeometryUtilities* GeometryUtilities::_me = 0;
00015
00016
00017 GeometryUtilities::GeometryUtilities()
00018 {
00019 _name = "GeometryUtilities";
00020
00021 Reconfigure();
00022 }
00023
00024 void GeometryUtilities::Reconfigure()
00025 {
00026 geom = (larutil::Geometry*)(larutil::Geometry::GetME());
00027 detp = (larutil::DetectorProperties*)(larutil::DetectorProperties::GetME());
00028 larp = (larutil::LArProperties*)(larutil::LArProperties::GetME());
00029
00030 fNPlanes = geom->Nplanes();
00031 vertangle.resize(fNPlanes);
00032 for(UInt_t ip=0;ip<fNPlanes;ip++)
00033 vertangle[ip]=geom->WireAngleToVertical(geom->PlaneToView(ip)) - TMath::Pi()/2;
00034
00035 fWirePitch = geom->WirePitch(0,1,0);
00036 fTimeTick=detp->SamplingRate()/1000.;
00037 fDriftVelocity=larp->DriftVelocity(larp->Efield(),larp->Temperature());
00038
00039 fWiretoCm=fWirePitch;
00040 fTimetoCm=fTimeTick*fDriftVelocity;
00041 fWireTimetoCmCm=fTimetoCm/fWirePitch;
00042 }
00043
00044
00045 GeometryUtilities::~GeometryUtilities()
00046 {
00047
00048 }
00049
00050
00051
00052
00053
00054
00055
00056
00058 Int_t GeometryUtilities::Get3DaxisN(Int_t iplane0,
00059 Int_t iplane1,
00060 Double_t omega0,
00061 Double_t omega1,
00062 Double_t &phi,
00063 Double_t &theta) const
00064 {
00065
00066 Double_t l(0),m(0),n(0);
00067 Double_t ln(0),mn(0),nn(0);
00068 Double_t phis(0),thetan(0);
00069
00070
00071
00072
00073 UInt_t Cplane=0,Iplane=1;
00074
00075 Double_t angleC,angleI,slopeC,slopeI,omegaC,omegaI;
00076 omegaC = larlight::DATA::INVALID_DOUBLE;
00077 omegaI = larlight::DATA::INVALID_DOUBLE;
00078
00079
00080 if(omega0==0 || omega1==0){
00081 phi=0;
00082 theta=-999;
00083 return -1;
00084 }
00085
00086
00088
00089
00090 Double_t backwards=0;
00091
00092 Double_t alt_backwards=0;
00093
00095 if(fabs(omega0)>(TMath::Pi()/2.0) && fabs(omega1)>(TMath::Pi()/2.0) ) {
00096 backwards=1;
00097 }
00098
00099 if(fabs(omega0)>(TMath::Pi()/2.0) || fabs(omega1)>(TMath::Pi()/2.0) ) {
00100 alt_backwards=1;
00101 }
00102
00103
00104
00105
00106 if(vertangle[iplane0] == 0){
00107
00108 Cplane=iplane0;
00109 Iplane=iplane1;
00110 omegaC=omega0;
00111 omegaI=omega1;
00112 }
00113 else if(vertangle[iplane1] == 0){
00114
00115 Cplane = iplane1;
00116 Iplane = iplane0;
00117 omegaC=omega1;
00118 omegaI=omega0;
00119 }
00120 else if(vertangle[iplane0] != 0 && vertangle[iplane1] != 0){
00121
00122 if(vertangle[iplane1] < vertangle[iplane0]){
00123 Cplane = iplane1;
00124 Iplane = iplane0;
00125 omegaC=omega1;
00126 omegaI=omega0;
00127 }
00128 else if(vertangle[iplane1] > vertangle[iplane0]){
00129 Cplane = iplane0;
00130 Iplane = iplane1;
00131 omegaC=omega0;
00132 omegaI=omega1;
00133 }
00134 else{
00135
00136 return -1;
00137 }
00138
00139 }
00140 slopeC=tan(omegaC);
00141 slopeI=tan(omegaI);
00142
00143
00144 angleC=vertangle[Cplane];
00145 angleI=vertangle[Iplane];
00146
00147
00148 bool nfact = !(vertangle[Cplane]);
00149
00150
00151
00152 if(omegaC < TMath::Pi() && omegaC > 0 )
00153 ln=1;
00154 else
00155 ln=-1;
00156
00157
00158 slopeI=tan(omegaI);
00159
00160
00161
00162 l = 1;
00163
00164
00165 m = (1/(2*sin(angleI)))*((cos(angleI)/(slopeC*cos(angleC)))-(1/slopeI)
00166 +nfact*( cos(angleI)/slopeC-1/slopeI ) );
00167
00168 n = (1/(2*cos(angleC)))*((1/slopeC)+(1/slopeI) +nfact*((1/slopeC)-(1/slopeI)));
00169
00170 mn = (ln/(2*sin(angleI)))*((cos(angleI)/(slopeC*cos(angleC)))-(1/slopeI)
00171 +nfact*( cos(angleI)/(cos(angleC)*slopeC)-1/slopeI ) );
00172
00173 nn = (ln/(2*cos(angleC)))*((1/slopeC)+(1/slopeI) +nfact*((1/slopeC)-(1/slopeI)));
00174
00175
00176 float Phi;
00177 float alt_Phi;
00178
00179 if(fabs(angleC)>0.01)
00180 {
00181 phi=atan(n/l);
00182
00183 phis=asin(ln/TMath::Sqrt(ln*ln+nn*nn));
00184
00185 if(fabs(slopeC+slopeI) < 0.001)
00186 phis=0;
00187 else if(fabs(omegaI)>0.01 && (omegaI/fabs(omegaI) == -omegaC/fabs(omegaC) ) && ( fabs(omegaC) < 20*TMath::Pi()/180 || fabs(omegaC) > 160*TMath::Pi()/180 ) )
00188 {phis = (fabs(omegaC) > TMath::Pi()/2) ? TMath::Pi() : 0;
00189
00190 }
00191
00192
00193
00194 if(nn<0 && phis>0 && !(!alt_backwards && fabs(phis)<TMath::Pi()/4 ) )
00195 phis=(TMath::Pi())-phis;
00196 else if(nn<0 && phis<0 && !(!alt_backwards && fabs(phis)<TMath::Pi()/4 ) )
00197 phis=(-TMath::Pi())-phis;
00198
00199
00200
00201 Phi = phi > 0. ? (TMath::Pi()/2)-phi : fabs(phi)-(TMath::Pi()/2) ;
00202 alt_Phi = phi > 0. ? (TMath::Pi()/2)-phi : fabs(phi)-(TMath::Pi()/2) ;
00203
00204 if(backwards==1){
00205 if(Phi<0){ Phi=Phi+TMath::Pi();}
00206 else if(Phi>0){Phi=Phi-TMath::Pi();}
00207 }
00208
00209 bool alt_condition=( ( fabs(omegaC)>0.75*TMath::Pi() && fabs(omegaI)>0.166*TMath::Pi() )|| ( fabs(omegaI)>0.75*TMath::Pi() && fabs(omegaC)>0.166*TMath::Pi() ) );
00210
00211
00212 if((alt_backwards==1 && alt_condition) || backwards==1 ){
00213 if(alt_Phi<0){alt_Phi=alt_Phi+TMath::Pi();}
00214 else if(alt_Phi>0){alt_Phi=alt_Phi-TMath::Pi();}
00215 }
00216
00217 }
00218 else
00219 {phi=omegaC;
00220 Phi=omegaC;
00221 phis=omegaC;
00222 alt_Phi=omegaC;
00223 }
00224
00225
00226 theta = acos( m / (sqrt(pow(l,2)+pow(m,2)+pow(n,2)) ) ) ;
00227 thetan = -asin ( mn / (sqrt(pow(l,2)+pow(mn,2)+pow(nn,2)) ) ) ;
00228
00229
00230
00231
00232
00233
00234
00235
00236
00237
00238
00239
00240
00242
00243
00244
00245
00246 phi=phis*180/TMath::Pi();
00247 theta=thetan*180/TMath::Pi();
00248
00249
00250 return 0; }
00251
00253
00254
00256 Double_t GeometryUtilities::Get3DSpecialCaseTheta(Int_t iplane0,
00257 Int_t iplane1,
00258 Double_t dw0,
00259 Double_t dw1) const
00260 {
00261
00262 Double_t splane,lplane;
00263 Double_t sdw,ldw;
00264
00265 if(dw0==0 && dw1==0)
00266 return -1;
00267
00268 if(dw0 >= dw1 ) {
00269 lplane=iplane0;
00270 splane=iplane1;
00271 ldw=dw0;
00272 sdw=dw1;
00273 }
00274 else {
00275 lplane=iplane1;
00276 splane=iplane0;
00277 ldw=dw1;
00278 sdw=dw0;
00279 }
00280
00281 Double_t top=(std::cos(vertangle[splane])-std::cos(vertangle[lplane])*sdw/ldw);
00282 Double_t bottom = tan(vertangle[lplane]*std::cos(vertangle[splane]) );
00283 bottom -= tan(vertangle[splane]*std::cos(vertangle[lplane]) )*sdw/ldw;
00284
00285 Double_t tantheta=top/bottom;
00286
00287 return atan(tantheta)*vertangle[lplane]/std::abs(vertangle[lplane])*180./TMath::Pi();
00288 }
00289
00291
00292
00294 Double_t GeometryUtilities::CalculatePitch(UInt_t iplane,
00295 Double_t phi,
00296 Double_t theta) const
00297 {
00298
00299 Double_t pitch = -1.;
00300
00301 if(geom->PlaneToView(iplane) == larlight::GEO::kUnknown ||
00302 geom->PlaneToView(iplane) == larlight::GEO::k3D){
00303 print(larlight::MSG::ERROR,__FUNCTION__,
00304 Form("Warning : no Pitch foreseen for view %d", geom->PlaneToView(iplane)));
00305 return pitch;
00306 }
00307 else{
00308
00309 Double_t pi=TMath::Pi();
00310
00311 Double_t fTheta=pi/2-theta;
00312
00313 Double_t fPhi=-(phi+pi/2);
00314
00315
00316
00317
00318
00319
00320
00321
00322 for(UInt_t i = 0; i < geom->Nplanes(); ++i) {
00323 if(i == iplane){
00324 Double_t wirePitch = geom->WirePitch(0,1,i);
00325 Double_t angleToVert =0.5*TMath::Pi() - geom->WireAngleToVertical(geom->PlaneToView(i));
00326
00327
00328
00329
00330
00331
00332
00333
00334 Double_t cosgamma = TMath::Abs(TMath::Sin(angleToVert)*TMath::Cos(fTheta)
00335 +TMath::Cos(angleToVert)*TMath::Sin(fTheta)*TMath::Sin(fPhi));
00336
00337 if (cosgamma>0) pitch = wirePitch/cosgamma;
00338 }
00339 }
00340 }
00341
00342 return pitch;
00343 }
00344
00345
00346
00348
00349
00351 Double_t GeometryUtilities::CalculatePitchPolar(UInt_t iplane,
00352 Double_t phi,
00353 Double_t theta) const
00354 {
00355
00356 Double_t pitch = -1.;
00357
00358 if(geom->PlaneToView(iplane) == larlight::GEO::kUnknown ||
00359 geom->PlaneToView(iplane) == larlight::GEO::k3D){
00360 print(larlight::MSG::ERROR,__FUNCTION__,
00361 Form("Warning : no Pitch foreseen for view %d", geom->PlaneToView(iplane)));
00362 return pitch;
00363 }
00364 else{
00365
00366 Double_t fTheta=theta;
00367 Double_t fPhi=phi;
00368
00369
00370
00371
00372
00373
00374 for(UInt_t i = 0; i < geom->Nplanes(); ++i){
00375 if(i == iplane){
00376 Double_t wirePitch = geom->WirePitch(0,1,i);
00377 Double_t angleToVert =0.5*TMath::Pi() - geom->WireAngleToVertical(geom->PlaneToView(i));
00378
00379
00380
00381
00382
00383
00384
00385
00386 Double_t cosgamma = TMath::Abs(TMath::Sin(angleToVert)*TMath::Cos(fTheta)
00387 +TMath::Cos(angleToVert)*TMath::Sin(fTheta)*TMath::Sin(fPhi));
00388
00389 if (cosgamma>0) pitch = wirePitch/cosgamma;
00390 }
00391 }
00392 }
00393
00394 return pitch;
00395 }
00396
00397
00398
00399
00401
00402
00404 Double_t GeometryUtilities::Get2Dslope(Double_t wireend,
00405 Double_t wirestart,
00406 Double_t timeend,
00407 Double_t timestart) const
00408 {
00409
00410 return GeometryUtilities::Get2Dslope((wireend-wirestart)*fWiretoCm,(timeend-timestart)*fTimetoCm);
00411
00412 }
00413
00415
00416
00418 double GeometryUtilities::Get2Dslope(const larutil::PxPoint *endpoint,
00419 const larutil::PxPoint *startpoint) const
00420 {
00421 return Get2Dslope(endpoint->w - startpoint->w,endpoint->t - startpoint->t);
00422
00423 }
00424
00426
00427
00428
00430 Double_t GeometryUtilities::Get2Dslope(Double_t dwire,
00431 Double_t dtime) const
00432 {
00433
00434
00435
00436 return tan(Get2Dangle(dwire,dtime))/fWireTimetoCmCm;
00437
00438 }
00439
00440
00442
00443
00445 Double_t GeometryUtilities::Get2Dangle(Double_t wireend,
00446 Double_t wirestart,
00447 Double_t timeend,
00448 Double_t timestart) const
00449 {
00450
00451 return Get2Dangle((wireend-wirestart)*fWiretoCm,(timeend-timestart)*fTimetoCm);
00452
00453 }
00454
00456
00457
00459 Double_t GeometryUtilities::Get2Dangle(const larutil::PxPoint *endpoint,
00460 const larutil::PxPoint *startpoint) const
00461 {
00462 return Get2Dangle(endpoint->w - startpoint->w, endpoint->t - startpoint->t);
00463
00464 }
00465
00467
00468
00470 Double_t GeometryUtilities::Get2Dangle(Double_t dwire,
00471 Double_t dtime) const
00472 {
00473
00474
00475 Double_t BC,AC;
00476 Double_t omega;
00477
00478 BC = ((Double_t)dwire);
00479 AC = ((Double_t)dtime);
00480 omega = std::asin( AC/std::sqrt(pow(AC,2)+pow(BC,2)) );
00481 if(BC<0)
00482 {
00483 if(AC>0){
00484 omega= TMath::Pi()-std::abs(omega);
00485 }
00486 else if(AC<0){
00487 omega=-TMath::Pi()+std::abs(omega);
00488 }
00489 else {
00490 omega=TMath::Pi();
00491 }
00492 }
00493
00494 return omega;
00495
00496 }
00497
00498
00499
00500
00501 double GeometryUtilities::Get2DangleFrom3D(unsigned int plane,double phi, double theta) const
00502 {
00503 TVector3 dummyvector(cos(theta*TMath::Pi()/180.)*sin(phi*TMath::Pi()/180.) ,sin(theta*TMath::Pi()/180.) , cos(theta*TMath::Pi()/180.)*cos(phi*TMath::Pi()/180.));
00504
00505 return Get2DangleFrom3D(plane,dummyvector);
00506
00507 }
00508
00509
00510
00511
00512
00513 double GeometryUtilities::Get2DangleFrom3D(unsigned int plane,TVector3 dir_vector) const
00514 {
00515 double alpha= 0.5*TMath::Pi()-geom->WireAngleToVertical(geom->PlaneToView(plane));
00516
00517
00518
00519
00520
00521 TVector3 start(geom->DetHalfWidth(),0.,geom->DetLength()/2.);
00522 TVector3 end=start+dir_vector;
00523
00524
00525
00526 larutil::PxPoint startp(plane,(geom->DetHalfHeight()*sin(fabs(alpha))+start[2]*cos(alpha)-start[1]*sin(alpha)),start[0]);
00527
00528 larutil::PxPoint endp(plane,(geom->DetHalfHeight()*sin(fabs(alpha))+end[2]*cos(alpha)-end[1]*sin(alpha)),end[0]);
00529
00530 double angle=Get2Dangle(&endp,&startp);
00531
00532
00533 return angle;
00534
00535 }
00536
00537
00538
00539
00540
00542
00543
00545 Double_t GeometryUtilities::Get2DDistance(Double_t wire1,
00546 Double_t time1,
00547 Double_t wire2,
00548 Double_t time2) const
00549 {
00550
00551 return TMath::Sqrt( pow((wire1-wire2)*fWiretoCm,2)+pow((time1-time2)*fTimetoCm,2) );
00552
00553 }
00554
00555
00556 double GeometryUtilities::Get2DDistance(const larutil::PxPoint *point1,
00557 const larutil::PxPoint *point2) const
00558 {
00559 return TMath::Sqrt( pow((point1->w - point2->w),2)+pow((point1->t - point2->t),2) );
00560 }
00561
00562
00564
00565
00567 Double_t GeometryUtilities::Get2DPitchDistance(Double_t angle,
00568 Double_t inwire,
00569 Double_t wire) const
00570 {
00571 Double_t radangle = TMath::Pi()*angle/180;
00572 if(std::cos(radangle)==0)
00573 return 9999;
00574 return std::abs((wire-inwire)/std::cos(radangle))*fWiretoCm;
00575 }
00576
00577
00578
00579 Double_t GeometryUtilities::Get2DPitchDistanceWSlope(Double_t slope,
00580 Double_t inwire,
00581 Double_t wire) const
00582 {
00583
00584 return std::abs(wire-inwire)*TMath::Sqrt(1+slope*slope)*fWiretoCm;
00585
00586 }
00587
00588
00589
00590
00592
00593
00595 Int_t GeometryUtilities::GetPointOnLine(Double_t slope,
00596 Double_t intercept,
00597 Double_t wire1,
00598 Double_t time1,
00599 Double_t &wireout,
00600 Double_t &timeout) const
00601 {
00602 Double_t invslope=0;
00603
00604 if(slope)
00605 {
00606 invslope=-1./slope;
00607 }
00608
00609 Double_t ort_intercept=time1-invslope*(Double_t)wire1;
00610
00611 if((slope-invslope)!=0)
00612 wireout=(ort_intercept - intercept)/(slope-invslope);
00613 else
00614 wireout=wire1;
00615 timeout=slope*wireout+intercept;
00616
00617 return 0;
00618 }
00619
00621
00622
00624 int GeometryUtilities::GetPointOnLine(Double_t slope,
00625 const larutil::PxPoint *startpoint,
00626 const larutil::PxPoint *point1,
00627 larutil::PxPoint &pointout) const
00628 {
00629
00630 double intercept=startpoint->t - slope * startpoint->w;
00631
00632
00633 return GetPointOnLine(slope,intercept,point1,pointout);
00634
00635 }
00636
00637
00639
00640
00642 int GeometryUtilities::GetPointOnLine(double slope,
00643 double intercept,
00644 const larutil::PxPoint *point1,
00645 larutil::PxPoint &pointout) const
00646 {
00647 double invslope=0;
00648
00649 if(slope)
00650 {
00651
00652 invslope=-1./slope;
00653 }
00654
00655 double ort_intercept=point1->t - invslope * point1->w;
00656
00657 if((slope-invslope)!=0)
00658 pointout.w = (ort_intercept - intercept)/(slope-invslope);
00659 else
00660 pointout.w = point1->w;
00661
00662 pointout.t = slope * pointout.w + intercept;
00663
00664 return 0;
00665 }
00666
00668
00669
00671 Int_t GeometryUtilities::GetPointOnLine(Double_t slope,
00672 Double_t wirestart,
00673 Double_t timestart,
00674 Double_t wire1,
00675 Double_t time1,
00676 Double_t &wireout,
00677 Double_t &timeout) const
00678 {
00679 Double_t intercept=timestart-slope*(Double_t)wirestart;
00680
00681 return GetPointOnLine(slope,intercept,wire1,time1,wireout,timeout);
00682 }
00683
00685
00686
00688 Int_t GeometryUtilities::GetPointOnLineWSlopes(Double_t slope,
00689 Double_t intercept,
00690 Double_t ort_intercept,
00691 Double_t &wireout,
00692 Double_t &timeout) const
00693 {
00694 Double_t invslope=0;
00695
00696 if(slope)
00697 {
00698 invslope=-1./slope;
00699 }
00700
00701 invslope*=fWireTimetoCmCm*fWireTimetoCmCm;
00702
00703 wireout=(ort_intercept - intercept)/(slope-invslope);
00704 timeout=slope*wireout+intercept;
00705
00706
00707 wireout/=fWiretoCm;
00708 timeout/=fTimetoCm;
00709
00710 return 0;
00711 }
00712
00713
00715
00716
00718 Int_t GeometryUtilities::GetPointOnLineWSlopes(double slope,
00719 double intercept,
00720 double ort_intercept,
00721 larutil::PxPoint &pointonline) const
00722 {
00723 Double_t invslope=0;
00724
00725 if(slope)
00726 invslope=-1./slope;
00727
00728
00729
00730
00731 pointonline.w = (ort_intercept - intercept)/(slope-invslope);
00732 pointonline.t = slope * pointonline.w + intercept;
00733 return 0;
00734 }
00735
00736
00737
00739
00740
00742 const larlight::hit* GeometryUtilities::FindClosestHit(const std::vector<larlight::hit*> &hitlist,
00743 UInt_t wirein,
00744 Double_t timein) const
00745 {
00746 return hitlist.at(FindClosestHitIndex(hitlist,wirein,timein));
00747 }
00748
00749
00750
00751
00753 UInt_t GeometryUtilities::FindClosestHitIndex(const std::vector<larlight::hit*> &hitlist,
00754 UInt_t wirein,
00755 Double_t timein) const
00756 {
00757
00758 Double_t min_length_from_start=larlight::DATA::INVALID_DOUBLE;
00759 UInt_t index=larlight::DATA::INVALID_UINT;
00760
00761 UInt_t plane,wire;
00762
00763
00764 for(UInt_t ii=0; ii<hitlist.size();ii++){
00765
00766 Double_t time = hitlist.at(ii)->PeakTime();
00767 GetPlaneAndTPC(hitlist.at(ii),plane,wire);
00768
00769 Double_t dist_mod=Get2DDistance(wirein,timein,wire,time);
00770
00771 if(dist_mod<min_length_from_start){
00772
00773
00774 index = ii;
00775 min_length_from_start=dist_mod;
00776 }
00777
00778 }
00779
00780 return index;
00781 }
00782
00783
00784
00785
00786
00787
00788
00789
00790
00791
00792
00793
00794
00795
00796
00797
00798
00799
00800
00801
00802
00803
00804
00805
00806
00807
00808
00809
00810
00811
00812
00813
00814
00815
00816
00817
00818
00819
00820
00821
00823 Int_t GeometryUtilities::GetProjectedPoint(const PxPoint *p0,
00824 const PxPoint *p1,
00825 PxPoint &pN) const
00826 {
00827
00828
00829 for(UInt_t i = 0; i < fNPlanes; ++i){
00830 if(i == p0->plane || i == p1->plane)
00831 continue;
00832 pN.plane = i;
00833 }
00834
00835
00836
00837 UInt_t chan1 = geom->PlaneWireToChannel(p0->plane,p0->w);
00838 UInt_t chan2 = geom->PlaneWireToChannel(p1->plane,p1->w);
00839
00840 Double_t pos[3]={0.};
00841 geom->PlaneOriginVtx(p0->plane, pos);
00842
00843 Double_t x=(p0->t - detp->TriggerOffset())*fTimetoCm+pos[0];
00844
00845 Double_t y,z;
00846 if(! geom->ChannelsIntersect(chan1,chan2,y,z) )
00847 return -1;
00848
00849
00850 pos[1]=y;
00851 pos[2]=z;
00852 pos[0]=x;
00853
00854 pN=Get2DPointProjection(pos, pN.plane);
00855
00856 return 0;
00857 }
00858
00859
00861 Int_t GeometryUtilities::GetYZ(const PxPoint *p0,
00862 const PxPoint *p1,
00863 Double_t* yz) const
00864 {
00865 Double_t y,z;
00866
00867 UInt_t chan1 = geom->PlaneWireToChannel(p0->plane, p0->w);
00868 UInt_t chan2 = geom->PlaneWireToChannel(p1->plane, p1->w);
00869
00870 if(! geom->ChannelsIntersect(chan1,chan2,y,z) )
00871 return -1;
00872
00873 yz[0]=y;
00874 yz[1]=z;
00875
00876 return 0;
00877 }
00878
00880
00881 PxPoint GeometryUtilities::Get2DPointProjection(Double_t *xyz, Int_t plane) const{
00882
00883 PxPoint pN(0,0,0);
00884
00885 Double_t pos[3];
00886 geom->PlaneOriginVtx(plane,pos);
00887 Double_t drifttick=(xyz[0]/fDriftVelocity)*(1./fTimeTick);
00888
00889 pos[1]=xyz[1];
00890 pos[2]=xyz[2];
00891
00893
00894 pN.w = geom->NearestWire(pos, plane);
00895 pN.t=drifttick-(pos[0]/fDriftVelocity)*(1./fTimeTick)+detp->TriggerOffset();
00896 pN.plane=plane;
00897
00898 return pN;
00899
00900 }
00901
00902
00904
00905
00906
00908
00909 PxPoint GeometryUtilities::Get2DPointProjectionCM(std::vector< double > xyz, int plane) const{
00910
00911 PxPoint pN(0,0,0);
00912
00913 Double_t pos[3];
00914
00915
00916 pos[1]=xyz[1];
00917 pos[2]=xyz[2];
00918
00920
00921 pN.w = geom->NearestWire(pos, plane)*fWiretoCm;
00922 pN.t=xyz[0];
00923 pN.plane=plane;
00924
00925 return pN;
00926
00927 }
00928
00929
00930 PxPoint GeometryUtilities::Get2DPointProjectionCM(double *xyz, int plane) const{
00931
00932 PxPoint pN(0,0,0);
00933
00934 Double_t pos[3];
00935
00936
00937 pos[1]=xyz[1];
00938 pos[2]=xyz[2];
00939
00941
00942 pN.w = geom->NearestWire(pos, plane)*fWiretoCm;
00943 pN.t=xyz[0];
00944 pN.plane=plane;
00945
00946 return pN;
00947
00948 }
00949
00950
00951
00952 PxPoint GeometryUtilities::Get2DPointProjectionCM(TLorentzVector *xyz, int plane) const{
00953 double xyznew[3]={(*xyz)[0],(*xyz)[1],(*xyz)[2]};
00954
00955 return Get2DPointProjectionCM(xyznew,plane);
00956 }
00957
00958
00959
00960 Double_t GeometryUtilities::GetTimeTicks(Double_t x, Int_t plane) const{
00961
00962
00963
00964 Double_t pos[3];
00965 geom->PlaneOriginVtx(plane,pos);
00966 Double_t drifttick=(x/fDriftVelocity)*(1./fTimeTick);
00967
00968 return drifttick-(pos[0]/fDriftVelocity)*(1./fTimeTick)+detp->TriggerOffset();
00969
00970
00971 }
00972
00973
00974
00975
00976
00977
00978 Double_t GeometryUtilities::PitchInView(UInt_t plane,
00979 Double_t phi,
00980 Double_t theta) const
00981 {
00982 Double_t dirs[3] = {0.};
00983 GetDirectionCosines(phi,theta,dirs);
00984
00987 Double_t wirePitch = 0.;
00988 Double_t angleToVert = 0.;
00989
00990 wirePitch = geom->WirePitch(0,1,plane);
00991 angleToVert = geom->WireAngleToVertical(geom->PlaneToView(plane)) - 0.5*TMath::Pi();
00992
00993
00994
00995 Double_t cosgamma = TMath::Abs(TMath::Sin(angleToVert)*dirs[1] +
00996 TMath::Cos(angleToVert)*dirs[2]);
00997
00998
00999
01000 if(cosgamma < 1.e-5)
01001 throw LArUtilException("cosgamma is basically 0, that can't be right");
01002
01003 return wirePitch/cosgamma;
01004 }
01005
01006
01008 void GeometryUtilities::GetDirectionCosines(Double_t phi,
01009 Double_t theta,
01010 Double_t *dirs) const
01011 {
01012 theta*=(TMath::Pi()/180);
01013 phi*=(TMath::Pi()/180);
01014 dirs[0]=TMath::Cos(theta)*TMath::Sin(phi);
01015 dirs[1]=TMath::Sin(theta);
01016 dirs[2]=TMath::Cos(theta)*TMath::Cos(phi);
01017
01018 }
01019
01020
01022 Int_t GeometryUtilities::GetPlaneAndTPC(const larlight::hit* h,
01023 UInt_t &p,
01024 UInt_t &w) const
01025 {
01026 p = geom->ChannelToPlane(h->Channel());
01027 w = geom->ChannelToWire(h->Channel());
01028 return 0;
01029 }
01030
01031
01032 void GeometryUtilities::SelectLocalHitlist(const std::vector< larlight::hit*> &hitlist,
01033 std::vector<UInt_t> &hitlistlocal_index,
01034 Double_t wire_start,Double_t time_start,
01035 Double_t linearlimit, Double_t ortlimit,
01036 Double_t lineslopetest)
01037 {
01038 hitlistlocal_index.clear();
01039 Double_t locintercept=time_start-wire_start*lineslopetest;
01040
01041 for(size_t i=0; i<hitlist.size(); ++i) {
01042
01043 Double_t time = hitlist.at(i)->PeakTime();
01044 UInt_t plane,wire;
01045 GetPlaneAndTPC(hitlist.at(i),plane,wire);
01046
01047 Double_t wonline=wire,tonline=time;
01048
01049 GetPointOnLine(lineslopetest,locintercept,wire,time,wonline,tonline);
01050
01051
01052 Double_t lindist=Get2DDistance(wonline,tonline,wire_start,time_start);
01053 Double_t ortdist=Get2DDistance(wire,time,wonline,tonline);
01054
01056
01057 if(lindist<linearlimit && ortdist<ortlimit){
01058 hitlistlocal_index.push_back((UInt_t)i);
01059
01060 }
01061
01062 }
01063 }
01064
01065 void GeometryUtilities::SelectLocalHitlist(const std::vector< larlight::hit*> &hitlist,
01066 std::vector<larlight::hit*> &hitlistlocal,
01067 Double_t wire_start,Double_t time_start,
01068 Double_t linearlimit, Double_t ortlimit,
01069 Double_t lineslopetest)
01070 {
01071 hitlistlocal.clear();
01072 Double_t locintercept=time_start-wire_start*lineslopetest;
01073
01074 for(size_t i=0; i<hitlist.size(); ++i) {
01075
01076 Double_t time = hitlist.at(i)->PeakTime();
01077 UInt_t plane,wire;
01078 GetPlaneAndTPC(hitlist.at(i),plane,wire);
01079
01080 Double_t wonline=wire,tonline=time;
01081
01082 GetPointOnLine(lineslopetest,locintercept,wire,time,wonline,tonline);
01083
01084
01085 Double_t lindist=Get2DDistance(wonline,tonline,wire_start,time_start);
01086 Double_t ortdist=Get2DDistance(wire,time,wonline,tonline);
01087
01089
01090 if(lindist<linearlimit && ortdist<ortlimit){
01091 hitlistlocal.push_back(hitlist.at(i));
01092
01093 }
01094 }
01095 }
01096
01097 void GeometryUtilities::SelectLocalHitlist(const std::vector<larutil::PxHit> &hitlist,
01098 std::vector <const larutil::PxHit*> &hitlistlocal,
01099 larutil::PxPoint &startHit,
01100 Double_t& linearlimit,
01101 Double_t& ortlimit,
01102 Double_t& lineslopetest,
01103 larutil::PxHit &averageHit)
01104 {
01105
01106 hitlistlocal.clear();
01107 double locintercept=startHit.t - startHit.w * lineslopetest;
01108 double timesum = 0;
01109 double wiresum = 0;
01110 for(size_t i=0; i<hitlist.size(); ++i) {
01111
01112 larutil::PxPoint hitonline;
01113
01114 GetPointOnLine( lineslopetest, locintercept, (const larutil::PxHit*)(&hitlist.at(i)), hitonline );
01115
01116
01117 Double_t lindist=Get2DDistance((const larutil::PxPoint*)(&hitonline),(const larutil::PxPoint*)(&startHit));
01118 Double_t ortdist=Get2DDistance((const larutil::PxPoint*)(&hitlist.at(i)),(const larutil::PxPoint*)(&hitonline));
01119
01120
01121 if(lindist<linearlimit && ortdist<ortlimit){
01122 hitlistlocal.push_back((const larutil::PxHit*)(&(hitlist.at(i))));
01123 timesum += hitlist.at(i).t;
01124 wiresum += hitlist.at(i).w;
01125 }
01126
01127
01128 }
01129
01130 averageHit.plane = startHit.plane;
01131 if(hitlistlocal.size())
01132 {
01133 averageHit.w = wiresum/(double)hitlistlocal.size();
01134 averageHit.t = timesum/((double) hitlistlocal.size());
01135 }
01136 }
01137
01138
01139 void GeometryUtilities::SelectPolygonHitList(const std::vector<larutil::PxHit> &hitlist,
01140 std::vector <const larutil::PxHit*> &hitlistlocal)
01141 {
01142 if(!(hitlist.size())) {
01143 throw LArUtilException("Provided empty hit list!");
01144 return;
01145 }
01146
01147 hitlistlocal.clear();
01148 unsigned char plane = (*hitlist.begin()).plane;
01149
01150
01151 std::map<double,const larutil::PxHit*> hitmap;
01152 double qtotal=0;
01153 for(auto const &h : hitlist){
01154
01155 hitmap.insert(std::pair<double,const larutil::PxHit*>(h.charge,&h));
01156 qtotal += h.charge;
01157
01158 }
01159 double qintegral=0;
01160 std::vector<const larutil::PxHit*> ordered_hits;
01161 ordered_hits.reserve(hitlist.size());
01162 for(auto hiter = hitmap.rbegin();
01163 qintegral < qtotal*0.95;
01164 ++hiter) {
01165
01166 qintegral += (*hiter).first;
01167 ordered_hits.push_back((*hiter).second);
01168
01169 }
01170
01171
01172 std::vector<size_t> hit_index(8,0);
01173 std::vector<double> hit_distance(8,1e9);
01174
01175
01176
01177 std::vector<larutil::PxPoint> edges(4,PxPoint(plane,0,0));
01178 double wire_max = geom->Nwires(plane) * fWiretoCm;
01179 double time_max = detp->NumberTimeSamples() * fTimetoCm;
01180
01181 for(size_t index = 0; index<ordered_hits.size(); ++index) {
01182
01183 if(ordered_hits.at(index)->t < 0 ||
01184 ordered_hits.at(index)->w < 0 ||
01185 ordered_hits.at(index)->t > time_max ||
01186 ordered_hits.at(index)->w > wire_max ) {
01187
01188 throw LArUtilException(Form("Invalid wire/time (%g,%g) ... range is (0=>%g,0=>%g)",
01189 ordered_hits.at(index)->w,
01190 ordered_hits.at(index)->t,
01191 wire_max,
01192 time_max)
01193 );
01194 return;
01195 }
01196
01197 double dist = 0;
01198
01199
01200 dist = ordered_hits.at(index)->t;
01201 if(dist < hit_distance.at(1)) {
01202 hit_distance.at(1) = dist;
01203 hit_index.at(1) = index;
01204 edges.at(0).t = ordered_hits.at(index)->t;
01205 edges.at(1).t = ordered_hits.at(index)->t;
01206 }
01207
01208
01209 dist = wire_max - ordered_hits.at(index)->w;
01210 if(dist < hit_distance.at(3)) {
01211 hit_distance.at(3) = dist;
01212 hit_index.at(3) = index;
01213 edges.at(1).w = ordered_hits.at(index)->w;
01214 edges.at(2).w = ordered_hits.at(index)->w;
01215 }
01216
01217
01218 dist = time_max - ordered_hits.at(index)->t;
01219 if(dist < hit_distance.at(5)) {
01220 hit_distance.at(5) = dist;
01221 hit_index.at(5) = index;
01222 edges.at(2).t = ordered_hits.at(index)->t;
01223 edges.at(3).t = ordered_hits.at(index)->t;
01224 }
01225
01226
01227 dist = ordered_hits.at(index)->w;
01228 if(dist < hit_distance.at(7)) {
01229 hit_distance.at(7) = dist;
01230 hit_index.at(7) = index;
01231 edges.at(0).w = ordered_hits.at(index)->w;
01232 edges.at(3).w = ordered_hits.at(index)->w;
01233 }
01234 }
01235
01236
01237
01238
01239
01240
01241
01242
01243
01244 for(size_t index = 0; index<ordered_hits.size(); ++index) {
01245
01246 double dist = 0;
01247
01248 dist = pow((ordered_hits.at(index)->t - edges.at(0).t),2) + pow((ordered_hits.at(index)->w - edges.at(0).w),2);
01249 if(dist < hit_distance.at(0)) {
01250 hit_distance.at(0) = dist;
01251 hit_index.at(0) = index;
01252 }
01253
01254
01255 dist = pow((ordered_hits.at(index)->t - edges.at(1).t),2) + pow((ordered_hits.at(index)->w - edges.at(1).w),2);
01256 if(dist < hit_distance.at(2)) {
01257 hit_distance.at(2) = dist;
01258 hit_index.at(2) = index;
01259 }
01260
01261
01262 dist = pow((ordered_hits.at(index)->t - edges.at(2).t),2) + pow((ordered_hits.at(index)->w - edges.at(2).w),2);
01263 if(dist < hit_distance.at(4)) {
01264 hit_distance.at(4) = dist;
01265 hit_index.at(4) = index;
01266 }
01267
01268
01269 dist = pow((ordered_hits.at(index)->t - edges.at(3).t),2) + pow((ordered_hits.at(index)->w - edges.at(3).w),2);
01270 if(dist < hit_distance.at(6)) {
01271 hit_distance.at(6) = dist;
01272 hit_index.at(6) = index;
01273 }
01274
01275 }
01276
01277
01278 std::set<size_t> unique_index;
01279 std::vector<size_t> candidate_polygon;
01280 candidate_polygon.reserve(9);
01281
01282 for(auto &index : hit_index) {
01283
01284 if(unique_index.find(index) == unique_index.end()) {
01285
01286
01287 unique_index.insert(index);
01288 candidate_polygon.push_back(index);
01289 }
01290 }
01291 for (auto &index: hit_index){
01292 candidate_polygon.push_back(index);
01293 break;
01294 }
01295
01296 if(unique_index.size()>8) throw LArUtilException("Size of the polygon > 8!");
01297
01298
01299 candidate_polygon = PolyOverlap( ordered_hits, candidate_polygon);
01300
01301 hitlistlocal.clear();
01302 for( unsigned int i=0; i<(candidate_polygon.size()-1); i++){
01303 hitlistlocal.push_back((const larutil::PxHit*)(ordered_hits.at(candidate_polygon.at(i))));
01304 }
01305
01306 if(unique_index.size()>8) throw LArUtilException("Size of the polygon > 8!");
01307 }
01308
01309
01310 std::vector<size_t> GeometryUtilities::PolyOverlap( std::vector<const larutil::PxHit*> ordered_hits ,
01311 std::vector<size_t> candidate_polygon) {
01312
01313
01314 for ( unsigned int i=0; i<(candidate_polygon.size()-1); i++){
01315 double Ax = ordered_hits.at(candidate_polygon.at(i))->w;
01316 double Ay = ordered_hits.at(candidate_polygon.at(i))->t;
01317 double Bx = ordered_hits.at(candidate_polygon.at(i+1))->w;
01318 double By = ordered_hits.at(candidate_polygon.at(i+1))->t;
01319
01320
01321 for ( unsigned int j=i+2; j<(candidate_polygon.size()-1); j++){
01322
01323 if ( candidate_polygon.at(i) == candidate_polygon.at(j+1) )
01324 continue;
01325 else{
01326 double Cx = ordered_hits.at(candidate_polygon.at(j))->w;
01327 double Cy = ordered_hits.at(candidate_polygon.at(j))->t;
01328 double Dx = ordered_hits.at(candidate_polygon.at(j+1))->w;
01329 double Dy = ordered_hits.at(candidate_polygon.at(j+1))->t;
01330
01331 if ( (Clockwise(Ax,Ay,Cx,Cy,Dx,Dy) != Clockwise(Bx,By,Cx,Cy,Dx,Dy))
01332 and (Clockwise(Ax,Ay,Bx,By,Cx,Cy) != Clockwise(Ax,Ay,Bx,By,Dx,Dy)) ){
01333 size_t tmp = candidate_polygon.at(i+1);
01334 candidate_polygon.at(i+1) = candidate_polygon.at(j);
01335 candidate_polygon.at(j) = tmp;
01336
01337 candidate_polygon.at(candidate_polygon.size()-1) = candidate_polygon.at(0);
01338
01339 return PolyOverlap( ordered_hits, candidate_polygon);
01340 }
01341 }
01342 }
01343 }
01344
01345 return candidate_polygon;
01346 }
01347
01348 bool GeometryUtilities::Clockwise(double Ax,double Ay,double Bx,double By,double Cx,double Cy){
01349 return (Cy-Ay)*(Bx-Ax) > (By-Ay)*(Cx-Ax);
01350 }
01351
01352 }