9 #include "AnitaVersion.h" 10 #include "UsefulAdu5Pat.h" 12 #include "TTimeStamp.h" 13 #include "AnitaDataset.h" 16 #ifdef ENABLE_VECTORIZE 17 #include "vectormath_trig.h" 28 UsefulAdu5Pat::UsefulAdu5Pat()
33 pitch = AnitaStaticAdu5Offsets::pitch;
34 roll = AnitaStaticAdu5Offsets::roll;
35 heading += AnitaStaticAdu5Offsets::heading;
51 fInterpSurfaceAboveGeoid =
false;
52 fSurfaceCloseEnoughIter = 1.0;
53 setMaxLoopIterations();
56 UsefulAdu5Pat::UsefulAdu5Pat(
const Adu5Pat *patPtr)
61 pitch = AnitaStaticAdu5Offsets::pitch;
62 roll = AnitaStaticAdu5Offsets::roll;
63 heading += AnitaStaticAdu5Offsets::heading;
79 fInterpSurfaceAboveGeoid =
false;
80 fSurfaceCloseEnoughIter = 1.0;
102 fBalloonPos.SetXYZ(fBalloonCoords[0],fBalloonCoords[1],fBalloonCoords[2]);
103 fBalloonTheta=fBalloonPos.Theta();
104 fBalloonPhi=fBalloonPos.Phi();
106 fBalloonPhi+=TMath::TwoPi();
108 fBalloonHeight=fBalloonPos.Mag();
125 void UsefulAdu5Pat::getThetaAndPhiWaveWillyBorehole(Double_t &thetaWave,Double_t &phiWave)
137 AnitaLocations::LATITUDE_TD,
138 AnitaLocations::ALTITUDE_TD,
143 int UsefulAdu5Pat::getSourceLonAndLatAltZero(Double_t phiWave, Double_t thetaWave, Double_t &sourceLon, Double_t &sourceLat) {
151 void UsefulAdu5Pat::accountForPitchAndRollInPhiWaveThetaWave(Double_t& phiWave, Double_t& thetaWave)
const {
155 Double_t tempPhiWave=phiWave;
156 Double_t tempThetaWave=TMath::PiOver2()-thetaWave;
158 TVector3 rollAxis = geom->fRollRotationAxis;
159 TVector3 pitchAxis = geom->fPitchRotationAxis;
162 arbDir.SetMagThetaPhi(1,tempThetaWave,-1*tempPhiWave);
164 arbDir.Rotate(
heading*TMath::DegToRad(),geom->fHeadingRotationAxis);
165 rollAxis.Rotate((
heading)*TMath::DegToRad(),geom->fHeadingRotationAxis);
166 pitchAxis.Rotate((
heading)*TMath::DegToRad(),geom->fHeadingRotationAxis);
168 arbDir.Rotate(
pitch*TMath::DegToRad(),pitchAxis);
169 rollAxis.Rotate(
pitch*TMath::DegToRad(),pitchAxis);
170 arbDir.Rotate(roll*TMath::DegToRad(),rollAxis);
172 tempPhiWave=arbDir.Phi();
173 if(tempPhiWave>TMath::TwoPi()) {
174 tempPhiWave-=TMath::TwoPi();
177 tempPhiWave+=TMath::TwoPi();
179 tempThetaWave=arbDir.Theta();
182 thetaWave = tempThetaWave;
183 phiWave = tempPhiWave;
192 if(fPhiWave!=phiWave) fPhiWave=phiWave;
193 if(fThetaWave!=thetaWave) fThetaWave=thetaWave;
195 Double_t tempPhiWave=phiWave;
196 Double_t tempThetaWave=thetaWave;
199 accountForPitchAndRollInPhiWaveThetaWave(tempPhiWave, tempThetaWave);
202 std::cerr <<
"Error in " << __PRETTY_FUNCTION__ <<
": Bad heading = " <<
heading << std::endl;
210 Double_t reBalloon=geom->getDistanceToCentreOfEarth(
latitude)+desiredAlt;
211 Double_t re=reBalloon;
215 const Double_t sintw = TMath::Sin(tempThetaWave);
216 const Double_t costw = TMath::Cos(tempThetaWave);
223 Double_t sqrtArg(re*re-reh*reh*sintw*sintw);
231 Double_t L=reh*costw - TMath::Sqrt(sqrtArg);
232 Double_t sinThetaL=L*sintw/re;
233 Double_t sourceTheta=TMath::ASin(sinThetaL);
235 fSourcePos.SetXYZ(0, 0, re);
236 fSourcePos.RotateY(sourceTheta);
237 fSourcePos.RotateZ(-1*tempPhiWave);
239 fSourcePos.RotateY(fBalloonTheta);
240 fSourcePos.RotateZ(fBalloonPhi);
242 Double_t sourceVec[3];
243 fSourcePos.GetXYZ(sourceVec);
246 geom->getLatLonAltFromCartesian(sourceVec,sourceLat,sourceLon,sourceAlt);
247 nextRe=geom->getDistanceToCentreOfEarth(sourceLat);
249 }
while(TMath::Abs(nextRe-re)>1);
258 if(fPhiWave!=phiWave) fPhiWave=phiWave;
259 if(fThetaWave!=thetaWave) fThetaWave=thetaWave;
260 return getSourceLonAndLatAtAlt2(phiWave, thetaWave, sourceLon, sourceLat, sourceAltitude, fMaxLoopIterations, &fSourcePos);
267 int UsefulAdu5Pat::getSourceLonAndLatAtAlt2(Double_t phiWave, Double_t thetaWave, Double_t &sourceLon, Double_t &sourceLat,Double_t &sourceAltitude, Int_t maxLoopIterations, TVector3* sourcePosOptional)
const 277 Double_t tempPhiWave = phiWave;
278 Double_t tempThetaWave = thetaWave;
279 TVector3 sourcePosIfNoOptionalPtrPassed;
281 TVector3& sourcePos = sourcePosOptional ? *sourcePosOptional : sourcePosIfNoOptionalPtrPassed;
284 accountForPitchAndRollInPhiWaveThetaWave(tempPhiWave, tempThetaWave);
287 std::cerr <<
"Error in " << __PRETTY_FUNCTION__ <<
": Bad heading = " <<
heading << std::endl;
290 sourceAltitude = -9999;
296 Double_t reBalloon = geom->getDistanceToCentreOfEarth(
latitude);
298 Double_t re = reBalloon+chosenAlt;
299 Double_t nextRe = re;
303 std::cout <<
"balloon: lat = " <<
latitude <<
", lon = " <<
longitude <<
", re = " << reBalloon+chosenAlt <<
", surface elevation = " << chosenAlt << std::endl;
305 std::cout <<
"heading = " <<
heading <<
", pitch = " <<
pitch <<
", roll = " << roll << std::endl;
309 Double_t lastButOneRe = 0;
310 Double_t lastButTwoRe = 0;
311 Double_t lastButThreeRe = 0;
312 Double_t lastButFourRe = 0;
316 maxLoopIterations = maxLoopIterations < 0 ? fMaxLoopIterations : maxLoopIterations;
318 const double deltaReCloseEnough = fSurfaceCloseEnoughIter;
319 Bool_t ocillatingAroundSolution =
false;
320 Bool_t tooManyLoops =
false;
322 const Double_t sintw = TMath::Sin(tempThetaWave);
323 const Double_t costw = TMath::Cos(tempThetaWave);
331 if(inTheLoop>3){lastButFourRe = lastButThreeRe;}
332 if(inTheLoop>2){lastButThreeRe = lastButTwoRe;}
333 if(inTheLoop>1){lastButTwoRe = lastButOneRe;}
334 if(inTheLoop>0){lastButOneRe = re;}
338 Double_t sqrtArg = re*re - reh*reh*sintw*sintw;
346 std::cerr <<
"Error in " << __PRETTY_FUNCTION__ <<
", no solution possible! Returning 0\n";
354 Double_t L = reh*costw - TMath::Sqrt(sqrtArg);
355 Double_t sinThetaL = L*sintw/re;
356 Double_t sourceTheta = TMath::ASin(sinThetaL);
358 sourcePos.SetXYZ(0, 0, re);
361 sourcePos.RotateY(sourceTheta);
362 sourcePos.RotateZ(-1*tempPhiWave);
363 sourcePos.RotateY(fBalloonTheta);
364 sourcePos.RotateZ(fBalloonPhi);
366 Double_t sourceVec[3];
367 sourcePos.GetXYZ(sourceVec);
369 geom->getLatLonAltFromCartesian(sourceVec,sourceLat,sourceLon,sourceAlt);
371 nextRe = geom->getDistanceToCentreOfEarth(sourceLat) + chosenAlt;
378 if(fDebug && maxLoopIterations - inTheLoop < 3){
379 std::cerr <<
"Debug in " << __PRETTY_FUNCTION__ <<
": inTheLoop = " << inTheLoop
380 <<
", sourceLon = " << sourceLon <<
", sourceLat = " << sourceLat <<
", sourceAlt = " << sourceAlt
381 <<
", re = " << re <<
", lastButOneRe-re = " << lastButOneRe-re <<
", lastButTwoRe-re = " << lastButTwoRe-re
382 <<
", lastButThreeRe-re = " << lastButThreeRe-re <<
", lastButFourRe-re = " << lastButFourRe-re
383 <<
", TMath::Abs(lastButOneRe-nextRe) = " << TMath::Abs(lastButOneRe-nextRe) <<
"\n";
386 const int numLoopChecks = 4;
387 const double deltaRes[numLoopChecks] = {TMath::Abs(lastButOneRe-nextRe),
388 TMath::Abs(lastButTwoRe-nextRe),
389 TMath::Abs(lastButThreeRe-nextRe),
390 TMath::Abs(lastButFourRe-nextRe)};
391 int smallestRe = TMath::LocMin(numLoopChecks, deltaRes);
392 if(deltaRes[smallestRe] <= deltaReCloseEnough){
394 const double Res[numLoopChecks] = {lastButOneRe, lastButTwoRe, lastButThreeRe, lastButFourRe};
395 const char* whichRe[numLoopChecks] = {
"lastButOneRe",
"lastButTwoRe",
"lastButThreeRe",
"lastButFourRe"};
396 std::cerr <<
"Breaking out due to small enough difference over several loop iterations, nextRe = " 397 << nextRe <<
", " << whichRe[smallestRe] <<
" = " << Res[smallestRe]
398 <<
", abs(" << whichRe[smallestRe] <<
" - nextRe) = " << deltaRes[smallestRe] << std::endl;
400 ocillatingAroundSolution =
true;
405 if(inTheLoop>maxLoopIterations){
407 std::cerr <<
"Debug in " << __PRETTY_FUNCTION__ <<
": Breaking out due to too many loop iterations! inTheLoop > " << maxLoopIterations
408 <<
" (default value, fMaxLoopIterations = " << fMaxLoopIterations <<
")" << std::endl;
414 }
while(TMath::Abs(nextRe-re)>deltaReCloseEnough);
416 sourceAltitude = chosenAlt;
418 if(ocillatingAroundSolution){
423 else if(tooManyLoops){
427 sourceAltitude = -9999;
430 else if(TMath::Nint(chosenAlt)==-9999){
434 sourceAltitude = -9999;
453 Double_t * lon, Double_t * lat, Double_t *alt,
454 Double_t * theta_adjustment_required)
const{
457 bool wantBestPosition = theta_adjustment_required ? true :
false;
459 if(theta_adjustment_required){
460 *theta_adjustment_required = 0;
463 int success = getSourceLonAndLatAtAlt3(phiWave, thetaWave, *lon, *lat, *alt, &deltaAlt, wantBestPosition);
465 if(success==3 && wantBestPosition){
467 double newThetaWave, newPhiWave;
471 *theta_adjustment_required = newThetaWave - thetaWave;
483 int UsefulAdu5Pat::getSourceLonAndLatAtAlt3(Double_t phiWave, Double_t thetaWave,
484 Double_t &sourceLon, Double_t &sourceLat,Double_t &sourceAltitude,
485 double* deltaAltIfNoIntersectection,
bool returnBestPositionIfNoIntersection)
const 490 std::cout <<
"No chance! " << std::endl;
508 Double_t anitaPosition[3];
510 const TVector3 anitaVector(anitaPosition);
515 const TVector3 inwardNorm = anitaVector.Unit();
516 const double scale = TMath::Abs(1./inwardNorm.Dot(unitVector));
517 const TVector3 deltaVector = scale*unitVector;
521 double minAbsDeltaAlt = DBL_MAX;
522 double bestLon, bestLat, bestAlt, bestDeltaAlt;
525 int best_last_i = -1;
527 for(
int precise=0; precise <= 1; precise++){
529 int i = precise == 0 ? 0 : best_last_i;
532 double deltaAlt = DBL_MAX;
533 double firstDeltaAlt = DBL_MAX;
535 while(deltaAlt <= firstDeltaAlt){
537 const TVector3 rayVector = i*deltaVector + anitaPosition;
538 double rayLat, rayLon, rayAlt;
539 double rayPosition[3];
540 rayVector.GetXYZ(rayPosition);
541 geom->getLatLonAltFromCartesian(rayPosition, rayLat, rayLon, rayAlt);
544 deltaAlt = rayAlt - surfaceAlt;
546 if(firstDeltaAlt==DBL_MAX){
547 firstDeltaAlt = deltaAlt;
556 double absDeltaAlt = fabs(deltaAlt);
557 if(absDeltaAlt < minAbsDeltaAlt){
560 bestAlt = surfaceAlt;
561 bestDeltaAlt = deltaAlt;
563 best_last_i = last_i;
564 minAbsDeltaAlt = absDeltaAlt;
574 sourceAltitude = surfaceAlt;
575 if(deltaAltIfNoIntersectection){
576 *deltaAltIfNoIntersectection = deltaAlt;
584 if(deltaAlt > 10000){
590 else if(deltaAlt > 1000){
593 else if(deltaAlt > 500){
596 else if(deltaAlt > 100){
603 if(returnBestPositionIfNoIntersection){
606 sourceAltitude = bestAlt;
611 sourceAltitude = -9999;
613 if(deltaAltIfNoIntersectection){
614 *deltaAltIfNoIntersectection = bestDeltaAlt;
638 Double_t anitaPosition[3];
651 double testThetaWave, testPhiWave;
659 Double_t testPosition[3];
660 geom->getCartesianCoords(testLat, testLon, testAlt, testPosition);
662 TVector3 testVector(testPosition);
663 const TVector3 unitAnita = TVector3(anitaPosition).Unit();
664 testVector.Rotate(-testPhiWave, unitAnita);
675 testVector.Rotate(phiWave, unitAnita);
677 testVector.GetXYZ(testPosition);
678 geom->getLatLonAltFromCartesian(testPosition, testLat, testLon, testAlt);
712 TVector3 anitaVector(anitaPosition);
714 double A = TMath::PiOver2() - thetaWave;
715 double O = testVector.Angle(anitaPosition);
716 double T = TMath::Pi() - A - O;
717 double t = anitaVector.Mag();
718 double a = TMath::Sin(A)*(t/TMath::Sin(T));
720 testVector.SetMag(a);
731 TVector3 deltaVec = testVector - anitaPosition;
732 return deltaVec.Unit();
742 return getThetaAndPhiWave(AnitaLocations::getWaisLongitude(), AnitaLocations::getWaisLatitude(),AnitaLocations::getWaisAltitude(),thetaWave,phiWave);
760 Double_t pSource[3]={0};
762 geom->getCartesianCoords(TMath::Abs(sourceLat),sourceLon,sourceAlt,pSource);
763 TVector3 sourcePosStack;
764 sourcePos = sourcePos ? sourcePos : &sourcePosStack;
765 sourcePos->SetXYZ(pSource[0],pSource[1],pSource[2]);
774 sourcePos->RotateZ(-1*fBalloonPhi);
775 sourcePos->RotateY(-1*fBalloonTheta);
778 thetaWave = TMath::ATan((fBalloonHeight-sourcePos->Z())/TMath::Sqrt(sourcePos->X()*sourcePos->X() + sourcePos->Y()*sourcePos->Y()));
783 if(sourcePos->X()==0) {
784 phiWave = TMath::PiOver2();
786 phiWave += TMath::Pi();
788 else if(sourcePos->X()<0) {
789 phiWave = TMath::Pi()+TMath::ATan(sourcePos->Y()/sourcePos->X());
792 phiWave = TMath::ATan(sourcePos->Y()/sourcePos->X());
793 if(sourcePos->Y()<0) {
794 phiWave += TMath::TwoPi();
798 TVector3 rollAxis = geom->fRollRotationAxis;
799 TVector3 pitchAxis = geom->fPitchRotationAxis;
801 Double_t tempThetaWave=TMath::PiOver2()-thetaWave;
805 arbDir.SetMagThetaPhi(1,tempThetaWave,-1*phiWave);
807 rollAxis.Rotate(
heading*TMath::DegToRad(),geom->fHeadingRotationAxis);
808 pitchAxis.Rotate(
heading*TMath::DegToRad(),geom->fHeadingRotationAxis);
809 rollAxis.Rotate(
pitch*TMath::DegToRad(),pitchAxis);
811 arbDir.Rotate(-1.*roll*TMath::DegToRad(),rollAxis);
812 arbDir.Rotate(-1*
pitch*TMath::DegToRad(),pitchAxis);
813 arbDir.Rotate(-1*
heading*TMath::DegToRad(),geom->fHeadingRotationAxis);
815 phiWave = arbDir.Phi();
817 if(phiWave>TMath::TwoPi()) {
818 phiWave-=TMath::TwoPi();
821 phiWave+=TMath::TwoPi();
823 thetaWave=TMath::PiOver2()-arbDir.Theta();
830 Double_t UsefulAdu5Pat::getGroupDelay(Double_t phiToAntBoresight)
832 Double_t phiDeg=phiToAntBoresight*TMath::RadToDeg();
833 Double_t delayTime=(phiDeg*phiDeg*phiDeg*phiDeg)*1.45676e-8;
834 delayTime-=(phiDeg*phiDeg)*5.01452e-6;
846 Double_t pSource[3]={0};
848 fSourcePos.SetXYZ(pSource[0], pSource[1], pSource[2]);
851 TVector3 rotatedBalloonPos = fBalloonPos;
852 rotatedBalloonPos.RotateZ(-1*fSourcePos.Phi());
853 rotatedBalloonPos.RotateY(-1*fSourcePos.Theta());
855 TVector3 rotatedBase = fSourcePos;
856 rotatedBase.RotateZ(-1*fSourcePos.Phi());
857 rotatedBase.RotateY(-1*fSourcePos.Theta());
860 thetaWave=TMath::ATan((rotatedBase.Z()-rotatedBalloonPos.Z())/TMath::Sqrt(rotatedBalloonPos.X()*rotatedBalloonPos.X() + rotatedBalloonPos.Y()*rotatedBalloonPos.Y()));
867 Double_t tempTheta,tempPhi;
868 if(fSourceAltitude!=sourceAlt || fSourceLongitude!=sourceLon || fSourceLatitude!=sourceLat){
876 Double_t r1=geom->
getAntR(ant1);
877 Double_t z1=geom->
getAntZ(ant1);
880 Double_t r2=geom->
getAntR(ant2);
881 Double_t z2=geom->
getAntZ(ant2);
883 Double_t tanThetaW=TMath::Tan(fThetaWave);
884 Double_t part1=z1*tanThetaW - r1 * TMath::Cos(fPhiWave-phi1);
885 Double_t part2=z2*tanThetaW - r2 * TMath::Cos(fPhiWave-phi2);
887 Double_t geomTime= 1e9*((TMath::Cos(fThetaWave) * (part1 - part2))/C_LIGHT);
888 if(fIncludeGroupDelay) {
889 Double_t phi1Diff=geom->
getPhiDiff(fPhiWave,phi1);
890 Double_t delay1=getGroupDelay(phi1Diff);
891 Double_t phi2Diff=geom->
getPhiDiff(fPhiWave,phi2);
892 Double_t delay2=getGroupDelay(phi2Diff);
893 geomTime+=(delay1-delay2);
905 if(fPhiWave!=phiWave || fThetaWave!=thetaWave){
906 fThetaWave=thetaWave;
912 Double_t r1=geom->
getAntR(ant1);
913 Double_t z1=geom->
getAntZ(ant1);
916 Double_t r2=geom->
getAntR(ant2);
917 Double_t z2=geom->
getAntZ(ant2);
919 Double_t tanThetaW=TMath::Tan(fThetaWave);
920 Double_t part1=z1*tanThetaW - r1 * TMath::Cos(fPhiWave-phi1);
921 Double_t part2=z2*tanThetaW - r2 * TMath::Cos(fPhiWave-phi2);
923 return 1e9*((TMath::Cos(fThetaWave) * (part1 - part2))/C_LIGHT);
937 Double_t part1 = x1*cosTheta*cosPhi + y1*cosTheta*sinPhi + z1*sinTheta;
938 Double_t part2 = x2*cosTheta*cosPhi + y2*cosTheta*sinPhi + z2*sinTheta;
939 return 1e9 * (part1 - part2) / C_LIGHT;
963 AnitaLocations::LONGITUDE_TD,
964 AnitaLocations::LATITUDE_TD,
965 AnitaLocations::ALTITUDE_TD);
968 Double_t UsefulAdu5Pat::getDeltaTTaylorOpt(Int_t ant1, Int_t ant2, Double_t *deltaR, Double_t *deltaZ, Double_t *deltaPhi)
970 return getDeltaTExpectedOpt(ant1, ant2,
971 AnitaLocations::LONGITUDE_TD,
972 AnitaLocations::LATITUDE_TD,
973 AnitaLocations::ALTITUDE_TD,
974 deltaR, deltaZ,deltaPhi);
978 Double_t UsefulAdu5Pat::getDeltaTExpectedOpt(Int_t ant1, Int_t ant2,Double_t sourceLon, Double_t sourceLat, Double_t sourceAlt, Double_t *deltaR, Double_t *deltaZ, Double_t *deltaPhi)
980 Double_t tempTheta,tempPhi;
981 if(fSourceAltitude!=sourceAlt || fSourceLongitude!=sourceLon || fSourceLatitude!=sourceLat)
987 Double_t r1=geom->
getAntR(ant1)+deltaR[ant1];
988 Double_t z1=geom->
getAntZ(ant1)+deltaZ[ant1];
991 Double_t r2=geom->
getAntR(ant2)+deltaR[ant2];
992 Double_t z2=geom->
getAntZ(ant2)+deltaZ[ant2];
996 Double_t tanThetaW=TMath::Tan(fThetaWave);
997 Double_t part1=z1*tanThetaW - r1 * TMath::Cos(fPhiWave-phi1);
998 Double_t part2=z2*tanThetaW - r2 * TMath::Cos(fPhiWave-phi2);
1000 return 1e9*((TMath::Cos(fThetaWave) * (part1 - part2))/C_LIGHT);
1004 Double_t UsefulAdu5Pat::getDeltaTSeaveyOpt(Int_t ant1, Int_t ant2, Double_t *deltaR, Double_t *deltaZ, Double_t *deltaPhi)
1006 return getDeltaTExpectedSeaveyOpt(ant1, ant2,
1010 deltaR, deltaZ,deltaPhi);
1013 Double_t UsefulAdu5Pat::getDeltaTExpectedSeaveyOpt(Int_t ant1, Int_t ant2,Double_t sourceLon, Double_t sourceLat, Double_t sourceAlt, Double_t *deltaR, Double_t *deltaZ, Double_t *deltaPhi)
1015 Double_t tempTheta,tempPhi;
1016 if(fSourceAltitude!=sourceAlt || fSourceLongitude!=sourceLon || fSourceLatitude!=sourceLat){
1023 Double_t r1=geom->
getAntR(ant1)+deltaR[ant1];
1024 Double_t z1=geom->
getAntZ(ant1)+deltaZ[ant1];
1027 Double_t r2=geom->
getAntR(ant2)+deltaR[ant2];
1028 Double_t z2=geom->
getAntZ(ant2)+deltaZ[ant2];
1032 Double_t tanThetaW=TMath::Tan(fThetaWave);
1033 Double_t part1=z1*tanThetaW - r1 * TMath::Cos(fPhiWave-phi1);
1034 Double_t part2=z2*tanThetaW - r2 * TMath::Cos(fPhiWave-phi2);
1036 return 1e9*((TMath::Cos(fThetaWave) * (part1 - part2))/C_LIGHT);
1040 UInt_t UsefulAdu5Pat::getTaylorDomeTriggerTimeNs()
const 1043 AnitaLocations::LONGITUDE_TD,
1044 AnitaLocations::ALTITUDE_TD);
1050 AnitaLocations::getWaisLongitude(),
1051 AnitaLocations::getWaisAltitude());
1073 Double_t pTaylor[3]={0};
1078 Double_t s2 = ((pTaylor[0]-fBalloonCoords[0])*(pTaylor[0]-fBalloonCoords[0]) +
1079 (pTaylor[1]-fBalloonCoords[1])*(pTaylor[1]-fBalloonCoords[1]) +
1080 (pTaylor[2]-fBalloonCoords[2])*(pTaylor[2]-fBalloonCoords[2]));
1081 Double_t distanceToFly=TMath::Sqrt(s2);
1082 return distanceToFly;
1092 Double_t timeOfFlight=distanceToFly/C_LIGHT;
1095 Double_t expTime=timeOfFlight;
1096 UInt_t expTrigTime=(UInt_t)expTime;
1106 Double_t UsefulAdu5Pat::getAngleBetweenPayloadAndSource(Double_t sourceLon, Double_t sourceLat, Double_t sourceAlt) {
1114 Double_t radiusSource=geom->
getGeoid(thetaSource)+sourceAlt;
1117 fSourcePos.SetX(radiusSource*TMath::Sin(thetaSource)*TMath::Cos(phiSource));
1118 fSourcePos.SetY(radiusSource*TMath::Sin(thetaSource)*TMath::Sin(phiSource));
1119 fSourcePos.SetZ(radiusSource*TMath::Cos(thetaSource));
1123 fSourcePos.RotateZ(-1*phiBalloon);
1124 fSourcePos.RotateY(-1*thetaBalloon);
1126 Double_t dotProduct=balloonHeight*fSourcePos.Z();
1127 Double_t magSource=TMath::Sqrt(fSourcePos.X()*fSourcePos.X() + fSourcePos.Y()*fSourcePos.Y()+fSourcePos.Z()*fSourcePos.Z());
1128 Double_t magBalloon=balloonHeight;
1130 Double_t phiEarthCenter=TMath::ACos(TMath::Abs(dotProduct/(magSource*magBalloon)));
1132 return phiEarthCenter;
1149 TTimeStamp theTime = this->
realTime;
1154 theTime.GetTime(
true,0,&hour,&min,&sec);
1155 Int_t
timeOfDay = hour*3600 + min*60 + sec;
1159 Int_t secondsPerDay = (24*60*60);
1160 Double_t zeroLonAngleToSun = 360*Double_t(
timeOfDay)/secondsPerDay;
1163 zeroLonAngleToSun-=180.;
1164 Double_t thisLonAngleToSun = zeroLonAngleToSun+this->
longitude;
1166 while(thisLonAngleToSun<-180) thisLonAngleToSun+=360.;
1167 while(thisLonAngleToSun>180) thisLonAngleToSun-=360.;
1169 return thisLonAngleToSun;
1184 Double_t sunAngleAtHeading = sunAngle + this->
heading;
1186 while(sunAngleAtHeading<-180) sunAngleAtHeading+=360;
1187 while(sunAngleAtHeading>180) sunAngleAtHeading-=360;
1189 return sunAngleAtHeading;
1207 if(phiAngle>9999 || phiAngle<-9999){
1208 std::cerr <<
"UsefulAdu5Pat::getDifferencePointingToSun() " << phiAngle <<
" ignore\n";
1214 Double_t angleFromSun=0;
1215 if(inputInDegrees==
false){
1216 angleFromSun = sunAngle - phiAngle*TMath::RadToDeg();
1219 angleFromSun = sunAngle - phiAngle;
1222 while(angleFromSun<-180){
1225 while(angleFromSun>=180){
1230 return angleFromSun;
1247 const Double_t dEarthMeanRadius = 6371.01;
1248 const Double_t dAstronomicalUnit =149597890;
1252 UInt_t year, month, day;
1253 timeStamp.GetDate(
true, 0, &year, &month, &day);
1254 UInt_t hour, min, sec;
1255 timeStamp.GetTime(
true, 0, &hour, &min, &sec);
1261 Int_t iMonth = month;
1266 Double_t dZenithAngle;
1267 Double_t dElapsedJulianDays;
1268 Double_t dDecimalHours;
1269 Double_t dEclipticLongitude;
1270 Double_t dEclipticObliquity;
1271 Double_t dRightAscension;
1272 Double_t dDeclination;
1281 Double_t dJulianDate;
1285 dDecimalHours = (double)hour + ((
double)min + (double)sec / 60.0 ) / 60.0;
1287 liAux1 =(iMonth-14)/12;
1288 liAux2=(1461*(iYear + 4800 + liAux1))/4 + (367*(iMonth
1289 - 2-12*liAux1))/12- (3*((iYear + 4900
1290 + liAux1)/100))/4+iDay-32075;
1291 dJulianDate=(double)(liAux2)-0.5+dDecimalHours/24.0;
1293 dElapsedJulianDays = dJulianDate-2451545.0;
1300 Double_t dMeanLongitude;
1301 Double_t dMeanAnomaly;
1303 dOmega=2.1429-0.0010394594*dElapsedJulianDays;
1304 dMeanLongitude = 4.8950630+ 0.017202791698*dElapsedJulianDays;
1305 dMeanAnomaly = 6.2400600+ 0.0172019699*dElapsedJulianDays;
1306 dEclipticLongitude = dMeanLongitude + 0.03341607*sin( dMeanAnomaly )
1307 + 0.00034894*sin( 2*dMeanAnomaly )-0.0001134
1308 -0.0000203*sin(dOmega);
1309 dEclipticObliquity = 0.4090928 - 6.2140e-9*dElapsedJulianDays
1310 +0.0000396*cos(dOmega);
1317 Double_t dSin_EclipticLongitude;
1318 dSin_EclipticLongitude= sin( dEclipticLongitude );
1319 dY = cos( dEclipticObliquity ) * dSin_EclipticLongitude;
1320 dX = cos( dEclipticLongitude );
1321 dRightAscension = atan2( dY,dX );
1322 if( dRightAscension < 0.0 ) dRightAscension = dRightAscension + TMath::TwoPi();
1323 dDeclination = asin( sin( dEclipticObliquity )*dSin_EclipticLongitude );
1328 Double_t dGreenwichMeanSiderealTime;
1329 Double_t dLocalMeanSiderealTime;
1330 Double_t dLatitudeInRadians;
1331 Double_t dHourAngle;
1332 Double_t dCos_Latitude;
1333 Double_t dSin_Latitude;
1334 Double_t dCos_HourAngle;
1336 dGreenwichMeanSiderealTime = 6.6974243242 +
1337 0.0657098283*dElapsedJulianDays
1339 dLocalMeanSiderealTime = (dGreenwichMeanSiderealTime*15
1341 dHourAngle = dLocalMeanSiderealTime - dRightAscension;
1342 dLatitudeInRadians =
latitude*TMath::DegToRad();
1343 dCos_Latitude = cos( dLatitudeInRadians );
1344 dSin_Latitude = sin( dLatitudeInRadians );
1345 dCos_HourAngle= cos( dHourAngle );
1346 dZenithAngle = (acos( dCos_Latitude*dCos_HourAngle
1347 *cos(dDeclination) + sin( dDeclination )*dSin_Latitude));
1348 dY = -sin( dHourAngle );
1349 dX = tan( dDeclination )*dCos_Latitude - dSin_Latitude*dCos_HourAngle;
1350 dAzimuth = atan2( dY, dX );
1351 if ( dAzimuth < 0.0 )
1352 dAzimuth = dAzimuth + TMath::TwoPi();
1353 dAzimuth = dAzimuth/TMath::DegToRad();
1355 dParallax=(dEarthMeanRadius/dAstronomicalUnit)
1357 dZenithAngle=(dZenithAngle
1358 + dParallax)/TMath::DegToRad();
1369 while(phiDeg < -180) phiDeg += 360;
1370 while(phiDeg >= 180) phiDeg -= 360;
1373 thetaDeg = dZenithAngle - 90;
1381 Double_t * lon_ptr, Double_t * lat_ptr, Double_t * alt_ptr,
1382 Double_t * adj_ptr, Double_t max_adjust, Int_t max_iter)
const {
1385 std::cerr <<
"Debug info in " << __PRETTY_FUNCTION__ <<
":\n";
1389 if (thetaWave + max_adjust < 0){
1391 std::cerr <<
"thetaWave + max_adjust < 0... no chance! returning 0!" << std::endl;
1396 Double_t lon,lat,alt;
1397 Double_t last_theta_tried =0;
1398 Double_t last_successful_theta = 0;
1399 Double_t last_failed_theta = 0;
1401 double last_good_lat = -9999;
1402 double last_good_lon = -9990;
1403 double last_good_alt = -9999;
1406 while(iter++ < max_iter)
1408 Double_t theta_try = last_theta_tried == 0 ? thetaWave
1409 : last_theta_tried == thetaWave
1410 ? thetaWave+max_adjust
1411 : (last_successful_theta + last_failed_theta)/2;
1414 std::cerr <<
"iter = " << iter <<
", theta_try (degrees) = " << theta_try*TMath::RadToDeg()
1415 <<
", last_successful_theta (degrees) = " << last_successful_theta*TMath::RadToDeg() <<
"\n";
1418 last_theta_tried = theta_try;
1426 const int crazyNumberOfPowersOfTen = 2;
1427 while(success==3 && moarLoops < crazyNumberOfPowersOfTen){
1428 int maxLoopIter = fMaxLoopIterations * pow(10, 1+moarLoops);
1430 std::cerr <<
"Got non-convergent solution in getSourceLonAndLatAtAlt2... will try again with " << maxLoopIter <<
" loops...\n";
1440 std::cerr <<
"getSourceLonAndLatAtAlt2: success = " << success <<
"\n";
1443 if (success == 1 || success == 2)
1447 if (lon_ptr) *lon_ptr = lon;
1448 if (lat_ptr) *lat_ptr = lat;
1449 if (alt_ptr) *alt_ptr = alt;
1450 if (adj_ptr) *adj_ptr = 0;
1452 std::cerr <<
"success on first try! Returning 1" << std::endl;
1458 last_good_lat = lat;
1459 last_good_lon = lon;
1460 last_good_alt = alt;
1461 last_successful_theta = theta_try;
1466 if (theta_try == thetaWave + max_adjust)
1469 std::cerr <<
"theta_try = thetaWave + max_adjust = " << theta_try <<
"... it's hopeless! returning 0" << std::endl;
1475 last_failed_theta = theta_try;
1479 if (lat_ptr) *lat_ptr = last_good_lat;
1480 if (lon_ptr) *lon_ptr = last_good_lon;
1481 if (alt_ptr) *alt_ptr = last_good_alt;
1482 if (adj_ptr) *adj_ptr = last_successful_theta - thetaWave;
1485 std::cerr <<
"Got here! Returning 2... iter = " << iter
1486 <<
", last_successful_theta (degrees) = " << last_successful_theta*TMath::RadToDeg()
1487 <<
", adjustment (degrees) = " << (last_successful_theta - thetaWave)*TMath::RadToDeg()
1499 Double_t result = -9999;
1500 const Double_t EARTH_POLAR_RADIUS = 6378000;
1502 Double_t theta = M_PI / 2.0 - (el * M_PI / 180.0);
1503 Double_t er = EARTH_POLAR_RADIUS;
1504 Double_t plH = er + plAlt;
1505 Double_t costr = cos(theta);
1506 Double_t d = -plH*costr - sqrt(plH*plH*costr*costr - 2*er*(plAlt-imAlt) - plAlt*plAlt + imAlt*imAlt);
1508 Double_t alpha = d * sin(theta) / (er+imAlt);
1510 Double_t td = M_PI + 2*alpha - theta;
1511 result = (90.0 - 180.0*td/M_PI);
1523 #if ROOT_VERSION_CODE < ROOT_VERSION(6,0,0) 1524 std::cerr <<
"Your version of ROOT does not support all the features of eventReaderRoot\n";
1530 double Az = phiWave -
heading;
1531 double el = -thetaWave;
1541 double dec = asin( sin(lat) * sin(el) + cos(lat) *cos(el) *cos(Az));
1544 double h = atan2 ( sin(Az) , -cos(Az)* sin(lat) + tan(el) * cos(lat));
1561 if (RA_ptr) *RA_ptr = RA * 12 / M_PI;
1562 if (dec_ptr) *dec_ptr = dec* 180 / M_PI;
1564 if (!l_ptr && ! b_ptr)
return 0;
1568 double b1950 = 2433282.4235;
1569 double jd = ts.AsJulianDate();
1571 double T = ( jd - 2451545) / (36525);
1572 double t = (b1950 - jd) / 36525;
1573 double sectodeg = 1./3600 ;
1576 double zeta = (2306.2181*sectodeg+1.39656*sectodeg*T-0.000139*sectodeg*T*T)*t+
1577 (0.30188*sectodeg-0.000344*sectodeg*T)*t*t+
1578 0.017998*sectodeg*t*t*t;
1579 double z = (2306.2181*sectodeg+1.39656*sectodeg*T-0.000139*sectodeg*T*T)*t+
1580 (1.09468*sectodeg+0.000066*sectodeg*T)*t*t+
1581 0.018203*sectodeg*t*t*t;
1582 double theta = (2004.3109*sectodeg-0.85330*sectodeg*T-0.000217*sectodeg*T*T)*t-
1583 (0.42665*sectodeg+0.000217*sectodeg*T)*t*t+0.041833*sectodeg*t*t*t;
1589 double A = cos(dec)*sin(RA+zeta);
1590 double B = cos(theta)*cos(dec)*cos(RA+zeta)-sin(theta)*sin(dec);
1591 double C = sin(theta)*cos(dec)*cos(RA+zeta)+cos(theta)*sin(dec);
1593 double ra1950 = (atan2(A,B)+z);
1594 double dec1950 = asin(C);
1599 *l_ptr = 303 - 180 / M_PI *
1600 atan2( sin(192.25 * M_PI/180 - ra1950),
1601 cos (192.25 * M_PI/180 - ra1950) * sin(27.5 * M_PI/180) - tan(dec1950) * cos (27.4 * M_PI/180)
1604 while (*l_ptr > 180) *l_ptr -= 360 ;
1605 while (*l_ptr < -180) *l_ptr += 360 ;
1613 *b_ptr = 180 / M_PI * asin(
1614 sin(dec1950) * sin(27.4 * M_PI/180) +
1615 cos(dec1950) * cos(27.4 * M_PI/180) * cos (192.25 * M_PI/180 - ra1950)
1624 int UsefulAdu5Pat::fromRADec(
int N,
const Double_t * RA,
const Double_t * dec, Double_t * phi, Double_t *theta)
const 1626 #if ROOT_VERSION_CODE < ROOT_VERSION(6,0,0) 1627 std::cerr <<
"Your version of ROOT does not support all the features of eventReaderRoot\n";
1637 double lat =
latitude * (M_PI /180);
1638 double sin_lat = sin(lat);
1639 double cos_lat = cos(lat);
1644 #ifdef ENABLE_VECTORIZE 1645 int nit = N / VEC_N;
1647 istart = nit * VEC_N;
1654 VEC vsin_lat(sin_lat);
1655 VEC vcos_lat(cos_lat);
1668 for (
int i = 0; i < nit; i++)
1670 vra.load(RA+i*VEC_N);
1671 vdec.load(dec+i*VEC_N);
1676 vcos_dec = cos(vdec);
1677 vsin_dec = sin(vdec);
1681 vaz = atan2(vcos_dec * vsin_h, -vcos_h * vsin_lat * vcos_dec + vsin_dec * vcos_lat);
1682 vel = asin(vsin_lat * vsin_dec + vcos_lat * vcos_dec * vcos_h);
1684 vphi = vheading + vaz * 180/M_PI;
1685 vtheta = -vel * 180/M_PI;
1686 vphi = vphi - 360 * floor(vphi/360) ;
1688 vphi.store(phi+i*VEC_N);
1689 vtheta.store(theta+i*VEC_N);
1696 for (
int i = istart; i < N; i++)
1698 double h = lst - RA[i];
1700 double dc = dec[i] * M_PI/180;
1702 double Az = atan2( cos(dc) * sin(h), -cos(h) * sin_lat* cos(dc) + sin(dc) * cos_lat);
1703 double el = asin(sin_lat * sin(dc) + cos_lat * cos(dc) * cos(h));
1706 theta[i] = - el * (180/M_PI);
1715 int UsefulAdu5Pat::fromRADec(Double_t RA, Double_t dec, Double_t * phi, Double_t *theta)
const 1717 #if ROOT_VERSION_CODE < ROOT_VERSION(6,0,0) 1718 std::cerr <<
"Your version of ROOT does not support all the features of eventReaderRoot\n";
1727 double h = lst - RA;
1731 double lat =
latitude * (M_PI /180);
1732 double Az = atan2( cos(dec) * sin(h), -cos(h) * sin(lat)* cos(dec) + sin(dec) * cos(lat));
1733 double el = asin(sin(lat) * sin(dec) + cos(lat) * cos(dec) * cos(h));
1735 if (phi) *phi =
heading + Az * (180/M_PI);
1736 if (theta) *theta = - el * (180/M_PI);
1747 void UsefulAdu5Pat::getThetaAndPhiWaveHiCal(Double_t& thetaWave, Double_t& phiWave){
1749 Double_t hiCalLon, hiCalLat, hiCalAlt;
1752 if(hiCalAlt == -9999){
1767 tstep = fabs(tstep);
1768 if (!plus) tstep *= -1;
1770 double last_theta, last_phi;
1778 test = p0 - v0*tstep*istep;
1782 if (fabs(theta-last_theta) < eps && fabs(phi-last_phi) < eps)
1784 if (testp) *testp = test;
Double_t getDeltaTWillyBorehole(Int_t ant1, Int_t ant2)
const Double_t LATITUDE_SIPLE
Latitude of Siple dome pulser.
int getSourceLonAndLatAtDesiredAlt(Double_t phiWave, Double_t thetaWave, Double_t &sourceLon, Double_t &sourceLat, Double_t desiredAlt)
Destructor.
Double_t getDifferencePointingToSun(Double_t phiAngle, Bool_t inputInDegrees=true) const
Quick way of getting difference between any azimuth phi and the sun's azimuth phi.
int getSourceLonAndLatAtAlt2(Double_t phiWave, Double_t thetaWave, Double_t &sourceLon, Double_t &sourceLat, Double_t &sourceAltitude, Int_t maxLoopIter=-1, TVector3 *sourcePosOptional=NULL) const
TVector3 getUnitVectorAlongThetaWavePhiWave(double thetaWave, double phiWave) const
static void hiCal(UInt_t unixTime, Double_t &longitude, Double_t &latitude, Double_t &altitude)
static Double_t getReflectionAngle(Double_t plAlt, Double_t imageEl, Double_t imageAlt)
Currently just does direct events...
Adu5Pat – The ADU5 Position and Attitude Data.
void getThetaAndPhiWaveLDB(Double_t &thetaWave, Double_t &phiWave)
UInt_t getWaisDivideTriggerTimeNs() const
Gets the time of flight to Taylor Dome.
Float_t latitude
In degrees.
void getThetaAndPhiWaveWillySeavey(Double_t &thetaWave, Double_t &phiWave)
Float_t longitude
In degrees.
UInt_t realTime
Time from the GPS unit.
UInt_t getTriggerTimeNsFromSource(Double_t sourceLat, Double_t sourceLong, Double_t sourceAlt) const
Gets the time of flight to LDB camp.
void getThetaWaveAtBase(Double_t baseLon, Double_t baseLat, Double_t baseAlt, Double_t &thetaWave)
void getThetaAndPhiWave(Double_t sourceLon, Double_t sourceLat, Double_t sourceAlt, Double_t &thetaWave, Double_t &phiWave)
const double LONGITUDE_SURF_SEAVEY
Longitude of surface seavey.
UInt_t getLDBTriggerTimeNs() const
Gets the time of flight to Siple.
void setMaxLoopIterations(Int_t n=50)
double surfaceAboveGeoid(Double_t lon, Double_t lat) const
UInt_t getSipleTriggerTimeNs() const
Gets the time of flight to Wais Divide.
Double_t getDeltaTExpected(Int_t ant1, Int_t ant2, Double_t sourceLon, Double_t sourceLat, Double_t sourceAlt)
void getThetaAndPhiWaveWaisDivide(Double_t &thetaWave, Double_t &phiWave)
Float_t altitude
In metres.
const double ALTITUDE_BH
Altitude of borehole antenna.
void getThetaAndPhiWaveTaylorDome(Double_t &thetaWave, Double_t &phiWave)
Double_t getAzimuthOfSunRelativeToNorth() const
Calculates the azimuth position of the sun if ANITA was facing directly north, relies on timeOfDay...
Double_t getDeltaTTaylor(Int_t ant1, Int_t ant2)
Double_t getAzimuthOfSun() const
void getSunPosition(Double_t &phiDeg, Double_t &thetaDeg) const
Uses realTime, latitude, longitude to calculate the sun's position.
void getThetaAndPhiWaveCart(TVector3 *sourcePos, Double_t &thetaWave, Double_t &phiWave) const
~UsefulAdu5Pat()
Assignment constructor.
const Double_t LATITUDE_LDB
Latitude at LDB.
Double_t getDeltaTWillySeavey(Int_t ant1, Int_t ant2)
As UsefulAnitaEvent is to RawAnitaEvent, UsefulAdu5Pat is to Adu5Pat. Well not quite as useful but yo...
const Double_t LONGITUDE_LDB
Longitude at LDB.
int getSourceLonAndLatAtAlt(Double_t phiWave, Double_t thetaWave, Double_t &sourceLon, Double_t &sourceLat, Double_t &sourceAltitude)
const double ALTITUDE_SURF_SEAVEY
Altitude of surface seavey.
int traceBackToContinent(Double_t phiWave, Double_t thetaWave, Double_t *lon, Double_t *lat, Double_t *alt, Double_t *theta_adjustment_required, Double_t max_theta_adjustment=TMath::Pi()/180, Int_t max_iter=10) const
const double LONGITUDE_BH
Longitude of borehole antenna.
Double_t getDistanceFromSource(Double_t sourceLat, Double_t sourceLong, Double_t sourceAlt) const
Gets time of flight from any source.
UInt_t timeOfDay
in ms since the start of the day
const Double_t LONGITUDE_SIPLE
Longitude of Siple dome pulser.
int astronomicalCoordinates(Double_t phiWave, Double_t thetaWave, Double_t *RA=0, Double_t *dec=0, Double_t *l=0, Double_t *b=0) const
void updateCartesianBalloonInfo()
const Double_t ALTITUDE_SIPLE
Altitude of Siple dome pulser according to http://mapcarta.com/25623620.
Float_t heading
0 is facing north, 180 is facing south
int traceBackToContinent3(Double_t phiWave, Double_t thetaWave, Double_t *lon, Double_t *lat, Double_t *alt, Double_t *theta_adjustment_required) const
void getThetaAndPhiWaveOfRayAtInfinity(const TVector3 &p0, const TVector3 &v0, Double_t &thetaWave, Double_t &phiWave, Bool_t plus_infinity=true, Double_t eps=0.00001 *TMath::DegToRad(), Double_t step=10e7, TVector3 *testPosition=0) const
void getThetaAndPhiWave2(Double_t sourceLon, Double_t sourceLat, Double_t sourceAlt, Double_t &thetaWave, Double_t &phiWave, TVector3 *sourcePos=NULL) const
const double LATITUDE_SURF_SEAVEY
Latitude of surface seavey.
const double LATITUDE_BH
Latitude if borehole antenna.
const Double_t ALTITUDE_LDB
Altitude at LDB.