Changeset 1452 for trunk/external/atnf/PKSIO/MBFITSreader.cc
- Timestamp:
- 11/19/08 20:41:16 (16 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/external/atnf/PKSIO/MBFITSreader.cc
r1427 r1452 27 27 //# AUSTRALIA 28 28 //# 29 //# $Id: MBFITSreader.cc,v 19. 38 2008-06-26 02:24:22cal103 Exp $29 //# $Id: MBFITSreader.cc,v 19.54 2008-11-17 06:51:55 cal103 Exp $ 30 30 //#--------------------------------------------------------------------------- 31 31 //# The MBFITSreader class reads single dish RPFITS files (such as Parkes … … 35 35 //#--------------------------------------------------------------------------- 36 36 37 #include <atnf/pks/pks_maths.h> 37 38 #include <atnf/PKSIO/MBFITSreader.h> 38 #include <atnf/PKSIO/PKSMBrecord.h> 39 40 #include <RPFITS.h> 39 #include <atnf/PKSIO/MBrecord.h> 41 40 42 41 #include <casa/math.h> … … 47 46 #include <unistd.h> 48 47 48 #include <RPFITS.h> 49 49 50 using namespace std; 50 51 … … 52 53 const double PI = 3.141592653589793238462643; 53 54 const double TWOPI = 2.0 * PI; 55 const double HALFPI = PI / 2.0; 54 56 const double R2D = 180.0 / PI; 55 57 … … 93 95 94 96 cMBopen = 0; 97 98 // Tell RPFITSIN not to report errors directly. 99 iostat_.errlun = -1; 100 101 // By default, messages are written to stderr. 102 initMsg(); 95 103 } 96 104 … … 121 129 int &extraSysCal) 122 130 { 131 // Clear the message stack. 132 clearMsg(); 133 123 134 if (cMBopen) { 124 135 close(); … … 129 140 // Open the RPFITS file. 130 141 int jstat = -3; 131 rpfitsin_(&jstat, cVis, cWgt, &cBaseline, &cUTC, &cU, &cV, &cW, &cFlag, 132 &cBin, &cIFno, &cSrcNo); 133 134 if (jstat) { 135 fprintf(stderr, "ERROR, failed to open MBFITS file: %s\n", rpname); 142 if (rpfitsin(jstat)) { 143 sprintf(cMsg, "ERROR: failed to open MBFITS file\n %s", rpname); 144 logMsg(cMsg); 136 145 return 1; 137 146 } … … 149 158 // Read the first header. 150 159 jstat = -1; 151 rpfitsin_(&jstat, cVis, cWgt, &cBaseline, &cUTC, &cU, &cV, &cW, &cFlag, 152 &cBin, &cIFno, &cSrcNo); 153 154 if (jstat) { 155 fprintf(stderr, "ERROR, failed to read MBFITS header: %s\n", rpname); 160 if (rpfitsin(jstat)) { 161 sprintf(cMsg, "ERROR: failed to read MBFITS header in file\n" 162 " %s", rpname); 163 logMsg(cMsg); 156 164 close(); 157 165 return 1; … … 163 171 // Non-ATNF data may not store the position in (u,v,w). 164 172 if (strncmp(names_.sta, "tid", 3) == 0) { 165 fprintf(stderr, "WARNING, found Tidbinbilla data");173 sprintf(cMsg, "WARNING: Found Tidbinbilla data"); 166 174 cSUpos = 1; 167 175 } else if (strncmp(names_.sta, "HOB", 3) == 0) { 168 fprintf(stderr, "WARNING, found Hobart data");176 sprintf(cMsg, "WARNING: Found Hobart data"); 169 177 cSUpos = 1; 170 178 } else if (strncmp(names_.sta, "CED", 3) == 0) { 171 fprintf(stderr, "WARNING, found Ceduna data");179 sprintf(cMsg, "WARNING: Found Ceduna data"); 172 180 cSUpos = 1; 173 181 } else { … … 176 184 177 185 if (cSUpos) { 178 fprintf(stderr, ", using telescope position from SU table.\n"); 186 strcat(cMsg, ", using telescope position\n from SU table."); 187 logMsg(cMsg); 179 188 cInterp = 0; 180 189 } 190 191 // Mean scan rate (for timestamp repairs). 192 cNRate = 0; 193 cAvRate[0] = 0.0; 194 cAvRate[1] = 0.0; 195 cCode5 = 0; 181 196 182 197 … … 190 205 191 206 if (cNBeam <= 0) { 192 fprintf(stderr, "ERROR, couldn't determine number of beams.\n");207 logMsg("ERROR, couldn't determine number of beams."); 193 208 close(); 194 209 return 1; … … 203 218 // ...beams present in the data. 204 219 for (int iBeam = 0; iBeam < anten_.nant; iBeam++) { 205 cBeams[anten_.ant_num[iBeam] - 1] = 1; 220 // Guard against dubious beam numbers, e.g. zeroes in 221 // 1999-09-29_1632_024848p14_071b.hpf and the four scans following. 222 // Note that the actual beam number is decoded from the 'baseline' random 223 // parameter for each spectrum and is only used for beam selection. 224 int beamNo = anten_.ant_num[iBeam]; 225 if (beamNo != iBeam+1) { 226 char sta[8]; 227 strncpy(sta, names_.sta+(8*iBeam), 8); 228 char *cp = sta + 7; 229 while (*cp == ' ') *(cp--) = '\0'; 230 231 sprintf(cMsg, 232 "WARNING: RPFITSIN returned beam number %2d for AN table\n" 233 " entry %2d with name '%.8s'", beamNo, iBeam+1, sta); 234 235 char text[8]; 236 sprintf(text, "MB%2.2d", iBeam+1); 237 cp = cMsg + strlen(cMsg); 238 if (strncmp(sta, text, 8) == 0) { 239 beamNo = iBeam + 1; 240 sprintf(cp, "; using beam number %2d.", beamNo); 241 } else { 242 sprintf(cp, "."); 243 } 244 245 logMsg(cMsg); 246 } 247 248 if (0 < beamNo && beamNo <= cNBeam) { 249 cBeams[beamNo-1] = 1; 250 } 206 251 } 207 252 … … 292 337 // Read the first syscal record. 293 338 if (rpget(1, cEOS)) { 294 fprintf(stderr, "ERROR, failed to read first syscal record.\n");339 logMsg("ERROR, failed to read first syscal record."); 295 340 close(); 296 341 return 1; … … 328 373 { 329 374 if (!cMBopen) { 330 fprintf(stderr, "ERROR, an MBFITS file has not been opened.\n");375 logMsg("ERROR, an MBFITS file has not been opened."); 331 376 return 1; 332 377 } … … 348 393 antPos[1] = 2816759.046; 349 394 antPos[2] = -3454035.950; 395 350 396 } else if (strncmp(names_.sta, "HOH", 3) == 0) { 351 397 // Parkes HOH receiver. … … 354 400 antPos[1] = 2816759.046; 355 401 antPos[2] = -3454035.950; 402 356 403 } else if (strncmp(names_.sta, "CA0", 3) == 0) { 357 404 // An ATCA antenna, use the array centre position. … … 360 407 antPos[1] = 2792906.182; 361 408 antPos[2] = -3200483.747; 409 410 // ATCA-104. Updated position at epoch 2007/06/24 from Chris Phillips. 411 // antPos[0] = -4751640.182; // ± 0.008 412 // antPos[1] = 2791700.322; // ± 0.006 413 // antPos[2] = -3200490.668; // ± 0.007 414 // 362 415 } else if (strncmp(names_.sta, "MOP", 3) == 0) { 363 // Mopra. 416 // Mopra. Updated position at epoch 2007/06/24 from Chris Phillips. 364 417 sprintf(telescope, "%-16.16s", "ATMOPRA"); 365 antPos[0] = -4682768.630; 366 antPos[1] = 2802619.060; 367 antPos[2] = -3291759.900; 418 antPos[0] = -4682769.444; // ± 0.009 419 antPos[1] = 2802618.963; // ± 0.006 420 antPos[2] = -3291758.864; // ± 0.008 421 368 422 } else if (strncmp(names_.sta, "HOB", 3) == 0) { 369 423 // Hobart. … … 372 426 antPos[1] = 2522347.567; 373 427 antPos[2] = -4311562.569; 428 374 429 } else if (strncmp(names_.sta, "CED", 3) == 0) { 375 // Ceduna. 430 // Ceduna. Updated position at epoch 2007/06/24 from Chris Phillips. 376 431 sprintf(telescope, "%-16.16s", "CEDUNA"); 377 antPos[0] = -3749943.657; 378 antPos[1] = 3909017.709; 379 antPos[2] = -3367518.309; 432 antPos[0] = -3753443.168; // ± 0.017 433 antPos[1] = 3912709.794; // ± 0.017 434 antPos[2] = -3348067.060; // ± 0.016 435 380 436 } else if (strncmp(names_.sta, "tid", 3) == 0) { 381 437 // DSS. … … 448 504 //--------------------------------------------------------- MBFITSreader::read 449 505 450 // Read the next data record .506 // Read the next data record (if you're feeling lucky). 451 507 452 508 int MBFITSreader::read( 453 PKSMBrecord &MBrec)509 MBrecord &MBrec) 454 510 { 455 511 int beamNo = -1; 456 int haveData, status; 457 PKSMBrecord *iMBuff = 0x0; 512 int haveData, pCode = 0, status; 513 double raRate = 0.0, decRate = 0.0, paRate = 0.0; 514 MBrecord *iMBuff = 0x0; 458 515 459 516 if (!cMBopen) { 460 fprintf(stderr, "ERROR, an MBFITS file has not been opened.\n");517 logMsg("ERROR, an MBFITS file has not been opened."); 461 518 return 1; 462 519 } 463 520 464 // Positions recorded in the input records do not coincide with the midpoint465 // of the integration and hence the input must be buffered so that true466 // positions may be interpolated.521 // Positions recorded in the input records usually do not coincide with the 522 // midpoint of the integration and hence the input must be buffered so that 523 // true positions may be interpolated. 467 524 // 468 525 // On the first call nBeamSel buffers of length nBin, are allocated and … … 494 551 495 552 // Read the next record. 553 pCode = 0; 496 554 if ((status = rpget(0, cEOS)) == -1) { 497 555 // EOF. … … 502 560 503 561 #ifdef PKSIO_DEBUG 504 printf("\nEnd-of-file detected, flushing last scan.\n");562 fprintf(stderr, "\nEnd-of-file detected, flushing last cycle.\n"); 505 563 #endif 506 564 … … 586 644 587 645 if (cNBin > 1 && cNBeamSel > 1) { 588 fprintf(stderr, "ERROR, cannot handle binning mode for multiple " 589 "beams.\n"); 646 logMsg("ERROR, cannot handle binning mode for multiple beams."); 590 647 close(); 591 648 return 1; 592 649 } 593 650 594 // Allocate buffer data storage; the PKSMBrecord constructor zeroes651 // Allocate buffer data storage; the MBrecord constructor zeroes 595 652 // class members such as cycleNo that are tested in the first pass 596 653 // below. 597 654 int nBuff = cNBeamSel * cNBin; 598 cBuffer = new PKSMBrecord[nBuff];655 cBuffer = new MBrecord[nBuff]; 599 656 600 657 // Allocate memory for spectral arrays. … … 602 659 cBuffer[ibuff].setNIFs(simulIF); 603 660 cBuffer[ibuff].allocate(0, maxChan, maxXpol); 661 662 // Signal that this IF in this buffer has been flushed. 663 for (int iIF = 0; iIF < simulIF; iIF++) { 664 cBuffer[ibuff].IFno[iIF] = 0; 665 } 604 666 } 605 667 … … 609 671 cScanNo = 1; 610 672 cCycleNo = 0; 611 cPrevUTC = 0.0;673 cPrevUTC = -1.0; 612 674 } 613 675 … … 616 678 cScanNo++; 617 679 cCycleNo = 0; 618 cPrevUTC = 0.0;680 cPrevUTC = -1.0; 619 681 } 620 682 621 683 // Check for change-of-day. 622 if (cUTC < cPrevUTC - 85800.0) { 684 double cod = 0.0; 685 if ((cUTC + 86400.0) < (cPrevUTC + 600.0)) { 686 // cUTC should continue to increase past 86400 during a single scan. 687 // However, if the RPFITS file contains multiple scans that straddle 688 // midnight then cUTC can jump backwards from the end of one scan to 689 // the start of the next. 690 #ifdef PKSIO_DEBUG 691 fprintf(stderr, "Change-of-day on cUTC: %.1f -> %.1f", 692 cPrevUTC, cUTC); 693 #endif 694 // Can't change the recorded value of cUTC directly (without also 695 // changing dateobs) so change-of-day must be recorded separately as 696 // an offset to be applied when comparing integration timestamps. 697 cod = 86400.0; 698 699 } else if (cUTC < cPrevUTC - 1.0) { 700 sprintf(cMsg, 701 "WARNING: Cycle %d:%03d-%03d, UTC went backwards from\n" 702 " %.1f to %.1f! Incrementing day number,\n" 703 " positions may be unreliable.", cScanNo, cCycleNo, 704 cCycleNo+1, cPrevUTC, cUTC); 705 logMsg(cMsg); 623 706 cUTC += 86400.0; 624 707 } … … 630 713 631 714 // New integration cycle? 632 if ( cUTC> cPrevUTC) {715 if ((cUTC+cod) > cPrevUTC) { 633 716 cCycleNo++; 634 717 cPrevUTC = cUTC + 0.0001; … … 637 720 // Apply beam selection. 638 721 beamNo = int(cBaseline / 256.0); 722 if (beamNo == 1) { 723 // Store the position of beam 1 for grid convergence corrections. 724 cRA0 = cU; 725 cDec0 = cV; 726 } 639 727 iBeamSel = cBeamSel[beamNo-1]; 640 728 if (iBeamSel < 0) continue; … … 648 736 649 737 sprintf(cDateObs, "%-10.10s", names_.datobs); 738 cDateObs[10] = '\0'; 650 739 651 740 // Compute buffer number. … … 660 749 661 750 // Begin flush cycle? 662 if (cEOS || (iMBuff->nIF && cUTC > iMBuff->utc + 0.0001)) {751 if (cEOS || (iMBuff->nIF && (cUTC+cod) > (iMBuff->utc+0.0001))) { 663 752 cFlushing = 1; 664 753 cFlushBin = 0; … … 667 756 668 757 #ifdef PKSIO_DEBUG 669 printf("\n In:%4d%4d%3d%3d\n", cScanNo, cCycleNo, beamNo, cIFno); 670 if (cEOS) printf("Start of new scan, flushing previous scan.\n"); 758 char rel = '='; 759 double dt = utcDiff(cUTC, cW); 760 if (dt < 0.0) { 761 rel = '<'; 762 } else if (dt > 0.0) { 763 rel = '>'; 764 } 765 766 fprintf(stderr, "\n In:%4d%4d%3d%3d %.3f %c %.3f (%+.3fs) - " 767 "%sflushing\n", cScanNo, cCycleNo, beamNo, cIFno, cUTC, rel, cW, dt, 768 cFlushing ? "" : "not "); 769 if (cEOS) { 770 fprintf(stderr, "Start of new scan, flushing previous scan.\n"); 771 } 671 772 #endif 672 773 } … … 733 834 // as the 'u' and 'v' visibility coordinates, must be interpolated to 734 835 // the integration time which RPFITSIN returns as 'cUTC', this usually 735 // being a second or two later. 836 // being a second or two later. The interpolation method used here is 837 // based on the scan rate. 736 838 // 737 839 // "This" RA, Dec, and UTC refers to the position currently stored in 738 // the buffer marked for output (iMBuff). This position will be 739 // interpolated to the midpoint of that integration using the position 740 // recorded in the "next" integration which is currently sitting in the 741 // RPFITS commons. The interpolation method used here is based on the 742 // scan rate. At the end of a scan, or if the next position has not 743 // been updated, the most recent determination of the scan rate will be 744 // used for extrapolation. 840 // the buffer marked for output (iMBuff). This position is interpolated 841 // to the midpoint of that integration using either 842 // a) the rate currently sitting in iMBuff, which was computed from 843 // the previous integration, otherwise 844 // b) from the position recorded in the "next" integration which is 845 // currently sitting in the RPFITS commons, 846 // so that the position timestamps straddle the midpoint of the 847 // integration and is thereby interpolated rather than extrapolated. 745 848 // 746 // The rate "age" is the offset from "this" integration (in iMBuff) of747 // the earliest integration in the pair used to compute the rate. A748 // rate "age" of 0 thus refers to the normal situation where the rate749 // is determined from "this" integration and the "next" one. An age750 // of 1 cycle means that it is determined from "this" integration and751 // the one preceding it, which should be equally reliable. An age 752 // of 2 cycles means that the rate is determined from the previous753 // integration and the one before that, so the extrapolation spans one754 // integration cycle. Thus it has a "staleness" of 1.755 849 // At the end of a scan, or if the next position has not been updated 850 // or its timestamp does not advance sufficiently, the most recent 851 // determination of the scan rate will be used for extrapolation which 852 // is quantified by the "rate age" measured in seconds beyond the 853 // interval defined by the position timestamps. 854 855 // At this point, iMBuff contains cU, cV, cW, parAngle and focusRot 856 // stored from the previous call to rpget() for this beam (i.e. "this"), 857 // and also raRate, decRate and paRate computed from that integration 858 // and the previous one. 756 859 double thisRA = iMBuff->ra; 757 860 double thisDec = iMBuff->dec; 758 861 double thisUTC = cPosUTC[iBeamSel]; 862 double thisPA = iMBuff->parAngle + iMBuff->focusRot; 863 864 #ifdef PKSIO_DEBUG 865 fprintf(stderr, "This (%d) ra, dec, UTC: %9.4f %9.4f %10.3f %9.4f\n", 866 iMBuff->cycleNo, thisRA*R2D, thisDec*R2D, thisUTC, thisPA*R2D); 867 #endif 759 868 760 869 if (cEOF || cEOS) { 761 iMBuff->rateAge++; 762 iMBuff->rateson = 0; 763 870 // Use rates from the last cycle. 871 raRate = iMBuff->raRate; 872 decRate = iMBuff->decRate; 873 paRate = iMBuff->paRate; 874 764 875 } else { 765 // Note that the time recorded as the 'w' visibility coordinate 766 // cycles through 86400 back to 0 at midnight, whereas that in 'cUTC' 767 // continues to increase past 86400. 768 769 double nextRA = cU; 770 double nextDec = cV; 771 double nextUTC = cW; 772 773 if (nextUTC < thisUTC) { 774 // Must have cycled through midnight. 775 nextUTC += 86400.0; 776 } 777 778 // Guard against RA cycling through 24h in either direction. 779 if (fabs(nextRA - thisRA) > PI) { 780 if (nextRA < thisRA) { 781 nextRA += TWOPI; 876 if (cW == thisUTC) { 877 // The control system at Mopra typically does not update the 878 // positions between successive integration cycles at the end of a 879 // scan (nor are they flagged). In this case we use the previously 880 // computed rates, even if from the previous scan since these are 881 // likely to be a better guess than anything else. 882 raRate = iMBuff->raRate; 883 decRate = iMBuff->decRate; 884 paRate = iMBuff->paRate; 885 886 if (cU == thisRA && cV == thisDec) { 887 // Position and timestamp unchanged. 888 pCode = 1; 889 890 } else if (fabs(cU-thisRA) < 0.0001 && fabs(cV-thisDec) < 0.0001) { 891 // Allow small rounding errors (seen infrequently). 892 pCode = 1; 893 782 894 } else { 783 nextRA -= TWOPI; 895 // (cU,cV) are probably rubbish (not yet seen in practice). 896 pCode = 2; 897 cU = thisRA; 898 cV = thisDec; 784 899 } 785 }786 900 787 901 #ifdef PKSIO_DEBUG 788 printf("Previous ra, dec, UTC: %8.4f %8.4f %7.1f\n", thisRA*R2D, 789 thisDec*R2D, thisUTC); 790 printf("Current ra, dec, UTC: %8.4f %8.4f %7.1f\n", nextRA*R2D, 791 nextDec*R2D, nextUTC); 902 fprintf(stderr, "Next (%d) ra, dec, UTC: %9.4f %9.4f %10.3f " 903 "(0.000s)\n", cCycleNo, cU*R2D, cV*R2D, cW); 792 904 #endif 793 905 794 // The control system at Mopra typically does not update the 795 // positions between successive integration cycles at the end of a 796 // scan (nor are they flagged). In this case we use the previously 797 // computed rates, even if from the previous scan since these are 798 // likely to be a better guess than anything else. 799 800 double dUTC = nextUTC - thisUTC; 801 802 // Scan rate for this beam. 803 if (dUTC > 0.0) { 804 iMBuff->raRate = (nextRA - thisRA) / dUTC; 805 iMBuff->decRate = (nextDec - thisDec) / dUTC; 806 iMBuff->rateAge = 0; 807 iMBuff->rateson = 0; 808 809 if (cInterp == 2) { 810 // Use the same interpolation scheme as the original pksmbfits 811 // client. This incorrectly assumed that (nextUTC - thisUTC) is 812 // equal to the integration time and interpolated by computing a 813 // weighted sum of the positions before and after the required 814 // time. 815 816 double utc = iMBuff->utc; 817 if (utc - thisUTC > 100.0) { 818 // Must have cycled through midnight. 819 utc -= 86400.0; 906 } else { 907 double nextRA = cU; 908 double nextDec = cV; 909 910 // Check and, if necessary, repair the position timestamp, 911 // remembering that pCode refers to the NEXT cycle. 912 pCode = fixw(cDateObs, cCycleNo, beamNo, cAvRate, thisRA, thisDec, 913 thisUTC, nextRA, nextDec, cW); 914 if (pCode > 0) pCode += 3; 915 double nextUTC = cW; 916 917 #ifdef PKSIO_DEBUG 918 fprintf(stderr, "Next (%d) ra, dec, UTC: %9.4f %9.4f %10.3f " 919 "(%+.3fs)\n", cCycleNo, nextRA*R2D, nextDec*R2D, nextUTC, 920 utcDiff(nextUTC, thisUTC)); 921 #endif 922 923 // Compute the scan rate for this beam. 924 double dUTC = utcDiff(nextUTC, thisUTC); 925 if ((0.0 < dUTC) && (dUTC < 600.0)) { 926 scanRate(cRA0, cDec0, thisRA, thisDec, nextRA, nextDec, dUTC, 927 raRate, decRate); 928 929 // Update the mean scan rate. 930 cAvRate[0] = (cAvRate[0]*cNRate + raRate) / (cNRate + 1); 931 cAvRate[1] = (cAvRate[1]*cNRate + decRate) / (cNRate + 1); 932 cNRate++; 933 934 // Rate of change of position angle. 935 if (sc_.sc_ant <= anten_.nant) { 936 paRate = 0.0; 937 } else { 938 int iOff = sc_.sc_q * (sc_.sc_ant - 1) - 1; 939 double nextPA = sc_.sc_cal[iOff + 4] + sc_.sc_cal[iOff + 7]; 940 double paDiff = nextPA - thisPA; 941 if (paDiff > PI) { 942 paDiff -= TWOPI; 943 } else if (paDiff < -PI) { 944 paDiff += TWOPI; 945 } 946 paRate = paDiff / dUTC; 820 947 } 821 948 822 double tw1 = 1.0 - (utc - thisUTC) / iMBuff->exposure; 823 double tw2 = 1.0 - (nextUTC - utc) / iMBuff->exposure; 824 double gamma = (tw2 / (tw1 + tw2)) * dUTC / (utc - thisUTC); 825 826 iMBuff->raRate *= gamma; 827 iMBuff->decRate *= gamma; 828 } 829 830 } else { 831 iMBuff->rateAge++; 832 833 // Staleness codes. 834 if (dUTC < 0.0) { 835 iMBuff->rateson = 3; 949 if (cInterp == 2) { 950 // Use the same interpolation scheme as the original pksmbfits 951 // client. This incorrectly assumed that (nextUTC - thisUTC) is 952 // equal to the integration time and interpolated by computing a 953 // weighted sum of the positions before and after the required 954 // time. 955 956 double utc = iMBuff->utc; 957 double tw1 = 1.0 - utcDiff(utc, thisUTC) / iMBuff->exposure; 958 double tw2 = 1.0 - utcDiff(nextUTC, utc) / iMBuff->exposure; 959 double gamma = (tw2 / (tw1 + tw2)) * dUTC / (utc - thisUTC); 960 961 // Guard against RA cycling through 24h in either direction. 962 if (fabs(nextRA - thisRA) > PI) { 963 if (nextRA < thisRA) { 964 nextRA += TWOPI; 965 } else { 966 nextRA -= TWOPI; 967 } 968 } 969 970 raRate = gamma * (nextRA - thisRA) / dUTC; 971 decRate = gamma * (nextDec - thisDec) / dUTC; 972 } 973 836 974 } else { 837 if (nextRA != thisRA || nextDec != thisDec) { 838 iMBuff->rateson = 2; 975 if (cCycleNo == 2 && fabs(utcDiff(cUTC,cW)) < 600.0) { 976 // thisUTC (i.e. cW for the first cycle) is rubbish, and 977 // probably the position as well (extremely rare in practice, 978 // e.g. 97-12-19_1029_235708-18_586e.hpf which actually has the 979 // t/1000 scaling bug in the first cycle). 980 iMBuff->pCode = 3; 981 thisRA = cU; 982 thisDec = cV; 983 thisUTC = cW; 984 raRate = 0.0; 985 decRate = 0.0; 986 paRate = 0.0; 987 839 988 } else { 840 iMBuff->rateson = 1; 989 // cW is rubbish and probably (cU,cV), and possibly the 990 // parallactic angle and everything else as well (rarely seen 991 // in practice, e.g. 97-12-09_0743_235707-58_327c.hpf and 992 // 97-09-01_0034_123717-42_242b.hpf, the latter with bad 993 // parallactic angle). 994 pCode = 3; 995 cU = thisRA; 996 cV = thisDec; 997 cW = thisUTC; 998 raRate = iMBuff->raRate; 999 decRate = iMBuff->decRate; 1000 paRate = iMBuff->paRate; 841 1001 } 842 1002 } … … 844 1004 } 845 1005 1006 1007 // Choose the closest rate determination. 1008 if (cCycleNo == 1) { 1009 // Scan containing a single integration. 1010 iMBuff->raRate = 0.0; 1011 iMBuff->decRate = 0.0; 1012 iMBuff->paRate = 0.0; 1013 1014 } else { 1015 double dUTC = iMBuff->utc - cPosUTC[iBeamSel]; 1016 1017 if (dUTC >= 0.0) { 1018 // In HIPASS/ZOA, the position timestamp, which should always occur 1019 // on the whole second, normally precedes an integration midpoint 1020 // falling on the half-second. Consequently, positive ages are 1021 // always half-integral. 1022 dUTC = utcDiff(iMBuff->utc, cW); 1023 if (dUTC > 0.0) { 1024 iMBuff->rateAge = dUTC; 1025 } else { 1026 iMBuff->rateAge = 0.0f; 1027 } 1028 1029 iMBuff->raRate = raRate; 1030 iMBuff->decRate = decRate; 1031 iMBuff->paRate = paRate; 1032 1033 } else { 1034 // In HIPASS/ZOA, negative ages occur when the integration midpoint, 1035 // occurring on the whole second, precedes the position timestamp. 1036 // Thus negative ages are always an integral number of seconds. 1037 // They have only been seen to occur sporadically in the period 1038 // 1999/05/31 to 1999/11/01, e.g. 1999-07-26_1821_005410-74_007c.hpf 1039 // 1040 // In recent (2008/10/07) Mopra data, small negative ages (~10ms, 1041 // occasionally up to ~300ms) seem to be the norm, with both the 1042 // position timestamp and integration midpoint falling close to but 1043 // not on the integral second. 1044 if (cCycleNo == 2) { 1045 // We have to start with something! 1046 iMBuff->rateAge = dUTC; 1047 1048 } else { 1049 // Although we did not record the relevant position timestamp 1050 // explicitly, it can easily be deduced. 1051 double w = iMBuff->utc - utcDiff(cUTC, iMBuff->utc) - 1052 iMBuff->rateAge; 1053 dUTC = utcDiff(iMBuff->utc, w); 1054 1055 if (dUTC > 0.0) { 1056 iMBuff->rateAge = 0.0f; 1057 } else { 1058 iMBuff->rateAge = dUTC; 1059 } 1060 } 1061 1062 iMBuff->raRate = raRate; 1063 iMBuff->decRate = decRate; 1064 iMBuff->paRate = paRate; 1065 } 1066 } 1067 846 1068 #ifdef PKSIO_DEBUG 847 printf("Doing position interpolation for beam %d.\n", iMBuff->beamNo);848 printf("RA and Dec rates and age: %7.4f %7.4f %d\n",849 iMBuff->raRate*R2D, iMBuff->decRate*R2D, iMBuff->rateAge);1069 double avRate = sqrt(cAvRate[0]*cAvRate[0] + cAvRate[1]*cAvRate[1]); 1070 fprintf(stderr, "RA, Dec, Av & PA rates: %8.4f %8.4f %8.4f %8.4f " 1071 "pCode %d\n", raRate*R2D, decRate*R2D, avRate*R2D, paRate*R2D, pCode); 850 1072 #endif 1073 851 1074 852 1075 // Compute the position of this beam for all bins. … … 856 1079 cBuffer[jbuff].raRate = iMBuff->raRate; 857 1080 cBuffer[jbuff].decRate = iMBuff->decRate; 858 859 double dutc = cBuffer[jbuff].utc - thisUTC; 860 if (dutc > 100.0) { 1081 cBuffer[jbuff].paRate = iMBuff->paRate; 1082 1083 double dUTC = utcDiff(cBuffer[jbuff].utc, thisUTC); 1084 if (dUTC > 100.0) { 861 1085 // Must have cycled through midnight. 862 dutc -= 86400.0; 863 } 864 865 cBuffer[jbuff].ra = thisRA + cBuffer[jbuff].raRate * dutc; 866 cBuffer[jbuff].dec = thisDec + cBuffer[jbuff].decRate * dutc; 867 if (cBuffer[jbuff].ra < 0.0) { 868 cBuffer[jbuff].ra += TWOPI; 869 } else if (cBuffer[jbuff].ra > TWOPI) { 870 cBuffer[jbuff].ra -= TWOPI; 871 } 1086 dUTC -= 86400.0; 1087 } 1088 1089 applyRate(cRA0, cDec0, thisRA, thisDec, 1090 cBuffer[jbuff].raRate, cBuffer[jbuff].decRate, dUTC, 1091 cBuffer[jbuff].ra, cBuffer[jbuff].dec); 1092 1093 #ifdef PKSIO_DEBUG 1094 fprintf(stderr, "Intp (%d) ra, dec, UTC: %9.4f %9.4f %10.3f (pCode, " 1095 "age: %d %.1fs)\n", iMBuff->cycleNo, cBuffer[jbuff].ra*R2D, 1096 cBuffer[jbuff].dec*R2D, cBuffer[jbuff].utc, iMBuff->pCode, 1097 iMBuff->rateAge); 1098 #endif 872 1099 } 873 1100 } … … 880 1107 881 1108 #ifdef PKSIO_DEBUG 882 printf("Out:%4d%4d%3d%3d\n", MBrec.scanNo, MBrec.cycleNo, MBrec.beamNo,883 MBrec. IFno[0]);1109 fprintf(stderr, "Out:%4d%4d%3d%3d\n", MBrec.scanNo, MBrec.cycleNo, 1110 MBrec.beamNo, MBrec.IFno[0]); 884 1111 #endif 885 1112 … … 923 1150 // Sanity check on the number of IFs in the new scan. 924 1151 if (if_.n_if != cNIF) { 925 fprintf(stderr, "WARNING, scan %d has %d IFs instead of %d, " 926 "continuing.\n", cScanNo, if_.n_if, cNIF); 1152 sprintf(cMsg, "WARNING: Scan %d has %d IFs instead of %d, " 1153 "continuing.", cScanNo, if_.n_if, cNIF); 1154 logMsg(cMsg); 927 1155 } 928 1156 } … … 935 1163 } 936 1164 937 iMBuff->scanNo = cScanNo; 938 iMBuff->cycleNo = cCycleNo; 939 940 // Times. 941 strncpy(iMBuff->datobs, cDateObs, 10); 942 iMBuff->utc = cUTC; 943 iMBuff->exposure = param_.intbase; 944 945 // Source identification. 946 sprintf(iMBuff->srcName, "%-16.16s", 947 names_.su_name + (cSrcNo-1)*16); 948 iMBuff->srcRA = doubles_.su_ra[cSrcNo-1]; 949 iMBuff->srcDec = doubles_.su_dec[cSrcNo-1]; 950 951 // Rest frequency of the line of interest. 952 iMBuff->restFreq = doubles_.rfreq; 953 if (strncmp(names_.instrument, "ATPKSMB", 7) == 0) { 954 // Fix the HI rest frequency recorded for Parkes multibeam data. 955 double reffreq = doubles_.freq; 956 double restfreq = doubles_.rfreq; 957 if ((restfreq == 0.0 || fabs(restfreq - reffreq) == 0.0) && 958 fabs(reffreq - 1420.40575e6) < 100.0) { 959 iMBuff->restFreq = 1420.40575e6; 960 } 961 } 962 963 // Observation type. 964 int j; 965 for (j = 0; j < 15; j++) { 966 iMBuff->obsType[j] = names_.card[11+j]; 967 if (iMBuff->obsType[j] == '\'') break; 968 } 969 iMBuff->obsType[j] = '\0'; 970 971 // Beam-dependent parameters. 972 iMBuff->beamNo = beamNo; 973 974 // Beam position at the specified time. 975 if (cSUpos) { 976 // Non-ATNF data that does not store the position in (u,v,w). 977 iMBuff->ra = doubles_.su_ra[cSrcNo-1]; 978 iMBuff->dec = doubles_.su_dec[cSrcNo-1]; 979 } else { 980 iMBuff->ra = cU; 981 iMBuff->dec = cV; 982 } 983 cPosUTC[iBeamSel] = cW; 1165 #ifdef PKSIO_DEBUG 1166 fprintf(stderr, "Buf:%4d%4d%3d%3d\n", cScanNo, cCycleNo, beamNo, cIFno); 1167 #endif 1168 1169 // Store IF-independent parameters only for the first IF of a new cycle, 1170 // particularly because this is the only one for which the scan rates 1171 // are computed above. 1172 int firstIF = (iMBuff->nIF == 0); 1173 if (firstIF) { 1174 iMBuff->scanNo = cScanNo; 1175 iMBuff->cycleNo = cCycleNo; 1176 1177 // Times. 1178 strcpy(iMBuff->datobs, cDateObs); 1179 iMBuff->utc = cUTC; 1180 iMBuff->exposure = param_.intbase; 1181 1182 // Source identification. 1183 sprintf(iMBuff->srcName, "%-16.16s", 1184 names_.su_name + (cSrcNo-1)*16); 1185 iMBuff->srcName[16] = '\0'; 1186 iMBuff->srcRA = doubles_.su_ra[cSrcNo-1]; 1187 iMBuff->srcDec = doubles_.su_dec[cSrcNo-1]; 1188 1189 // Rest frequency of the line of interest. 1190 iMBuff->restFreq = doubles_.rfreq; 1191 if (strncmp(names_.instrument, "ATPKSMB", 7) == 0) { 1192 // Fix the HI rest frequency recorded for Parkes multibeam data. 1193 double reffreq = doubles_.freq; 1194 double restfreq = doubles_.rfreq; 1195 if ((restfreq == 0.0 || fabs(restfreq - reffreq) == 0.0) && 1196 fabs(reffreq - 1420.405752e6) < 100.0) { 1197 iMBuff->restFreq = 1420.405752e6; 1198 } 1199 } 1200 1201 // Observation type. 1202 int j; 1203 for (j = 0; j < 15; j++) { 1204 iMBuff->obsType[j] = names_.card[11+j]; 1205 if (iMBuff->obsType[j] == '\'') break; 1206 } 1207 iMBuff->obsType[j] = '\0'; 1208 1209 // Beam-dependent parameters. 1210 iMBuff->beamNo = beamNo; 1211 1212 // Beam position at the specified time. 1213 if (cSUpos) { 1214 // Non-ATNF data that does not store the position in (u,v,w). 1215 iMBuff->ra = doubles_.su_ra[cSrcNo-1]; 1216 iMBuff->dec = doubles_.su_dec[cSrcNo-1]; 1217 } else { 1218 iMBuff->ra = cU; 1219 iMBuff->dec = cV; 1220 } 1221 cPosUTC[iBeamSel] = cW; 1222 iMBuff->pCode = pCode; 1223 1224 // Store rates for next time. 1225 iMBuff->raRate = raRate; 1226 iMBuff->decRate = decRate; 1227 iMBuff->paRate = paRate; 1228 } 984 1229 985 1230 // IF-dependent parameters. … … 992 1237 993 1238 iIFSel = cIFSel[iIF]; 994 iMBuff->nIF++; 995 iMBuff->IFno[iIFSel] = cIFno; 1239 if (iMBuff->IFno[iIFSel] == 0) { 1240 iMBuff->nIF++; 1241 iMBuff->IFno[iIFSel] = cIFno; 1242 } else { 1243 // Integration cycle written to the output file twice (the only known 1244 // example is 1999-05-22_1914_000-031805_03v.hpf). 1245 sprintf(cMsg, "WARNING: Integration cycle %d:%d, beam %2d, \n" 1246 " IF %d was duplicated.", cScanNo, cCycleNo-1, 1247 beamNo, cIFno); 1248 logMsg(cMsg); 1249 } 996 1250 iMBuff->nChan[iIFSel] = nChan; 997 1251 iMBuff->nPol[iIFSel] = cNPol[iIF]; … … 1093 1347 1094 1348 1095 // Parallactic angle.1096 iMBuff->parAngle = sc_.sc_cal[scq*iBeam + 11];1097 1098 1349 // Calibration factor applied to the data by the correlator. 1099 1350 if (scq > 14) { … … 1106 1357 } 1107 1358 1108 if (sc_.sc_ant <= anten_.nant) { 1109 // No extra syscal information present. 1110 iMBuff->extraSysCal = 0; 1111 iMBuff->azimuth = 0.0f; 1112 iMBuff->elevation = 0.0f; 1113 iMBuff->parAngle = 0.0f; 1114 iMBuff->focusAxi = 0.0f; 1115 iMBuff->focusTan = 0.0f; 1116 iMBuff->focusRot = 0.0f; 1117 iMBuff->temp = 0.0f; 1118 iMBuff->pressure = 0.0f; 1119 iMBuff->humidity = 0.0f; 1120 iMBuff->windSpeed = 0.0f; 1121 iMBuff->windAz = 0.0f; 1122 strcpy(iMBuff->tcalTime, " "); 1123 iMBuff->refBeam = 0; 1124 1125 } else { 1126 // Additional information for Parkes Multibeam data. 1127 int iOff = scq*(sc_.sc_ant - 1) - 1; 1128 iMBuff->extraSysCal = 1; 1129 iMBuff->azimuth = sc_.sc_cal[iOff + 2]; 1130 iMBuff->elevation = sc_.sc_cal[iOff + 3]; 1131 iMBuff->parAngle = sc_.sc_cal[iOff + 4]; 1132 iMBuff->focusAxi = sc_.sc_cal[iOff + 5] * 1e-3; 1133 iMBuff->focusTan = sc_.sc_cal[iOff + 6] * 1e-3; 1134 iMBuff->focusRot = sc_.sc_cal[iOff + 7]; 1135 iMBuff->temp = sc_.sc_cal[iOff + 8]; 1136 iMBuff->pressure = sc_.sc_cal[iOff + 9]; 1137 iMBuff->humidity = sc_.sc_cal[iOff + 10]; 1138 iMBuff->windSpeed = sc_.sc_cal[iOff + 11]; 1139 iMBuff->windAz = sc_.sc_cal[iOff + 12]; 1140 1141 char *tcalTime = iMBuff->tcalTime; 1142 sprintf(tcalTime, "%-16.16s", (char *)(&sc_.sc_cal[iOff+13])); 1359 if (firstIF) { 1360 if (sc_.sc_ant <= anten_.nant) { 1361 // No extra syscal information present. 1362 iMBuff->extraSysCal = 0; 1363 iMBuff->azimuth = 0.0f; 1364 iMBuff->elevation = 0.0f; 1365 iMBuff->parAngle = 0.0f; 1366 iMBuff->focusAxi = 0.0f; 1367 iMBuff->focusTan = 0.0f; 1368 iMBuff->focusRot = 0.0f; 1369 iMBuff->temp = 0.0f; 1370 iMBuff->pressure = 0.0f; 1371 iMBuff->humidity = 0.0f; 1372 iMBuff->windSpeed = 0.0f; 1373 iMBuff->windAz = 0.0f; 1374 strcpy(iMBuff->tcalTime, " "); 1375 iMBuff->refBeam = 0; 1376 1377 } else { 1378 // Additional information for Parkes Multibeam data. 1379 int iOff = scq*(sc_.sc_ant - 1) - 1; 1380 iMBuff->extraSysCal = 1; 1381 1382 iMBuff->azimuth = sc_.sc_cal[iOff + 2]; 1383 iMBuff->elevation = sc_.sc_cal[iOff + 3]; 1384 iMBuff->parAngle = sc_.sc_cal[iOff + 4]; 1385 1386 iMBuff->focusAxi = sc_.sc_cal[iOff + 5] * 1e-3; 1387 iMBuff->focusTan = sc_.sc_cal[iOff + 6] * 1e-3; 1388 iMBuff->focusRot = sc_.sc_cal[iOff + 7]; 1389 1390 iMBuff->temp = sc_.sc_cal[iOff + 8]; 1391 iMBuff->pressure = sc_.sc_cal[iOff + 9]; 1392 iMBuff->humidity = sc_.sc_cal[iOff + 10]; 1393 iMBuff->windSpeed = sc_.sc_cal[iOff + 11]; 1394 iMBuff->windAz = sc_.sc_cal[iOff + 12]; 1395 1396 char *tcalTime = iMBuff->tcalTime; 1397 sprintf(tcalTime, "%-16.16s", (char *)(&sc_.sc_cal[iOff+13])); 1398 tcalTime[16] = '\0'; 1143 1399 1144 1400 #ifndef AIPS_LITTLE_ENDIAN 1145 // Do byte swapping on the ASCII date string.1146 for (int j = 0; j < 16; j += 4) {1147 char ctmp;1148 ctmp = tcalTime[j];1149 tcalTime[j] = tcalTime[j+3];1150 tcalTime[j+3] = ctmp;1151 ctmp = tcalTime[j+1];1152 tcalTime[j+1] = tcalTime[j+2];1153 tcalTime[j+2] = ctmp;1154 }1401 // Do byte swapping on the ASCII date string. 1402 for (int j = 0; j < 16; j += 4) { 1403 char ctmp; 1404 ctmp = tcalTime[j]; 1405 tcalTime[j] = tcalTime[j+3]; 1406 tcalTime[j+3] = ctmp; 1407 ctmp = tcalTime[j+1]; 1408 tcalTime[j+1] = tcalTime[j+2]; 1409 tcalTime[j+2] = ctmp; 1410 } 1155 1411 #endif 1156 1412 1157 // Reference beam number. 1158 float refbeam = sc_.sc_cal[iOff + 17]; 1159 if (refbeam > 0.0f || refbeam < 100.0f) { 1160 iMBuff->refBeam = int(refbeam); 1161 } else { 1162 iMBuff->refBeam = 0; 1413 // Reference beam number. 1414 float refbeam = sc_.sc_cal[iOff + 17]; 1415 if (refbeam > 0.0f || refbeam < 100.0f) { 1416 iMBuff->refBeam = int(refbeam); 1417 } else { 1418 iMBuff->refBeam = 0; 1419 } 1163 1420 } 1164 1421 } … … 1185 1442 while (numErr < 10) { 1186 1443 int lastjstat = jstat; 1187 rpfitsin_(&jstat, cVis, cWgt, &cBaseline, &cUTC, &cU, &cV, &cW, &cFlag, 1188 &cBin, &cIFno, &cSrcNo); 1189 1190 switch(jstat) { 1444 1445 switch(rpfitsin(jstat)) { 1191 1446 case -1: 1192 1447 // Read failed; retry. 1193 1448 numErr++; 1194 fprintf(stderr, "RPFITS read failed - retrying.\n");1449 logMsg("WARNING: RPFITS read failed - retrying."); 1195 1450 jstat = 0; 1196 1451 break; … … 1248 1503 default: 1249 1504 // Shouldn't reach here. 1250 fprintf(stderr, "Unrecognized RPFITSIN return code: %d (retrying)\n", 1251 jstat); 1505 sprintf(cMsg, "WARNING: Unrecognized RPFITSIN return code: %d " 1506 "(retrying).", jstat); 1507 logMsg(cMsg); 1252 1508 jstat = 0; 1253 1509 break; … … 1255 1511 } 1256 1512 1257 fprintf(stderr, "ERROR, RPFITS read failed too many times.\n");1513 logMsg("ERROR: RPFITS read failed too many times."); 1258 1514 return 2; 1515 } 1516 1517 //----------------------------------------------------- MBFITSreader::rpfitsin 1518 1519 // Wrapper around RPFITSIN that reports errors. Returned RPFITSIN subroutine 1520 // arguments are captured as MBFITSreader member variables. 1521 1522 int MBFITSreader::rpfitsin(int &jstat) 1523 1524 { 1525 rpfitsin_(&jstat, cVis, cWgt, &cBaseline, &cUTC, &cU, &cV, &cW, &cFlag, 1526 &cBin, &cIFno, &cSrcNo); 1527 1528 // Handle messages from RPFITSIN. 1529 if (names_.errmsg[0] != ' ') { 1530 int i; 1531 for (i = 80; i > 0; i--) { 1532 if (names_.errmsg[i-1] != ' ') break; 1533 } 1534 1535 sprintf(cMsg, "WARNING: Cycle %d:%03d, RPFITSIN reported -\n" 1536 " %.*s", cScanNo, cCycleNo, i, names_.errmsg); 1537 logMsg(cMsg); 1538 } 1539 1540 return jstat; 1541 } 1542 1543 //------------------------------------------------------- MBFITSreader::fixPos 1544 1545 // Check and, if necessary, repair a position timestamp. 1546 // 1547 // Problems with the position timestamp manifest themselves via the scan rate: 1548 // 1549 // 1) Zero scan rate pairs, 1997/02/28 to 1998/01/07 1550 // 1551 // These occur because the position timestamp for the first integration 1552 // of the pair is erroneous; the value recorded is t/1000, where t is the 1553 // true value. 1554 // Earliest known: 97-02-28_1725_132653-42_258a.hpf 1555 // Latest known: 98-01-02_1923_095644-50_165c.hpf 1556 // (time range chosen to encompass observing runs). 1557 // 1558 // 2) Slow-fast scan rate pairs (0.013 - 0.020 deg/s), 1559 // 1997/03/28 to 1998/01/07. 1560 // 1561 // The UTC position timestamp is 1.0s later than it should be (never 1562 // earlier), almost certainly arising from an error in the telescope 1563 // control system. 1564 // Earliest known: 97-03-28_0150_010420-74_008d.hpf 1565 // Latest known: 98-01-04_1502_065150-02_177c.hpf 1566 // (time range chosen to encompass observing runs). 1567 // 1568 // 3) Slow-fast scan rate pairs (0.015 - 0.018 deg/s), 1569 // 1999/05/20 to 2001/07/12 (HIPASS and ZOA), 1570 // 2001/09/02 to 2001/12/04 (HIPASS and ZOA), 1571 // 2002/03/28 to 2002/05/13 (ZOA only), 1572 // 2003/04/26 to 2003/06/09 (ZOA only). 1573 // Earliest known: 1999-05-20_1818_175720-50_297e.hpf 1574 // Latest known: 2001-12-04_1814_065531p14_173e.hpf (HIPASS) 1575 // 2003-06-09_1924_352-085940_-6c.hpf (ZOA) 1576 // 1577 // Caused by the Linux signalling NaN problem. IEEE "signalling" NaNs 1578 // are silently transformed to "quiet" NaNs during assignment by setting 1579 // bit 22. This affected RPFITS because of its use of VAX-format 1580 // floating-point numbers which, with their permuted bytes, may sometimes 1581 // appear as signalling NaNs. 1582 // 1583 // The problem arose when the linux correlator came online and was 1584 // fixed with a workaround to the RPFITS library (repeated episodes 1585 // are probably due to use of an older version of the library). It 1586 // should not have affected the data significantly because of the 1587 // low relative error, which ranges from 0.0000038 to 0.0000076, but 1588 // it is important for the computation of scan rates which requires 1589 // taking the difference of two large UTC timestamps, one or other 1590 // of which will have 0.5s added to it. 1591 // 1592 // The return value identifies which, if any, of these problems was repaired. 1593 1594 int MBFITSreader::fixw( 1595 const char *datobs, 1596 int cycleNo, 1597 int beamNo, 1598 double avRate[2], 1599 double thisRA, 1600 double thisDec, 1601 double thisUTC, 1602 double nextRA, 1603 double nextDec, 1604 float &nextUTC) 1605 { 1606 if (strcmp(datobs, "2003-06-09") > 0) { 1607 return 0; 1608 1609 } else if (strcmp(datobs, "1998-01-07") <= 0) { 1610 if (nextUTC < thisUTC && (nextUTC + 86400.0) > (thisUTC + 600.0)) { 1611 // Possible scaling problem. 1612 double diff = nextUTC*1000.0 - thisUTC; 1613 if (0.0 < diff && diff < 600.0) { 1614 nextUTC *= 1000.0; 1615 return 1; 1616 } else { 1617 // Irreparable. 1618 return -1; 1619 } 1620 } 1621 1622 if (cycleNo > 2) { 1623 if (beamNo == 1) { 1624 // This test is only reliable for beam 1. 1625 double dUTC = nextUTC - thisUTC; 1626 if (dUTC < 0.0) dUTC += 86400.0; 1627 1628 // Guard against RA cycling through 24h in either direction. 1629 if (fabs(nextRA - thisRA) > PI) { 1630 if (nextRA < thisRA) { 1631 nextRA += TWOPI; 1632 } else { 1633 nextRA -= TWOPI; 1634 } 1635 } 1636 1637 double dRA = (nextRA - thisRA) * cos(nextDec); 1638 double dDec = nextDec - thisDec; 1639 double arc = sqrt(dRA*dRA + dDec*dDec); 1640 1641 double averate = sqrt(avRate[0]*avRate[0] + avRate[1]*avRate[1]); 1642 double diff1 = fabs(averate - arc/(dUTC-1.0)); 1643 double diff2 = fabs(averate - arc/dUTC); 1644 if ((diff1 < diff2) && (diff1 < 0.05*averate)) { 1645 nextUTC -= 1.0; 1646 cCode5 = cycleNo; 1647 return 2; 1648 } else { 1649 cCode5 = 0; 1650 } 1651 1652 } else { 1653 if (cycleNo == cCode5) { 1654 nextUTC -= 1.0; 1655 return 2; 1656 } 1657 } 1658 } 1659 1660 } else if ((strcmp(datobs, "1999-05-20") >= 0 && 1661 strcmp(datobs, "2001-07-12") <= 0) || 1662 (strcmp(datobs, "2001-09-02") >= 0 && 1663 strcmp(datobs, "2001-12-04") <= 0) || 1664 (strcmp(datobs, "2002-03-28") >= 0 && 1665 strcmp(datobs, "2002-05-13") <= 0) || 1666 (strcmp(datobs, "2003-04-26") >= 0 && 1667 strcmp(datobs, "2003-06-09") <= 0)) { 1668 // Signalling NaN problem, e.g. 1999-07-26_1839_011106-74_009c.hpf. 1669 // Position timestamps should always be an integral number of seconds. 1670 double resid = nextUTC - int(nextUTC); 1671 if (resid == 0.5) { 1672 nextUTC -= 0.5; 1673 return 3; 1674 } 1675 } 1676 1677 return 0; 1259 1678 } 1260 1679 … … 1292 1711 } 1293 1712 } 1713 1714 //-------------------------------------------------------------------- utcDiff 1715 1716 // Subtract two UTCs (s) allowing for any plausible number of cycles through 1717 // 86400s, returning a result in the range [-43200, +43200]s. 1718 1719 double MBFITSreader::utcDiff(double utc1, double utc2) 1720 { 1721 double diff = utc1 - utc2; 1722 1723 if (diff > 43200.0) { 1724 diff -= 86400.0; 1725 while (diff > 43200.0) diff -= 86400.0; 1726 } else if (diff < -43200.0) { 1727 diff += 86400.0; 1728 while (diff < -43200.0) diff += 86400.0; 1729 } 1730 1731 return diff; 1732 } 1733 1734 //------------------------------------------------------- scanRate & applyRate 1735 1736 // Compute and apply the scan rate corrected for grid convergence. (ra0,dec0) 1737 // are the coordinates of the central beam, assumed to be the tracking centre. 1738 // The rate computed in RA will be a rate of change of angular distance in the 1739 // direction of increasing RA at the position of the central beam. Similarly 1740 // for declination. Angles in radian, time in s. 1741 1742 void MBFITSreader::scanRate( 1743 double ra0, 1744 double dec0, 1745 double ra1, 1746 double dec1, 1747 double ra2, 1748 double dec2, 1749 double dt, 1750 double &raRate, 1751 double &decRate) 1752 { 1753 // Transform to a system where the central beam lies on the equator at 12h. 1754 eulerx(ra1, dec1, ra0+HALFPI, -dec0, -HALFPI, ra1, dec1); 1755 eulerx(ra2, dec2, ra0+HALFPI, -dec0, -HALFPI, ra2, dec2); 1756 1757 raRate = (ra2 - ra1) / dt; 1758 decRate = (dec2 - dec1) / dt; 1759 } 1760 1761 1762 void MBFITSreader::applyRate( 1763 double ra0, 1764 double dec0, 1765 double ra1, 1766 double dec1, 1767 double raRate, 1768 double decRate, 1769 double dt, 1770 double &ra2, 1771 double &dec2) 1772 { 1773 // Transform to a system where the central beam lies on the equator at 12h. 1774 eulerx(ra1, dec1, ra0+HALFPI, -dec0, -HALFPI, ra1, dec1); 1775 1776 ra2 = ra1 + (raRate * dt); 1777 dec2 = dec1 + (decRate * dt); 1778 1779 // Transform back. 1780 eulerx(ra2, dec2, -HALFPI, dec0, ra0+HALFPI, ra2, dec2); 1781 } 1782 1783 //--------------------------------------------------------------------- eulerx 1784 1785 void MBFITSreader::eulerx( 1786 double lng0, 1787 double lat0, 1788 double phi0, 1789 double theta, 1790 double phi, 1791 double &lng1, 1792 double &lat1) 1793 1794 // Applies the Euler angle based transformation of spherical coordinates. 1795 // 1796 // phi0 Longitude of the ascending node in the old system, radians. The 1797 // ascending node is the point of intersection of the equators of 1798 // the two systems such that the equator of the new system crosses 1799 // from south to north as viewed in the old system. 1800 // 1801 // theta Angle between the poles of the two systems, radians. THETA is 1802 // positive for a positive rotation about the ascending node. 1803 // 1804 // phi Longitude of the ascending node in the new system, radians. 1805 1806 { 1807 // Compute intermediaries. 1808 double lng0p = lng0 - phi0; 1809 double slng0p = sin(lng0p); 1810 double clng0p = cos(lng0p); 1811 double slat0 = sin(lat0); 1812 double clat0 = cos(lat0); 1813 double ctheta = cos(theta); 1814 double stheta = sin(theta); 1815 1816 double x = clat0*clng0p; 1817 double y = clat0*slng0p*ctheta + slat0*stheta; 1818 1819 // Longitude in the new system. 1820 if (x != 0.0 || y != 0.0) { 1821 lng1 = phi + atan2(y, x); 1822 } else { 1823 // Longitude at the poles in the new system is consistent with that 1824 // specified in the old system. 1825 lng1 = phi + lng0p; 1826 } 1827 lng1 = fmod(lng1, TWOPI); 1828 if (lng1 < 0.0) lng1 += TWOPI; 1829 1830 lat1 = asin(slat0*ctheta - clat0*stheta*slng0p); 1831 }
Note: See TracChangeset
for help on using the changeset viewer.