Ignore:
Timestamp:
06/09/10 19:03:06 (14 years ago)
Author:
Kana Sugimoto
Message:

New Development: Yes

JIRA Issue: Yes (CAS-2211)

Ready for Test: Yes

Interface Changes: Yes

What Interface Changed: ASAP 3.0.0 interface changes

Test Programs:

Put in Release Notes: Yes

Module(s): all the CASA sd tools and tasks are affected.

Description: Merged ATNF-ASAP 3.0.0 developments to CASA (alma) branch.

Note you also need to update casa/code/atnf.


Location:
branches/alma
Files:
22 added
4 deleted
24 edited
3 copied

Legend:

Unmodified
Added
Removed
  • branches/alma

  • branches/alma/external/atnf/PKSIO/FITSreader.cc

    r1453 r1757  
    22//# FITSreader.cc: ATNF single-dish FITS reader.
    33//#---------------------------------------------------------------------------
    4 //# Copyright (C) 2000-2006
    5 //# Mark Calabretta, ATNF
     4//# livedata - processing pipeline for single-dish, multibeam spectral data.
     5//# Copyright (C) 2000-2009, Australia Telescope National Facility, CSIRO
    66//#
    7 //# This library is free software; you can redistribute it and/or modify it
    8 //# under the terms of the GNU Library General Public License as published by
    9 //# the Free Software Foundation; either version 2 of the License, or (at your
    10 //# option) any later version.
     7//# This file is part of livedata.
    118//#
    12 //# This library is distributed in the hope that it will be useful, but WITHOUT
     9//# livedata is free software: you can redistribute it and/or modify it under
     10//# the terms of the GNU General Public License as published by the Free
     11//# Software Foundation, either version 3 of the License, or (at your option)
     12//# any later version.
     13//#
     14//# livedata is distributed in the hope that it will be useful, but WITHOUT
    1315//# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    14 //# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Library General Public
    15 //# License for more details.
     16//# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
     17//# more details.
    1618//#
    17 //# You should have received a copy of the GNU Library General Public License
    18 //# along with this library; if not, write to the Free Software Foundation,
    19 //# Inc., 675 Massachusetts Ave, Cambridge, MA 02139, USA.
     19//# You should have received a copy of the GNU General Public License along
     20//# with livedata.  If not, see <http://www.gnu.org/licenses/>.
    2021//#
    21 //# Correspondence concerning this software should be addressed as follows:
    22 //#        Internet email: mcalabre@atnf.csiro.au.
    23 //#        Postal address: Dr. Mark Calabretta,
    24 //#                        Australia Telescope National Facility,
    25 //#                        P.O. Box 76,
    26 //#                        Epping, NSW, 2121,
     22//# Correspondence concerning livedata may be directed to:
     23//#        Internet email: mcalabre@atnf.csiro.au
     24//#        Postal address: Dr. Mark Calabretta
     25//#                        Australia Telescope National Facility, CSIRO
     26//#                        PO Box 76
     27//#                        Epping NSW 1710
    2728//#                        AUSTRALIA
    2829//#
    29 //# $Id$
     30//# http://www.atnf.csiro.au/computing/software/livedata.html
     31//# $Id: FITSreader.cc,v 19.4 2009-09-29 07:33:38 cal103 Exp $
    3032//#---------------------------------------------------------------------------
    3133//# The FITSreader class is an abstract base class for the Parkes Multibeam
     
    5355        const int getSpectra,
    5456        const int getXPol,
    55         const int getFeedPos)
     57        const int getFeedPos,
     58        const int getPointing,
     59        const int coordSys)
    5660{
    5761  int maxNChan = 0;
     
    8488  cGetXPol    = getXPol    && cGetXPol;
    8589  cGetFeedPos = getFeedPos;
     90  cCoordSys   = coordSys;
     91
    8692
    8793  return maxNChan;
  • branches/alma/external/atnf/PKSIO/FITSreader.h

    r1453 r1757  
    22//# FITSreader.h: ATNF single-dish FITS reader.
    33//#---------------------------------------------------------------------------
    4 //# Copyright (C) 2000-2006
    5 //# Mark Calabretta, ATNF
     4//# livedata - processing pipeline for single-dish, multibeam spectral data.
     5//# Copyright (C) 2000-2009, Australia Telescope National Facility, CSIRO
    66//#
    7 //# This library is free software; you can redistribute it and/or modify it
    8 //# under the terms of the GNU Library General Public License as published by
    9 //# the Free Software Foundation; either version 2 of the License, or (at your
    10 //# option) any later version.
     7//# This file is part of livedata.
    118//#
    12 //# This library is distributed in the hope that it will be useful, but WITHOUT
     9//# livedata is free software: you can redistribute it and/or modify it under
     10//# the terms of the GNU General Public License as published by the Free
     11//# Software Foundation, either version 3 of the License, or (at your option)
     12//# any later version.
     13//#
     14//# livedata is distributed in the hope that it will be useful, but WITHOUT
    1315//# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    14 //# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Library General Public
    15 //# License for more details.
     16//# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
     17//# more details.
    1618//#
    17 //# You should have received a copy of the GNU Library General Public License
    18 //# along with this library; if not, write to the Free Software Foundation,
    19 //# Inc., 675 Massachusetts Ave, Cambridge, MA 02139, USA.
     19//# You should have received a copy of the GNU General Public License along
     20//# with livedata.  If not, see <http://www.gnu.org/licenses/>.
    2021//#
    21 //# Correspondence concerning this software should be addressed as follows:
    22 //#        Internet email: mcalabre@atnf.csiro.au.
    23 //#        Postal address: Dr. Mark Calabretta,
    24 //#                        Australia Telescope National Facility,
    25 //#                        P.O. Box 76,
    26 //#                        Epping, NSW, 2121,
     22//# Correspondence concerning livedata may be directed to:
     23//#        Internet email: mcalabre@atnf.csiro.au
     24//#        Postal address: Dr. Mark Calabretta
     25//#                        Australia Telescope National Facility, CSIRO
     26//#                        PO Box 76
     27//#                        Epping NSW 1710
    2728//#                        AUSTRALIA
    2829//#
    29 //# $Id$
     30//# http://www.atnf.csiro.au/computing/software/livedata.html
     31//# $Id: FITSreader.h,v 19.11 2009-09-29 07:33:38 cal103 Exp $
    3032//#---------------------------------------------------------------------------
    3133//# The FITSreader class is an abstract base class for the Parkes Multibeam
     
    3840#define ATNF_FITSREADER_H
    3941
    40 #include <atnf/PKSIO/PKSMBrecord.h>
     42#include <atnf/PKSIO/MBrecord.h>
     43
     44using namespace std;
     45
    4146
    4247// <summary>
     
    4449// </summary>
    4550
     51//class FITSreader
    4652class FITSreader
    4753{
     
    7480        double antPos[3],
    7581        char   obsType[32],
     82        char   bunit[32],
    7683        float  &equinox,
    7784        char   radecsys[32],
     
    9097    // Set data selection criteria.  Channel numbering is 1-relative, zero or
    9198    // negative channel numbers are taken to be offsets from the last channel.
     99    // Coordinate systems are
     100    //   0: equatorial (RA,Dec),
     101    //   1: horizontal (Az,El),
     102    //   2: feed-plane,
     103    //   3: zenithal position angle of feed and elevation, (ZPA,El).
    92104    int select(
    93105        const int startChan[],
     
    96108        const int getSpectra = 1,
    97109        const int getXPol = 0,
    98         const int getFeedPos = 0);
     110        const int getFeedPos = 0,
     111        const int getPointing = 0,
     112        const int coordSys = 0);
     113
    99114
    100115    // Find the range in time and position of the data selected.
     
    108123    // Read the next data record.
    109124    virtual int read(
    110         PKSMBrecord &record) = 0;
     125//        PKSMBrecord &record) = 0;
     126        MBrecord &record) = 0;
    111127
    112128    // Close the RPFITS file.
     
    114130
    115131  protected:
    116     int    *cBeams, *cEndChan, cGetFeedPos, cGetSpectra, cGetXPol, cHaveBase,
    117            cHaveSpectra, *cHaveXPol, *cIFs, cNBeam, *cNChan, cNIF, *cNPol,
    118            *cRefChan, *cStartChan;
     132    int  *cBeams, *cEndChan, cGetFeedPos, cCoordSys, cGetSpectra, cGetXPol,
     133           cHaveBase, cHaveSpectra, *cHaveXPol, *cIFs, cNBeam, *cNChan, cNIF,
     134           *cNPol, *cRefChan, *cStartChan;
     135
     136    // For use in constructing messages.
     137    char cMsg[256];
     138
    119139};
    120140
  • branches/alma/external/atnf/PKSIO/MBFITSreader.cc

    r1453 r1757  
    22//# MBFITSreader.cc: ATNF single-dish RPFITS reader.
    33//#---------------------------------------------------------------------------
    4 //# Copyright (C) 2000-2006
    5 //# Mark Calabretta, ATNF
     4//# livedata - processing pipeline for single-dish, multibeam spectral data.
     5//# Copyright (C) 2000-2009, Australia Telescope National Facility, CSIRO
    66//#
    7 //# This library is free software; you can redistribute it and/or modify it
    8 //# under the terms of the GNU Library General Public License as published by
    9 //# the Free Software Foundation; either version 2 of the License, or (at your
    10 //# option) any later version.
     7//# This file is part of livedata.
    118//#
    12 //# This library is distributed in the hope that it will be useful, but WITHOUT
     9//# livedata is free software: you can redistribute it and/or modify it under
     10//# the terms of the GNU General Public License as published by the Free
     11//# Software Foundation, either version 3 of the License, or (at your option)
     12//# any later version.
     13//#
     14//# livedata is distributed in the hope that it will be useful, but WITHOUT
    1315//# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    14 //# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Library General Public
    15 //# License for more details.
     16//# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
     17//# more details.
    1618//#
    17 //# You should have received a copy of the GNU Library General Public License
    18 //# along with this library; if not, write to the Free Software Foundation,
    19 //# Inc., 675 Massachusetts Ave, Cambridge, MA 02139, USA.
     19//# You should have received a copy of the GNU General Public License along
     20//# with livedata.  If not, see <http://www.gnu.org/licenses/>.
    2021//#
    21 //# Correspondence concerning this software should be addressed as follows:
    22 //#        Internet email: mcalabre@atnf.csiro.au.
    23 //#        Postal address: Dr. Mark Calabretta,
    24 //#                        Australia Telescope National Facility,
    25 //#                        P.O. Box 76,
    26 //#                        Epping, NSW, 2121,
     22//# Correspondence concerning livedata may be directed to:
     23//#        Internet email: mcalabre@atnf.csiro.au
     24//#        Postal address: Dr. Mark Calabretta
     25//#                        Australia Telescope National Facility, CSIRO
     26//#                        PO Box 76
     27//#                        Epping NSW 1710
    2728//#                        AUSTRALIA
    2829//#
    29 //# $Id$
     30//# http://www.atnf.csiro.au/computing/software/livedata.html
     31//# $Id: MBFITSreader.cc,v 19.57 2009-10-30 06:34:36 cal103 Exp $
    3032//#---------------------------------------------------------------------------
    3133//# The MBFITSreader class reads single dish RPFITS files (such as Parkes
     
    3537//#---------------------------------------------------------------------------
    3638
     39#include <atnf/pks/pks_maths.h>
    3740#include <atnf/PKSIO/MBFITSreader.h>
    38 #include <atnf/PKSIO/PKSMBrecord.h>
    39 
    40 #include <RPFITS.h>
     41#include <atnf/PKSIO/MBrecord.h>
     42
     43#include <casa/Logging/LogIO.h>
    4144
    4245#include <casa/math.h>
     
    4750#include <unistd.h>
    4851
     52#include <RPFITS.h>
     53
    4954using namespace std;
    5055
     
    5257const double PI = 3.141592653589793238462643;
    5358const double TWOPI = 2.0 * PI;
     59const double HALFPI = PI / 2.0;
     60const double R2D = 180.0 / PI;
     61
     62// Class name
     63const string className = "MBFITSreader" ;
    5464
    5565//------------------------------------------------- MBFITSreader::MBFITSreader
     
    8191  cRefChan   = 0x0;
    8292
    83   cVis = new float[2*4*8163];
     93  cVis = 0x0;
     94  cWgt = 0x0;
    8495
    8596  cBeamSel   = 0x0;
     
    91102
    92103  cMBopen = 0;
    93   jstat = -3;
     104
     105  // Tell RPFITSIN not to report errors directly.
     106  //iostat_.errlun = -1;
    94107}
    95108
     
    120133        int  &extraSysCal)
    121134{
     135  const string methodName = "open()" ;
     136  LogIO os( LogOrigin( className, methodName, WHERE ) ) ;
     137
    122138  if (cMBopen) {
    123139    close();
     
    127143
    128144  // Open the RPFITS file.
    129   rpfitsin_(&jstat, cVis, weight, &baseline, &ut, &u, &v, &w, &flag, &bin,
    130             &if_no, &sourceno);
    131 
    132   if (jstat) {
    133     fprintf(stderr, "Failed to open MBFITS file: %s\n", rpname);
     145  int jstat = -3;
     146  if (rpfitsin(jstat)) {
     147    sprintf(cMsg, "Failed to open MBFITS file\n%s", rpname);
     148    os << LogIO::SEVERE << cMsg << LogIO::POST ;
    134149    return 1;
    135150  }
     
    147162  // Read the first header.
    148163  jstat = -1;
    149   rpfitsin_(&jstat, cVis, weight, &baseline, &ut, &u, &v, &w, &flag, &bin,
    150             &if_no, &sourceno);
    151 
    152   if (jstat) {
    153     fprintf(stderr, "Failed to read MBFITS header: %s\n", rpname);
     164  if (rpfitsin(jstat)) {
     165    sprintf(cMsg, "Failed to read MBFITS header in file\n"
     166                  "%s", rpname);
     167    os << LogIO::SEVERE << cMsg << LogIO::POST ;
    154168    close();
    155169    return 1;
     
    159173  cMopra = strncmp(names_.instrument, "ATMOPRA", 7) == 0;
    160174
    161   // Tidbinbilla data has some more.
    162   cTid = strncmp(names_.sta, "tid", 3) == 0;
    163   if (cTid) {
    164     // Telescope position is stored in the source table.
     175  // Non-ATNF data may not store the position in (u,v,w).
     176  if (strncmp(names_.sta, "tid", 3) == 0) {
     177    sprintf(cMsg, "Found Tidbinbilla data");
     178    cSUpos = 1;
     179  } else if (strncmp(names_.sta, "HOB", 3) == 0) {
     180    sprintf(cMsg, "Found Hobart data");
     181    cSUpos = 1;
     182  } else if (strncmp(names_.sta, "CED", 3) == 0) {
     183    sprintf(cMsg, "Found Ceduna data");
     184    cSUpos = 1;
     185  } else {
     186    cSUpos = 0;
     187  }
     188
     189  if (cSUpos) {
     190    strcat(cMsg, ", using telescope position\n         from SU table.");
     191    os << LogIO::WARN << cMsg << LogIO::POST ;
    165192    cInterp = 0;
    166193  }
     194
     195  // Mean scan rate (for timestamp repairs).
     196  cNRate = 0;
     197  cAvRate[0] = 0.0;
     198  cAvRate[1] = 0.0;
     199  cCode5 = 0;
    167200
    168201
     
    176209
    177210  if (cNBeam <= 0) {
    178     fprintf(stderr, "Couldn't determine number of beams.\n");
     211    os << LogIO::SEVERE << "Couldn't determine number of beams." << LogIO::POST ;
    179212    close();
    180213    return 1;
     
    189222  // ...beams present in the data.
    190223  for (int iBeam = 0; iBeam < anten_.nant; iBeam++) {
    191     cBeams[anten_.ant_num[iBeam] - 1] = 1;
     224    // Guard against dubious beam numbers, e.g. zeroes in
     225    // 1999-09-29_1632_024848p14_071b.hpf and the four scans following.
     226    // Note that the actual beam number is decoded from the 'baseline' random
     227    // parameter for each spectrum and is only used for beam selection.
     228    int beamNo = anten_.ant_num[iBeam];
     229    if (beamNo != iBeam+1) {
     230      char sta[8];
     231      strncpy(sta, names_.sta+(8*iBeam), 8);
     232      char *cp = sta + 7;
     233      while (*cp == ' ') *(cp--) = '\0';
     234
     235      sprintf(cMsg,
     236        "RPFITSIN returned beam number %2d for AN table\n"
     237        "entry %2d with name '%.8s'", beamNo, iBeam+1, sta);
     238
     239      char text[8];
     240      sprintf(text, "MB%2.2d", iBeam+1);
     241      cp = cMsg + strlen(cMsg);
     242      if (strncmp(sta, text, 8) == 0) {
     243        beamNo = iBeam + 1;
     244        sprintf(cp, "; using beam number %2d.", beamNo);
     245      } else {
     246        sprintf(cp, ".");
     247      }
     248
     249      os << LogIO::WARN << cMsg << LogIO::POST ;
     250    }
     251
     252    if (0 < beamNo && beamNo <= cNBeam) {
     253      cBeams[beamNo-1] = 1;
     254    }
    192255  }
    193256
     
    237300  }
    238301
    239   // Is the vis array declared by RPFITS.h large enough?
    240   if (8*8193 < maxProd) {
    241     // Need to allocate more memory for RPFITSIN.
    242     cVis = new float[2*maxProd];
    243   }
     302  // Allocate memory for RPFITSIN subroutine arguments.
     303  if (cVis) delete [] cVis;
     304  if (cWgt) delete [] cWgt;
     305  cVis = new float[2*maxProd];
     306  cWgt = new float[maxProd];
    244307
    245308  nChan    = cNChan;
     
    278341  // Read the first syscal record.
    279342  if (rpget(1, cEOS)) {
    280     fprintf(stderr, "Error: Failed to read first syscal record.\n");
     343    os << LogIO::SEVERE << "Failed to read first syscal record." << LogIO::POST ;
    281344    close();
    282345    return 1;
     
    304367        double antPos[3],
    305368        char   obsType[32],
     369        char   bunit[32],
    306370        float  &equinox,
    307371        char   radecsys[32],
     
    312376        double &bandwidth)
    313377{
     378  const string methodName = "getHeader()" ;
     379  LogIO os( LogOrigin( className, methodName, WHERE ) ) ;
     380
    314381  if (!cMBopen) {
    315     fprintf(stderr, "An MBFITS file has not been opened.\n");
     382    os << LogIO::SEVERE << "An MBFITS file has not been opened." << LogIO::POST ;
    316383    return 1;
    317384  }
     
    333400    antPos[1] =  2816759.046;
    334401    antPos[2] = -3454035.950;
     402
    335403  } else if (strncmp(names_.sta, "HOH", 3) == 0) {
    336404    // Parkes HOH receiver.
     
    339407    antPos[1] =  2816759.046;
    340408    antPos[2] = -3454035.950;
     409
    341410  } else if (strncmp(names_.sta, "CA0", 3) == 0) {
    342411    // An ATCA antenna, use the array centre position.
     
    345414    antPos[1] =  2792906.182;
    346415    antPos[2] = -3200483.747;
     416
     417    // ATCA-104.  Updated position at epoch 2007/06/24 from Chris Phillips.
     418    // antPos[0] = -4751640.182; // ± 0.008
     419    // antPos[1] =  2791700.322; // ± 0.006
     420    // antPos[2] = -3200490.668; // ± 0.007
     421    //
    347422  } else if (strncmp(names_.sta, "MOP", 3) == 0) {
    348     // Mopra.
     423    // Mopra.  Updated position at epoch 2007/06/24 from Chris Phillips.
    349424    sprintf(telescope, "%-16.16s", "ATMOPRA");
    350     antPos[0] = -4682768.630;
    351     antPos[1] =  2802619.060;
    352     antPos[2] = -3291759.900;
     425    antPos[0] = -4682769.444; // ± 0.009
     426    antPos[1] =  2802618.963; // ± 0.006
     427    antPos[2] = -3291758.864; // ± 0.008
     428
    353429  } else if (strncmp(names_.sta, "HOB", 3) == 0) {
    354430    // Hobart.
     
    357433    antPos[1] =  2522347.567;
    358434    antPos[2] = -4311562.569;
     435
    359436  } else if (strncmp(names_.sta, "CED", 3) == 0) {
    360     // Ceduna.
     437    // Ceduna.  Updated position at epoch 2007/06/24 from Chris Phillips.
    361438    sprintf(telescope, "%-16.16s", "CEDUNA");
    362     antPos[0] = -3749943.657;
    363     antPos[1] =  3909017.709;
    364     antPos[2] = -3367518.309;
     439    antPos[0] = -3753443.168; // ± 0.017
     440    antPos[1] =  3912709.794; // ± 0.017
     441    antPos[2] = -3348067.060; // ± 0.016
     442
    365443  } else if (strncmp(names_.sta, "tid", 3) == 0) {
    366444    // DSS.
     
    379457  obsType[j] = '\0';
    380458
     459  // Brightness unit.
     460  sprintf(bunit, "%-16.16s", names_.bunit);
     461  if (strcmp(bunit, "JY") == 0) {
     462    bunit[1] = 'y';
     463  } else if (strcmp(bunit, "JY/BEAM") == 0) {
     464    strcpy(bunit, "Jy/beam");
     465  }
     466
    381467  // Coordinate frames.
    382468  equinox = 2000.0f;
     
    386472  // Time at start of observation.
    387473  sprintf(datobs, "%-10.10s", names_.datobs);
    388   utc = ut;
     474  utc = cUTC;
    389475
    390476  // Spectral parameters.
     
    425511//--------------------------------------------------------- MBFITSreader::read
    426512
    427 // Read the next data record.
     513// Read the next data record (if you're feeling lucky).
    428514
    429515int MBFITSreader::read(
    430         PKSMBrecord &MBrec)
     516        MBrecord &MBrec)
    431517{
     518  const string methodName = "read()" ;
     519  LogIO os( LogOrigin( className, methodName, WHERE ) ) ;
     520
    432521  int beamNo = -1;
    433   int haveData, status;
    434   PKSMBrecord *iMBuff = 0x0;
     522  int haveData, pCode = 0, status;
     523  double raRate = 0.0, decRate = 0.0, paRate = 0.0;
     524  MBrecord *iMBuff = 0x0;
    435525
    436526  if (!cMBopen) {
    437     fprintf(stderr, "An MBFITS file has not been opened.\n");
     527    os << LogIO::SEVERE << "An MBFITS file has not been opened." << LogIO::POST ;
    438528    return 1;
    439529  }
    440530
    441   // Positions recorded in the input records do not coincide with the midpoint
    442   // of the integration and hence the input must be buffered so that true
    443   // positions may be interpolated.
     531  // Positions recorded in the input records usually do not coincide with the
     532  // midpoint of the integration and hence the input must be buffered so that
     533  // true positions may be interpolated.
    444534  //
    445535  // On the first call nBeamSel buffers of length nBin, are allocated and
     
    471561
    472562      // Read the next record.
     563      pCode = 0;
    473564      if ((status = rpget(0, cEOS)) == -1) {
    474565        // EOF.
     
    479570
    480571#ifdef PKSIO_DEBUG
    481         printf("End-of-file detected, flushing last scan.\n");
     572        os << LogIO::DEBUGGING << "\nEnd-of-file detected, flushing last cycle.\n" << LogIO::POST ;
    482573#endif
    483574
     
    507598          cXpolOff = new int[cNIF];
    508599
    509           int simulIF = 0;
    510600          int maxChan = 0;
    511601          int maxXpol = 0;
    512602
     603          cSimulIF = 0;
    513604          for (int iIF = 0; iIF < cNIF; iIF++) {
    514605            if (cIFs[iIF]) {
     
    536627
    537628              // Maximum number of selected IFs in any simultaneous set.
    538               simulIF = max(simulIF, cIFSel[iIF]+1);
     629              cSimulIF = max(cSimulIF, cIFSel[iIF]+1);
    539630
    540631              // Maximum memory required for any simultaneous set.
     
    563654
    564655          if (cNBin > 1 && cNBeamSel > 1) {
    565             fprintf(stderr, "Cannot handle binning mode for multiple "
    566                             "beams.\n");
     656            os << LogIO::SEVERE << "Cannot handle binning mode for multiple beams.\nSelect a single beam for input." << LogIO::POST ;
    567657            close();
    568658            return 1;
    569659          }
    570660
    571           // Allocate buffer data storage.
     661          // Allocate buffer data storage; the MBrecord constructor zeroes
     662          // class members such as cycleNo that are tested in the first pass
     663          // below.
    572664          int nBuff = cNBeamSel * cNBin;
    573           cBuffer = new PKSMBrecord[nBuff];
     665          cBuffer = new MBrecord[nBuff];
    574666
    575667          // Allocate memory for spectral arrays.
    576668          for (int ibuff = 0; ibuff < nBuff; ibuff++) {
    577             cBuffer[ibuff].setNIFs(simulIF);
     669            cBuffer[ibuff].setNIFs(cSimulIF);
    578670            cBuffer[ibuff].allocate(0, maxChan, maxXpol);
     671
     672            // Signal that this IF in this buffer has been flushed.
     673            for (int iIF = 0; iIF < cSimulIF; iIF++) {
     674              cBuffer[ibuff].IFno[iIF] = 0;
     675            }
    579676          }
    580677
     
    584681          cScanNo  = 1;
    585682          cCycleNo = 0;
    586           cUTC = 0.0;
    587           cStaleness = new int[cNBeamSel];
    588           for (int iBeamSel = 0; iBeamSel < cNBeamSel; iBeamSel++) {
    589             cStaleness[iBeamSel] = 0;
    590           }
     683          cPrevUTC = -1.0;
    591684        }
    592685
     
    595688          cScanNo++;
    596689          cCycleNo = 0;
    597           cUTC = 0.0;
    598         }
    599 
    600         // Apply beam selection.
    601         beamNo = int(baseline / 256.0);
     690          cPrevUTC = -1.0;
     691        }
     692
     693        // Apply beam and IF selection before the change-of-day test to allow
     694        // a single selected beam and IF to be handled in binning-mode.
     695        beamNo = int(cBaseline / 256.0);
     696        if (beamNo == 1) {
     697          // Store the position of beam 1 for grid convergence corrections.
     698          cRA0  = cU;
     699          cDec0 = cV;
     700        }
    602701        iBeamSel = cBeamSel[beamNo-1];
    603702        if (iBeamSel < 0) continue;
    604703
    605704        // Sanity check (mainly for MOPS).
    606         if (if_no > cNIF) continue;
    607 
    608         // Apply IF selection.
    609         iIFSel = cIFSel[if_no - 1];
     705        if (cIFno > cNIF) continue;
     706
     707        // Apply IF selection; iIFSel == 0 for the first selected IF, == 1
     708        // for the second, etc.
     709        iIFSel = cIFSel[cIFno - 1];
    610710        if (iIFSel < 0) continue;
    611711
    612         sprintf(cDateObs, "%-10.10s", names_.datobs);
    613 
    614         // Change-of-day; note that the ut variable from RPFITS.h is global
    615         // and will be preserved between calls to this function.
    616         if (ut < cUTC - 85800.0) {
    617           ut += 86400.0;
    618         }
    619 
    620         // New integration cycle?
    621         if (ut > cUTC) {
    622           cCycleNo++;
    623           cUTC = ut + 0.0001;
    624         }
    625712
    626713        if (cNBin > 1) {
    627714          // Binning mode: correct the time.
    628           ut += param_.intbase * (bin - (cNBin + 1)/2.0);
    629         }
     715          cUTC += param_.intbase * (cBin - (cNBin + 1)/2.0);
     716        }
     717
     718        // Check for change-of-day.
     719        double cod = 0.0;
     720        if ((cUTC + 86400.0) < (cPrevUTC + 600.0)) {
     721          // cUTC should continue to increase past 86400 during a single scan.
     722          // However, if the RPFITS file contains multiple scans that straddle
     723          // midnight then cUTC can jump backwards from the end of one scan to
     724          // the start of the next.
     725#ifdef PKSIO_DEBUG
     726          char buf[256] ;
     727          sprintf(buf, "Change-of-day on cUTC: %.1f -> %.1f\n", cPrevUTC, cUTC);
     728          os << LogIO::DEBUGGING << buf << LogIO::POST ;
     729#endif
     730          // Can't change the recorded value of cUTC directly (without also
     731          // changing dateobs) so change-of-day must be recorded separately as
     732          // an offset to be applied when comparing integration timestamps.
     733          cod = 86400.0;
     734
     735        }
     736
     737        if ((cUTC+cod) < cPrevUTC - 1.0) {
     738          if (cBin == 1 && iIFSel) {
     739            // Multiple-IF, binning-mode data is only partially time ordered.
     740#ifdef PKSIO_DEBUG
     741            fprintf(stderr, "New IF in multiple-IF, binning-mode data.\n");
     742#endif
     743            cCycleNo -= cNBin;
     744            cPrevUTC = -1.0;
     745
     746          } else {
     747            // All other data should be fully time ordered.
     748            sprintf(cMsg,
     749              "Cycle %d:%03d-%03d, UTC went backwards from\n"
     750              "%.1f to %.1f!  Incrementing day number,\n"
     751              "positions may be unreliable.", cScanNo, cCycleNo,
     752              cCycleNo+1, cPrevUTC, cUTC);
     753            //logMsg(cMsg);
     754            os << LogIO::WARN << cMsg << LogIO::POST ;
     755            cUTC += 86400.0;
     756          }
     757        }
     758
     759        // New integration cycle?
     760        if ((cUTC+cod) > cPrevUTC) {
     761          cCycleNo++;
     762          cPrevUTC = cUTC + 0.0001;
     763        }
     764
     765        sprintf(cDateObs, "%-10.10s", names_.datobs);
     766        cDateObs[10] = '\0';
    630767
    631768        // Compute buffer number.
    632769        iMBuff = cBuffer + iBeamSel;
    633         if (cNBin > 1) iMBuff += cNBeamSel*(bin-1);
     770        if (cNBin > 1) iMBuff += cNBeamSel*(cBin-1);
    634771
    635772        if (cCycleNo < iMBuff->cycleNo) {
     
    640777
    641778        // Begin flush cycle?
    642         if (cEOS || (iMBuff->nIF && ut > iMBuff->utc + 0.0001)) {
     779        if (cEOS || (iMBuff->nIF && (cUTC+cod) > (iMBuff->utc+0.0001))) {
    643780          cFlushing = 1;
    644781          cFlushBin = 0;
     
    647784
    648785#ifdef PKSIO_DEBUG
    649         printf(" In:%4d%4d%3d%3d\n", cScanNo, cCycleNo, beamNo, if_no);
    650         if (cEOS) printf("Start of new scan, flushing previous scan.\n");
     786        char rel = '=';
     787        double dt = utcDiff(cUTC, cW);
     788        if (dt < 0.0) {
     789          rel = '<';
     790        } else if (dt > 0.0) {
     791          rel = '>';
     792        }
     793
     794        sprintf(buf, "\n In:%4d%4d%3d%3d  %.3f %c %.3f (%+.3fs) - "
     795          "%sflushing\n", cScanNo, cCycleNo, beamNo, cIFno, cUTC, rel, cW, dt,
     796          cFlushing ? "" : "not ");
     797        os << LogIO::DEBUGGING << buf << LogIO::POST ;
     798        if (cEOS) {
     799          sprintf(buf, "Start of new scan, flushing previous scan.\n");
     800          os << LogIO::DEBUGGING << buf << LogIO::POST ;
     801        }
    651802#endif
    652803      }
     
    663814          iMBuff = cBuffer + iBeamSel + cNBeamSel*cFlushBin;
    664815
    665           // iMBuff->nIF is set to zero (below) to signal that all IFs in
    666           // an integration have been flushed.
     816          // iMBuff->nIF is decremented (below) and if zero signals that all
     817          // IFs in an integration have been flushed.
    667818          if (iMBuff->nIF) {
    668819            if (cycleNo == 0 || iMBuff->cycleNo < cycleNo) {
     
    677828          break;
    678829        }
     830
     831        // Start with the first IF in the next bin.
     832        cFlushIF = 0;
    679833      }
    680834
     
    684838
    685839        // Find the IF to flush.
    686         for (; cFlushIF < iMBuff->nIF; cFlushIF++) {
     840        for (; cFlushIF < cSimulIF; cFlushIF++) {
    687841          if (iMBuff->IFno[cFlushIF]) break;
    688842        }
     
    696850
    697851        // The last record read must have been the first of a new cycle.
    698         beamNo = int(baseline / 256.0);
     852        beamNo = int(cBaseline / 256.0);
    699853        iBeamSel = cBeamSel[beamNo-1];
    700854
    701855        // Compute buffer number.
    702856        iMBuff = cBuffer + iBeamSel;
    703         if (cNBin > 1) iMBuff += cNBeamSel*(bin-1);
     857        if (cNBin > 1) iMBuff += cNBeamSel*(cBin-1);
    704858      }
    705859    }
    706860
    707861
    708     if (cFlushing && cFlushBin == 0 && cFlushIF == 0 && cInterp) {
    709       // Interpolate the beam position at the start of the flush cycle.
     862    if (cInterp && cFlushing == 1) {
     863      // Start of flush cycle, interpolate the beam position.
     864      //
     865      // The position is measured by the control system at a time returned by
     866      // RPFITSIN as the 'w' visibility coordinate.  The ra and dec, returned
     867      // as the 'u' and 'v' visibility coordinates, must be interpolated to
     868      // the integration time which RPFITSIN returns as 'cUTC', this usually
     869      // being a second or two later.  The interpolation method used here is
     870      // based on the scan rate.
     871      //
     872      // "This" RA, Dec, and UTC refers to the position currently stored in
     873      // the buffer marked for output (iMBuff).  This position is interpolated
     874      // to the midpoint of that integration using either
     875      //   a) the rate currently sitting in iMBuff, which was computed from
     876      //      the previous integration, otherwise
     877      //   b) from the position recorded in the "next" integration which is
     878      //      currently sitting in the RPFITS commons,
     879      // so that the position timestamps straddle the midpoint of the
     880      // integration and is thereby interpolated rather than extrapolated.
     881      //
     882      // At the end of a scan, or if the next position has not been updated
     883      // or its timestamp does not advance sufficiently, the most recent
     884      // determination of the scan rate will be used for extrapolation which
     885      // is quantified by the "rate age" measured in seconds beyond the
     886      // interval defined by the position timestamps.
     887
     888      // At this point, iMBuff contains cU, cV, cW, parAngle and focusRot
     889      // stored from the previous call to rpget() for this beam (i.e. "this"),
     890      // and also raRate, decRate and paRate computed from that integration
     891      // and the previous one.
     892      double thisRA  = iMBuff->ra;
     893      double thisDec = iMBuff->dec;
     894      double thisUTC = cPosUTC[iBeamSel];
     895      double thisPA  = iMBuff->parAngle + iMBuff->focusRot;
     896
    710897#ifdef PKSIO_DEBUG
    711       printf("Doing position interpolation for beam %d.\n", iMBuff->beamNo);
     898      sprintf(buf, "This (%d) ra, dec, UTC: %9.4f %9.4f %10.3f %9.4f\n",
     899        iMBuff->cycleNo, thisRA*R2D, thisDec*R2D, thisUTC, thisPA*R2D);
     900      os << LogIO::DEBUGGING << buf << LogIO::POST ;
    712901#endif
    713902
    714       double prevRA  = iMBuff->ra;
    715       double prevDec = iMBuff->dec;
    716       double prevUTC = cPosUTC[iBeamSel];
    717 
    718       if (!cEOF && !cEOS) {
    719         // The position is measured by the control system at a time returned
    720         // by RPFITSIN as the 'w' visibility coordinate.  The ra and dec,
    721         // returned as the 'u' and 'v' visibility coordinates, must be
    722         // interpolated to the integration time which RPFITSIN returns as
    723         // 'ut', this usually being a second or two later.
    724         //
    725         // Note that the time recorded as the 'w' visibility coordinate
    726         // cycles through 86400 back to 0 at midnight, whereas that in 'ut'
    727         // continues to increase past 86400.
    728 
    729         double thisRA  = u;
    730         double thisDec = v;
    731         double thisUTC = w;
    732 
    733         if (thisUTC < prevUTC) {
    734           // Must have cycled through midnight.
    735           thisUTC += 86400.0;
    736         }
    737 
    738         // Guard against RA cycling through 24h in either direction.
    739         if (fabs(thisRA - prevRA) > PI) {
    740           if (thisRA < prevRA) {
    741             thisRA += TWOPI;
     903      if (cEOF || cEOS) {
     904        // Use rates from the last cycle.
     905        raRate  = iMBuff->raRate;
     906        decRate = iMBuff->decRate;
     907        paRate  = iMBuff->paRate;
     908
     909      } else {
     910        if (cW == thisUTC) {
     911          // The control system at Mopra typically does not update the
     912          // positions between successive integration cycles at the end of a
     913          // scan (nor are they flagged).  In this case we use the previously
     914          // computed rates, even if from the previous scan since these are
     915          // likely to be a better guess than anything else.
     916          raRate  = iMBuff->raRate;
     917          decRate = iMBuff->decRate;
     918          paRate  = iMBuff->paRate;
     919
     920          if (cU == thisRA && cV == thisDec) {
     921            // Position and timestamp unchanged.
     922            pCode = 1;
     923
     924          } else if (fabs(cU-thisRA) < 0.0001 && fabs(cV-thisDec) < 0.0001) {
     925            // Allow small rounding errors (seen infrequently).
     926            pCode = 1;
     927
    742928          } else {
    743             thisRA -= TWOPI;
     929            // (cU,cV) are probably rubbish (not yet seen in practice).
     930            pCode = 2;
     931            cU = thisRA;
     932            cV = thisDec;
    744933          }
    745         }
    746 
    747         // The control system at Mopra typically does not update the
    748         // positions between successive integration cycles at the end of a
    749         // scan (nor are they flagged).  In this case we use the previously
    750         // computed rates, even if from the previous scan since these are
    751         // likely to be a better guess than anything else.
    752 
    753         double dUTC = thisUTC - prevUTC;
    754 
    755         // Scan rate for this beam.
    756         if (dUTC > 0.0) {
    757           iMBuff->raRate  = (thisRA  - prevRA)  / dUTC;
    758           iMBuff->decRate = (thisDec - prevDec) / dUTC;
    759 
    760           if (cInterp == 2) {
    761             // Use the same interpolation scheme as the original pksmbfits
    762             // client.  This incorrectly assumed that (thisUTC - prevUTC) is
    763             // equal to the integration time and interpolated by computing a
    764             // weighted sum of the positions before and after the required
    765             // time.
    766 
    767             double utc = iMBuff->utc;
    768             if (utc - prevUTC > 100.0) {
    769               // Must have cycled through midnight.
    770               utc -= 86400.0;
     934
     935#ifdef PKSIO_DEBUG
     936          sprintf(buf, "Next (%d) ra, dec, UTC: %9.4f %9.4f %10.3f "
     937            "(0.000s)\n", cCycleNo, cU*R2D, cV*R2D, cW);
     938          os << LogIO::DEBUGGING << buf << LogIO::POST ;
     939#endif
     940
     941        } else {
     942          double nextRA  = cU;
     943          double nextDec = cV;
     944
     945          // Check and, if necessary, repair the position timestamp,
     946          // remembering that pCode refers to the NEXT cycle.
     947          pCode = fixw(cDateObs, cCycleNo, beamNo, cAvRate, thisRA, thisDec,
     948                       thisUTC, nextRA, nextDec, cW);
     949          if (pCode > 0) pCode += 3;
     950          double nextUTC = cW;
     951
     952#ifdef PKSIO_DEBUG
     953          sprintf(buf, "Next (%d) ra, dec, UTC: %9.4f %9.4f %10.3f "
     954            "(%+.3fs)\n", cCycleNo, nextRA*R2D, nextDec*R2D, nextUTC,
     955            utcDiff(nextUTC, thisUTC));
     956          os << LogIO::DEBUGGING << buf << LogIO::POST ;
     957#endif
     958
     959          // Compute the scan rate for this beam.
     960          double dUTC = utcDiff(nextUTC, thisUTC);
     961          if ((0.0 < dUTC) && (dUTC < 600.0)) {
     962            scanRate(cRA0, cDec0, thisRA, thisDec, nextRA, nextDec, dUTC,
     963                     raRate, decRate);
     964
     965            // Update the mean scan rate.
     966            cAvRate[0] = (cAvRate[0]*cNRate +  raRate) / (cNRate + 1);
     967            cAvRate[1] = (cAvRate[1]*cNRate + decRate) / (cNRate + 1);
     968            cNRate++;
     969
     970            // Rate of change of position angle.
     971            if (sc_.sc_ant <= anten_.nant) {
     972              paRate = 0.0;
     973            } else {
     974              int iOff = sc_.sc_q * (sc_.sc_ant - 1) - 1;
     975              double nextPA = sc_.sc_cal[iOff + 4] + sc_.sc_cal[iOff + 7];
     976              double paDiff = nextPA - thisPA;
     977              if (paDiff > PI) {
     978                paDiff -= TWOPI;
     979              } else if (paDiff < -PI) {
     980                paDiff += TWOPI;
     981              }
     982              paRate = paDiff / dUTC;
    771983            }
    772984
    773             double tw1 = 1.0 - (utc - prevUTC) / iMBuff->exposure;
    774             double tw2 = 1.0 - (thisUTC - utc) / iMBuff->exposure;
    775             double gamma = (tw2 / (tw1 + tw2)) * dUTC / (utc - prevUTC);
    776 
    777             iMBuff->raRate  *= gamma;
    778             iMBuff->decRate *= gamma;
    779           }
    780 
    781           cStaleness[iBeamSel] = 0;
    782 
    783         } else {
    784           // Issue warnings.
    785           int nch = 0;
    786           fprintf(stderr, "WARNING, scan %d,%n cycle %d: Position ",
    787             iMBuff->scanNo, &nch, iMBuff->cycleNo);
    788 
    789           if (dUTC < 0.0) {
    790             fprintf(stderr, "timestamp went backwards!\n");
     985            if (cInterp == 2) {
     986              // Use the same interpolation scheme as the original pksmbfits
     987              // client.  This incorrectly assumed that (nextUTC - thisUTC) is
     988              // equal to the integration time and interpolated by computing a
     989              // weighted sum of the positions before and after the required
     990              // time.
     991
     992              double utc = iMBuff->utc;
     993              double tw1 = 1.0 - utcDiff(utc, thisUTC) / iMBuff->exposure;
     994              double tw2 = 1.0 - utcDiff(nextUTC, utc) / iMBuff->exposure;
     995              double gamma = (tw2 / (tw1 + tw2)) * dUTC / (utc - thisUTC);
     996
     997              // Guard against RA cycling through 24h in either direction.
     998              if (fabs(nextRA - thisRA) > PI) {
     999                if (nextRA < thisRA) {
     1000                  nextRA += TWOPI;
     1001                } else {
     1002                  nextRA -= TWOPI;
     1003                }
     1004              }
     1005
     1006              raRate  = gamma * (nextRA  - thisRA)  / dUTC;
     1007              decRate = gamma * (nextDec - thisDec) / dUTC;
     1008            }
     1009
    7911010          } else {
    792             if (thisRA != prevRA || thisDec != prevDec) {
    793               fprintf(stderr, "changed but timestamp unchanged!\n");
     1011            if (cCycleNo == 2 && fabs(utcDiff(cUTC,cW)) < 600.0) {
     1012              // thisUTC (i.e. cW for the first cycle) is rubbish, and
     1013              // probably the position as well (extremely rare in practice,
     1014              // e.g. 97-12-19_1029_235708-18_586e.hpf which actually has the
     1015              // t/1000 scaling bug in the first cycle).
     1016              iMBuff->pCode = 3;
     1017              thisRA  = cU;
     1018              thisDec = cV;
     1019              thisUTC = cW;
     1020              raRate  = 0.0;
     1021              decRate = 0.0;
     1022              paRate  = 0.0;
     1023
    7941024            } else {
    795               fprintf(stderr, "and timestamp unchanged!\n");
     1025              // cW is rubbish and probably (cU,cV), and possibly the
     1026              // parallactic angle and everything else as well (rarely seen
     1027              // in practice, e.g. 97-12-09_0743_235707-58_327c.hpf and
     1028              // 97-09-01_0034_123717-42_242b.hpf, the latter with bad
     1029              // parallactic angle).
     1030              pCode = 3;
     1031              cU = thisRA;
     1032              cV = thisDec;
     1033              cW = thisUTC;
     1034              raRate  = iMBuff->raRate;
     1035              decRate = iMBuff->decRate;
     1036              paRate  = iMBuff->paRate;
    7961037            }
    7971038          }
    798 
    799           cStaleness[iBeamSel]++;
    800           fprintf(stderr, "%-*s Using stale scan rate, staleness = %d "
    801             "cycle%s.\n", nch, "WARNING,", cStaleness[iBeamSel],
    802             (cStaleness[iBeamSel] == 1) ? "" : "s");
    803 
    804           if (thisRA != prevRA || thisDec != prevDec) {
    805             if (iMBuff->raRate == 0.0 && iMBuff->decRate == 0.0) {
    806               fprintf(stderr, "%-*s But the previous rate was zero!  "
    807                 "Position will be inaccurate.\n", nch, "WARNING,");
     1039        }
     1040      }
     1041
     1042
     1043      // Choose the closest rate determination.
     1044      if (cCycleNo == 1) {
     1045        // Scan containing a single integration.
     1046        iMBuff->raRate  = 0.0;
     1047        iMBuff->decRate = 0.0;
     1048        iMBuff->paRate  = 0.0;
     1049
     1050      } else {
     1051        double dUTC = iMBuff->utc - cPosUTC[iBeamSel];
     1052
     1053        if (dUTC >= 0.0) {
     1054          // In HIPASS/ZOA, the position timestamp, which should always occur
     1055          // on the whole second, normally precedes an integration midpoint
     1056          // falling on the half-second.  Consequently, positive ages are
     1057          // always half-integral.
     1058          dUTC = utcDiff(iMBuff->utc, cW);
     1059          if (dUTC > 0.0) {
     1060            iMBuff->rateAge = dUTC;
     1061          } else {
     1062            iMBuff->rateAge = 0.0f;
     1063          }
     1064
     1065          iMBuff->raRate  =  raRate;
     1066          iMBuff->decRate = decRate;
     1067          iMBuff->paRate  =  paRate;
     1068
     1069        } else {
     1070          // In HIPASS/ZOA, negative ages occur when the integration midpoint,
     1071          // occurring on the whole second, precedes the position timestamp.
     1072          // Thus negative ages are always an integral number of seconds.
     1073          // They have only been seen to occur sporadically in the period
     1074          // 1999/05/31 to 1999/11/01, e.g. 1999-07-26_1821_005410-74_007c.hpf
     1075          //
     1076          // In recent (2008/10/07) Mopra data, small negative ages (~10ms,
     1077          // occasionally up to ~300ms) seem to be the norm, with both the
     1078          // position timestamp and integration midpoint falling close to but
     1079          // not on the integral second.
     1080          if (cCycleNo == 2) {
     1081            // We have to start with something!
     1082            iMBuff->rateAge = dUTC;
     1083
     1084          } else {
     1085            // Although we did not record the relevant position timestamp
     1086            // explicitly, it can easily be deduced.
     1087            double w = iMBuff->utc - utcDiff(cUTC, iMBuff->utc) -
     1088                       iMBuff->rateAge;
     1089            dUTC = utcDiff(iMBuff->utc, w);
     1090
     1091            if (dUTC > 0.0) {
     1092              iMBuff->rateAge = 0.0f;
     1093            } else {
     1094              iMBuff->rateAge = dUTC;
    8081095            }
    8091096          }
    810         }
    811       }
     1097
     1098          iMBuff->raRate  =  raRate;
     1099          iMBuff->decRate = decRate;
     1100          iMBuff->paRate  =  paRate;
     1101        }
     1102      }
     1103
     1104#ifdef PKSIO_DEBUG
     1105      double avRate = sqrt(cAvRate[0]*cAvRate[0] + cAvRate[1]*cAvRate[1]);
     1106      sprintf(buf, "RA, Dec, Av & PA rates: %8.4f %8.4f %8.4f %8.4f "
     1107        "pCode %d\n", raRate*R2D, decRate*R2D, avRate*R2D, paRate*R2D, pCode);
     1108      os << LogIO::DEBUGGING << buf << LogIO::POST ;
     1109#endif
     1110
    8121111
    8131112      // Compute the position of this beam for all bins.
     
    8171116        cBuffer[jbuff].raRate  = iMBuff->raRate;
    8181117        cBuffer[jbuff].decRate = iMBuff->decRate;
    819 
    820         double dutc = cBuffer[jbuff].utc - prevUTC;
    821         if (dutc > 100.0) {
     1118        cBuffer[jbuff].paRate  = iMBuff->paRate;
     1119
     1120        double dUTC = utcDiff(cBuffer[jbuff].utc, thisUTC);
     1121        if (dUTC > 100.0) {
    8221122          // Must have cycled through midnight.
    823           dutc -= 86400.0;
    824         }
    825 
    826         cBuffer[jbuff].ra  = prevRA  + cBuffer[jbuff].raRate  * dutc;
    827         cBuffer[jbuff].dec = prevDec + cBuffer[jbuff].decRate * dutc;
    828         if (cBuffer[jbuff].ra < 0.0) {
    829           cBuffer[jbuff].ra += TWOPI;
    830         } else if (cBuffer[jbuff].ra > TWOPI) {
    831           cBuffer[jbuff].ra -= TWOPI;
    832         }
    833       }
     1123          dUTC -= 86400.0;
     1124        }
     1125
     1126        applyRate(cRA0, cDec0, thisRA, thisDec,
     1127          cBuffer[jbuff].raRate, cBuffer[jbuff].decRate, dUTC,
     1128          cBuffer[jbuff].ra, cBuffer[jbuff].dec);
     1129
     1130#ifdef PKSIO_DEBUG
     1131        sprintf(buf, "Intp (%d) ra, dec, UTC: %9.4f %9.4f %10.3f (pCode, "
     1132          "age: %d %.1fs)\n", iMBuff->cycleNo, cBuffer[jbuff].ra*R2D,
     1133          cBuffer[jbuff].dec*R2D, cBuffer[jbuff].utc, iMBuff->pCode,
     1134          iMBuff->rateAge);
     1135        os << LogIO::DEBUGGING << buf << LogIO::POST ;
     1136#endif
     1137      }
     1138
     1139      cFlushing = 2;
    8341140    }
    8351141
     
    8411147
    8421148#ifdef PKSIO_DEBUG
    843       printf("Out:%4d%4d%3d%3d\n", MBrec.scanNo, MBrec.cycleNo, MBrec.beamNo,
    844         MBrec.IFno[0]);
     1149      sprintf(buf, "Out:%4d%4d%3d%3d\n", MBrec.scanNo, MBrec.cycleNo,
     1150        MBrec.beamNo, MBrec.IFno[0]);
     1151      os << LogIO::DEBUGGING << buf << LogIO::POST ;
    8451152#endif
    8461153
     
    8481155      iMBuff->IFno[cFlushIF] = 0;
    8491156
    850       if (cFlushIF == iMBuff->nIF - 1) {
    851         // Signal that all IFs in this buffer location have been flushed.
    852         iMBuff->nIF = 0;
     1157      iMBuff->nIF--;
     1158      if (iMBuff->nIF == 0) {
     1159        // All IFs in this buffer location have been flushed.  Stop cEOS
     1160        // being set when the next integration is read.
     1161        iMBuff->cycleNo = 0;
     1162
    8531163      } else {
    8541164        // Carry on flushing the other IFs.
     
    8591169      if (cFlushBin == cNBin - 1) {
    8601170        if (cEOS || cEOF) {
    861           // Stop cEOS being set when the next integration is read.
    862           iMBuff->cycleNo = 0;
    863 
    8641171          // Carry on flushing other buffers.
    8651172          cFlushIF = 0;
     
    8691176        cFlushing = 0;
    8701177
    871         beamNo = int(baseline / 256.0);
     1178        beamNo = int(cBaseline / 256.0);
    8721179        iBeamSel = cBeamSel[beamNo-1];
    8731180
    8741181        // Compute buffer number.
    8751182        iMBuff = cBuffer + iBeamSel;
    876         if (cNBin > 1) iMBuff += cNBeamSel*(bin-1);
     1183        if (cNBin > 1) iMBuff += cNBeamSel*(cBin-1);
    8771184      }
    8781185    }
     
    8801187    if (!cFlushing) {
    8811188      // Buffer this MBrec.
    882       if (cCycleNo == 1 && iMBuff->IFno[0]) {
     1189      if ((cScanNo > iMBuff->scanNo) && iMBuff->IFno[0]) {
    8831190        // Sanity check on the number of IFs in the new scan.
    8841191        if (if_.n_if != cNIF) {
    885           fprintf(stderr, "WARNING, scan %d has %d IFs instead of %d, "
    886             "continuing.\n", cScanNo, if_.n_if, cNIF);
    887         }
    888       }
    889 
    890       iMBuff->scanNo  = cScanNo;
    891       iMBuff->cycleNo = cCycleNo;
    892 
    893       // Times.
    894       strncpy(iMBuff->datobs, cDateObs, 10);
    895       iMBuff->utc = ut;
    896       iMBuff->exposure = param_.intbase;
    897 
    898       // Source identification.
    899       sprintf(iMBuff->srcName, "%-16.16s",
    900               names_.su_name + (sourceno-1)*16);
    901       iMBuff->srcRA  = doubles_.su_ra[sourceno-1];
    902       iMBuff->srcDec = doubles_.su_dec[sourceno-1];
    903 
    904       // Rest frequency of the line of interest.
    905       iMBuff->restFreq = doubles_.rfreq;
    906       if (strncmp(names_.instrument, "ATPKSMB", 7) == 0) {
    907         // Fix the HI rest frequency recorded for Parkes multibeam data.
    908         double reffreq  = doubles_.freq;
    909         double restfreq = doubles_.rfreq;
    910         if ((restfreq == 0.0 || fabs(restfreq - reffreq) == 0.0) &&
    911              fabs(reffreq - 1420.40575e6) < 100.0) {
    912           iMBuff->restFreq = 1420.40575e6;
    913         }
    914       }
    915 
    916       // Observation type.
    917       int j;
    918       for (j = 0; j < 15; j++) {
    919         iMBuff->obsType[j] = names_.card[11+j];
    920         if (iMBuff->obsType[j] == '\'') break;
    921       }
    922       iMBuff->obsType[j] = '\0';
    923 
    924       // Beam-dependent parameters.
    925       iMBuff->beamNo = beamNo;
    926 
    927       // Beam position at the specified time.
    928       if (cTid) {
    929         // Tidbinbilla data.
    930         iMBuff->ra  = doubles_.su_ra[sourceno-1];
    931         iMBuff->dec = doubles_.su_dec[sourceno-1];
    932       } else {
    933         iMBuff->ra  = u;
    934         iMBuff->dec = v;
    935       }
    936       cPosUTC[iBeamSel] = w;
     1192          sprintf(cMsg, "Scan %d has %d IFs instead of %d, "
     1193            "continuing.", cScanNo, if_.n_if, cNIF);
     1194          os << LogIO::WARN << cMsg << LogIO::POST ;
     1195        }
     1196      }
     1197
     1198      // Sanity check on incomplete integrations within a scan.
     1199      if (iMBuff->nIF && (iMBuff->cycleNo != cCycleNo)) {
     1200        // Force the incomplete integration to be flushed before proceeding.
     1201        cFlushing = 1;
     1202        continue;
     1203      }
     1204
     1205#ifdef PKSIO_DEBUG
     1206      sprintf(buf, "Buf:%4d%4d%3d%3d\n", cScanNo, cCycleNo, beamNo, cIFno);
     1207      os << LogIO::DEBUGGING << buf << LogIO::POST ;
     1208#endif
     1209
     1210      // Store IF-independent parameters only for the first IF of a new cycle,
     1211      // particularly because this is the only one for which the scan rates
     1212      // are computed above.
     1213      int firstIF = (iMBuff->nIF == 0);
     1214      if (firstIF) {
     1215        iMBuff->scanNo  = cScanNo;
     1216        iMBuff->cycleNo = cCycleNo;
     1217
     1218        // Times.
     1219        strcpy(iMBuff->datobs, cDateObs);
     1220        iMBuff->utc = cUTC;
     1221        iMBuff->exposure = param_.intbase;
     1222
     1223        // Source identification.
     1224        sprintf(iMBuff->srcName, "%-16.16s",
     1225                names_.su_name + (cSrcNo-1)*16);
     1226        iMBuff->srcName[16] = '\0';
     1227        iMBuff->srcRA  = doubles_.su_ra[cSrcNo-1];
     1228        iMBuff->srcDec = doubles_.su_dec[cSrcNo-1];
     1229
     1230        // Rest frequency of the line of interest.
     1231        iMBuff->restFreq = doubles_.rfreq;
     1232        if (strncmp(names_.instrument, "ATPKSMB", 7) == 0) {
     1233          // Fix the HI rest frequency recorded for Parkes multibeam data.
     1234          double reffreq  = doubles_.freq;
     1235          double restfreq = doubles_.rfreq;
     1236          if ((restfreq == 0.0 || fabs(restfreq - reffreq) == 0.0) &&
     1237               fabs(reffreq - 1420.405752e6) < 100.0) {
     1238            iMBuff->restFreq = 1420.405752e6;
     1239          }
     1240        }
     1241
     1242        // Observation type.
     1243        int j;
     1244        for (j = 0; j < 15; j++) {
     1245          iMBuff->obsType[j] = names_.card[11+j];
     1246          if (iMBuff->obsType[j] == '\'') break;
     1247        }
     1248        iMBuff->obsType[j] = '\0';
     1249
     1250        // Beam-dependent parameters.
     1251        iMBuff->beamNo = beamNo;
     1252
     1253        // Beam position at the specified time.
     1254        if (cSUpos) {
     1255          // Non-ATNF data that does not store the position in (u,v,w).
     1256          iMBuff->ra  = doubles_.su_ra[cSrcNo-1];
     1257          iMBuff->dec = doubles_.su_dec[cSrcNo-1];
     1258        } else {
     1259          iMBuff->ra  = cU;
     1260          iMBuff->dec = cV;
     1261        }
     1262        cPosUTC[iBeamSel] = cW;
     1263        iMBuff->pCode = pCode;
     1264
     1265        // Store rates for next time.
     1266        iMBuff->raRate  =  raRate;
     1267        iMBuff->decRate = decRate;
     1268        iMBuff->paRate  =  paRate;
     1269      }
    9371270
    9381271      // IF-dependent parameters.
    939       int iIF = if_no - 1;
     1272      int iIF = cIFno - 1;
    9401273      int startChan = cStartChan[iIF];
    9411274      int endChan   = cEndChan[iIF];
     
    9451278
    9461279      iIFSel = cIFSel[iIF];
    947       iMBuff->nIF++;
    948       iMBuff->IFno[iIFSel]  = if_no;
     1280      if (iMBuff->IFno[iIFSel] == 0) {
     1281        iMBuff->nIF++;
     1282        iMBuff->IFno[iIFSel] = cIFno;
     1283      } else {
     1284        // Integration cycle written to the output file twice (the only known
     1285        // example is 1999-05-22_1914_000-031805_03v.hpf).
     1286        sprintf(cMsg, "Integration cycle %d:%d, beam %2d, \n"
     1287                      "IF %d was duplicated.", cScanNo, cCycleNo-1,
     1288                      beamNo, cIFno);
     1289        os << LogIO::WARN << cMsg << LogIO::POST ;
     1290      }
    9491291      iMBuff->nChan[iIFSel] = nChan;
    9501292      iMBuff->nPol[iIFSel]  = cNPol[iIF];
     
    10051347
    10061348      // The baseline flag may be set independently.
    1007       if (rpflag == 0) rpflag = flag;
     1349      if (rpflag == 0) rpflag = cFlag;
    10081350
    10091351      // Copy and scale data.
     
    10461388
    10471389
    1048       // Parallactic angle.
    1049       iMBuff->parAngle = sc_.sc_cal[scq*iBeam + 11];
    1050 
    10511390      // Calibration factor applied to the data by the correlator.
    10521391      if (scq > 14) {
     
    10591398      }
    10601399
    1061       if (sc_.sc_ant <= anten_.nant) {
    1062         // No extra syscal information present.
    1063         iMBuff->extraSysCal = 0;
    1064         iMBuff->azimuth   = 0.0f;
    1065         iMBuff->elevation = 0.0f;
    1066         iMBuff->parAngle  = 0.0f;
    1067         iMBuff->focusAxi  = 0.0f;
    1068         iMBuff->focusTan  = 0.0f;
    1069         iMBuff->focusRot  = 0.0f;
    1070         iMBuff->temp      = 0.0f;
    1071         iMBuff->pressure  = 0.0f;
    1072         iMBuff->humidity  = 0.0f;
    1073         iMBuff->windSpeed = 0.0f;
    1074         iMBuff->windAz    = 0.0f;
    1075         strcpy(iMBuff->tcalTime, "                ");
    1076         iMBuff->refBeam = 0;
    1077 
    1078       } else {
    1079         // Additional information for Parkes Multibeam data.
    1080         int iOff = scq*(sc_.sc_ant - 1) - 1;
    1081         iMBuff->extraSysCal = 1;
    1082         iMBuff->azimuth   = sc_.sc_cal[iOff + 2];
    1083         iMBuff->elevation = sc_.sc_cal[iOff + 3];
    1084         iMBuff->parAngle  = sc_.sc_cal[iOff + 4];
    1085         iMBuff->focusAxi  = sc_.sc_cal[iOff + 5] * 1e-3;
    1086         iMBuff->focusTan  = sc_.sc_cal[iOff + 6] * 1e-3;
    1087         iMBuff->focusRot  = sc_.sc_cal[iOff + 7];
    1088         iMBuff->temp      = sc_.sc_cal[iOff + 8];
    1089         iMBuff->pressure  = sc_.sc_cal[iOff + 9];
    1090         iMBuff->humidity  = sc_.sc_cal[iOff + 10];
    1091         iMBuff->windSpeed = sc_.sc_cal[iOff + 11];
    1092         iMBuff->windAz    = sc_.sc_cal[iOff + 12];
    1093 
    1094         char *tcalTime = iMBuff->tcalTime;
    1095         sprintf(tcalTime, "%-16.16s", (char *)(&sc_.sc_cal[iOff+13]));
     1400      if (firstIF) {
     1401        if (sc_.sc_ant <= anten_.nant) {
     1402          // No extra syscal information present.
     1403          iMBuff->extraSysCal = 0;
     1404          iMBuff->azimuth   = 0.0f;
     1405          iMBuff->elevation = 0.0f;
     1406          iMBuff->parAngle  = 0.0f;
     1407          iMBuff->focusAxi  = 0.0f;
     1408          iMBuff->focusTan  = 0.0f;
     1409          iMBuff->focusRot  = 0.0f;
     1410          iMBuff->temp      = 0.0f;
     1411          iMBuff->pressure  = 0.0f;
     1412          iMBuff->humidity  = 0.0f;
     1413          iMBuff->windSpeed = 0.0f;
     1414          iMBuff->windAz    = 0.0f;
     1415          strcpy(iMBuff->tcalTime, "                ");
     1416          iMBuff->refBeam = 0;
     1417
     1418        } else {
     1419          // Additional information for Parkes Multibeam data.
     1420          int iOff = scq*(sc_.sc_ant - 1) - 1;
     1421          iMBuff->extraSysCal = 1;
     1422
     1423          iMBuff->azimuth   = sc_.sc_cal[iOff + 2];
     1424          iMBuff->elevation = sc_.sc_cal[iOff + 3];
     1425          iMBuff->parAngle  = sc_.sc_cal[iOff + 4];
     1426
     1427          iMBuff->focusAxi  = sc_.sc_cal[iOff + 5] * 1e-3;
     1428          iMBuff->focusTan  = sc_.sc_cal[iOff + 6] * 1e-3;
     1429          iMBuff->focusRot  = sc_.sc_cal[iOff + 7];
     1430
     1431          iMBuff->temp      = sc_.sc_cal[iOff + 8];
     1432          iMBuff->pressure  = sc_.sc_cal[iOff + 9];
     1433          iMBuff->humidity  = sc_.sc_cal[iOff + 10];
     1434          iMBuff->windSpeed = sc_.sc_cal[iOff + 11];
     1435          iMBuff->windAz    = sc_.sc_cal[iOff + 12];
     1436
     1437          char *tcalTime = iMBuff->tcalTime;
     1438          sprintf(tcalTime, "%-16.16s", (char *)(&sc_.sc_cal[iOff+13]));
     1439          tcalTime[16] = '\0';
    10961440
    10971441#ifndef AIPS_LITTLE_ENDIAN
    1098         // Do byte swapping on the ASCII date string.
    1099         for (int j = 0; j < 16; j += 4) {
    1100           char ctmp;
    1101           ctmp = tcalTime[j];
    1102           tcalTime[j]   = tcalTime[j+3];
    1103           tcalTime[j+3] = ctmp;
    1104           ctmp = tcalTime[j+1];
    1105           tcalTime[j+1] = tcalTime[j+2];
    1106           tcalTime[j+2] = ctmp;
    1107         }
     1442          // Do byte swapping on the ASCII date string.
     1443          for (int j = 0; j < 16; j += 4) {
     1444            char ctmp;
     1445            ctmp = tcalTime[j];
     1446            tcalTime[j]   = tcalTime[j+3];
     1447            tcalTime[j+3] = ctmp;
     1448            ctmp = tcalTime[j+1];
     1449            tcalTime[j+1] = tcalTime[j+2];
     1450            tcalTime[j+2] = ctmp;
     1451          }
    11081452#endif
    11091453
    1110         // Reference beam number.
    1111         float refbeam = sc_.sc_cal[iOff + 17];
    1112         if (refbeam > 0.0f || refbeam < 100.0f) {
    1113           iMBuff->refBeam = int(refbeam);
    1114         } else {
    1115           iMBuff->refBeam = 0;
     1454          // Reference beam number.
     1455          float refbeam = sc_.sc_cal[iOff + 17];
     1456          if (refbeam > 0.0f || refbeam < 100.0f) {
     1457            iMBuff->refBeam = int(refbeam);
     1458          } else {
     1459            iMBuff->refBeam = 0;
     1460          }
    11161461        }
    11171462      }
     
    11281473int MBFITSreader::rpget(int syscalonly, int &EOS)
    11291474{
     1475  const string methodName = "rpget()" ;
     1476  LogIO os( LogOrigin( className, methodName, WHERE ) ) ;
     1477
    11301478  EOS = 0;
    11311479
     
    11351483  int numErr = 0;
    11361484
    1137   jstat = 0;
     1485  int jstat = 0;
    11381486  while (numErr < 10) {
    11391487    int lastjstat = jstat;
    1140     rpfitsin_(&jstat, cVis, weight, &baseline, &ut, &u, &v, &w, &flag, &bin,
    1141               &if_no, &sourceno);
    1142 
    1143     switch(jstat) {
     1488
     1489    switch(rpfitsin(jstat)) {
    11441490    case -1:
    11451491      // Read failed; retry.
    11461492      numErr++;
    1147       fprintf(stderr, "RPFITS read failed - retrying.\n");
     1493      os << LogIO::WARN << "RPFITS read failed - retrying." << LogIO::POST ;
    11481494      jstat = 0;
    11491495      break;
     
    11521498      // Successful read.
    11531499      if (lastjstat == 0) {
    1154         if (baseline == -1) {
     1500        if (cBaseline == -1) {
    11551501          // Syscal data.
    11561502          if (syscalonly) {
     
    12011547    default:
    12021548      // Shouldn't reach here.
    1203       fprintf(stderr, "Unrecognized RPFITSIN return code: %d (retrying)\n",
    1204               jstat);
     1549      sprintf(cMsg, "Unrecognized RPFITSIN return code: %d "
     1550                    "(retrying).", jstat);
     1551      os << LogIO::WARN << cMsg << LogIO::POST ;
    12051552      jstat = 0;
    12061553      break;
     
    12081555  }
    12091556
    1210   fprintf(stderr, "RPFITS read failed too many times.\n");
     1557  os << LogIO::SEVERE << "RPFITS read failed too many times." << LogIO::POST ;
    12111558  return 2;
     1559}
     1560
     1561//----------------------------------------------------- MBFITSreader::rpfitsin
     1562
     1563// Wrapper around RPFITSIN that reports errors.  Returned RPFITSIN subroutine
     1564// arguments are captured as MBFITSreader member variables.
     1565
     1566int MBFITSreader::rpfitsin(int &jstat)
     1567
     1568{
     1569  rpfitsin_(&jstat, cVis, cWgt, &cBaseline, &cUTC, &cU, &cV, &cW, &cFlag,
     1570            &cBin, &cIFno, &cSrcNo);
     1571
     1572  // Handle messages from RPFITSIN.
     1573/**
     1574  if (names_.errmsg[0] != ' ') {
     1575    int i;
     1576    for (i = 80; i > 0; i--) {
     1577      if (names_.errmsg[i-1] != ' ') break;
     1578    }
     1579
     1580    sprintf(cMsg, "WARNING: Cycle %d:%03d, RPFITSIN reported -\n"
     1581                  "         %.*s", cScanNo, cCycleNo, i, names_.errmsg);
     1582    logMsg(cMsg);
     1583  }
     1584**/
     1585  return jstat;
     1586}
     1587
     1588//------------------------------------------------------- MBFITSreader::fixPos
     1589
     1590// Check and, if necessary, repair a position timestamp.
     1591//
     1592// Problems with the position timestamp manifest themselves via the scan rate:
     1593//
     1594//   1) Zero scan rate pairs, 1997/02/28 to 1998/01/07
     1595//
     1596//      These occur because the position timestamp for the first integration
     1597//      of the pair is erroneous; the value recorded is t/1000, where t is the
     1598//      true value.
     1599//        Earliest known: 97-02-28_1725_132653-42_258a.hpf
     1600//          Latest known: 98-01-02_1923_095644-50_165c.hpf
     1601//        (time range chosen to encompass observing runs).
     1602//
     1603//   2) Slow-fast scan rate pairs (0.013 - 0.020 deg/s),
     1604//        1997/03/28 to 1998/01/07.
     1605//
     1606//      The UTC position timestamp is 1.0s later than it should be (never
     1607//      earlier), almost certainly arising from an error in the telescope
     1608//      control system.
     1609//        Earliest known: 97-03-28_0150_010420-74_008d.hpf
     1610//          Latest known: 98-01-04_1502_065150-02_177c.hpf
     1611//        (time range chosen to encompass observing runs).
     1612//
     1613//   3) Slow-fast scan rate pairs (0.015 - 0.018 deg/s),
     1614//        1999/05/20 to 2001/07/12 (HIPASS and ZOA),
     1615//        2001/09/02 to 2001/12/04 (HIPASS and ZOA),
     1616//        2002/03/28 to 2002/05/13 (ZOA only),
     1617//        2003/04/26 to 2003/06/09 (ZOA only).
     1618//        Earliest known: 1999-05-20_1818_175720-50_297e.hpf
     1619//          Latest known: 2001-12-04_1814_065531p14_173e.hpf (HIPASS)
     1620//                        2003-06-09_1924_352-085940_-6c.hpf (ZOA)
     1621//
     1622//      Caused by the Linux signalling NaN problem.  IEEE "signalling" NaNs
     1623//      are silently transformed to "quiet" NaNs during assignment by setting
     1624//      bit 22.  This affected RPFITS because of its use of VAX-format
     1625//      floating-point numbers which, with their permuted bytes, may sometimes
     1626//      appear as signalling NaNs.
     1627//
     1628//      The problem arose when the linux correlator came online and was
     1629//      fixed with a workaround to the RPFITS library (repeated episodes
     1630//      are probably due to use of an older version of the library).  It
     1631//      should not have affected the data significantly because of the
     1632//      low relative error, which ranges from 0.0000038 to 0.0000076, but
     1633//      it is important for the computation of scan rates which requires
     1634//      taking the difference of two large UTC timestamps, one or other
     1635//      of which will have 0.5s added to it.
     1636//
     1637// The return value identifies which, if any, of these problems was repaired.
     1638
     1639int MBFITSreader::fixw(
     1640  const char *datobs,
     1641  int    cycleNo,
     1642  int    beamNo,
     1643  double avRate[2],
     1644  double thisRA,
     1645  double thisDec,
     1646  double thisUTC,
     1647  double nextRA,
     1648  double nextDec,
     1649  float &nextUTC)
     1650{
     1651  if (strcmp(datobs, "2003-06-09") > 0) {
     1652    return 0;
     1653
     1654  } else if (strcmp(datobs, "1998-01-07") <= 0) {
     1655    if (nextUTC < thisUTC && (nextUTC + 86400.0) > (thisUTC + 600.0)) {
     1656      // Possible scaling problem.
     1657      double diff = nextUTC*1000.0 - thisUTC;
     1658      if (0.0 < diff && diff < 600.0) {
     1659        nextUTC *= 1000.0;
     1660        return 1;
     1661      } else {
     1662        // Irreparable.
     1663        return -1;
     1664      }
     1665    }
     1666
     1667    if (cycleNo > 2) {
     1668      if (beamNo == 1) {
     1669        // This test is only reliable for beam 1.
     1670        double dUTC = nextUTC - thisUTC;
     1671        if (dUTC < 0.0) dUTC += 86400.0;
     1672
     1673        // Guard against RA cycling through 24h in either direction.
     1674        if (fabs(nextRA - thisRA) > PI) {
     1675          if (nextRA < thisRA) {
     1676            nextRA += TWOPI;
     1677          } else {
     1678            nextRA -= TWOPI;
     1679          }
     1680        }
     1681
     1682        double  dRA = (nextRA  - thisRA) * cos(nextDec);
     1683        double dDec =  nextDec - thisDec;
     1684        double  arc = sqrt(dRA*dRA + dDec*dDec);
     1685
     1686        double averate = sqrt(avRate[0]*avRate[0] + avRate[1]*avRate[1]);
     1687        double diff1 = fabs(averate - arc/(dUTC-1.0));
     1688        double diff2 = fabs(averate - arc/dUTC);
     1689        if ((diff1 < diff2) && (diff1 < 0.05*averate)) {
     1690          nextUTC -= 1.0;
     1691          cCode5 = cycleNo;
     1692          return 2;
     1693        } else {
     1694          cCode5 = 0;
     1695        }
     1696
     1697      } else {
     1698        if (cycleNo == cCode5) {
     1699          nextUTC -= 1.0;
     1700          return 2;
     1701        }
     1702      }
     1703    }
     1704
     1705  } else if ((strcmp(datobs, "1999-05-20") >= 0 &&
     1706              strcmp(datobs, "2001-07-12") <= 0) ||
     1707             (strcmp(datobs, "2001-09-02") >= 0 &&
     1708              strcmp(datobs, "2001-12-04") <= 0) ||
     1709             (strcmp(datobs, "2002-03-28") >= 0 &&
     1710              strcmp(datobs, "2002-05-13") <= 0) ||
     1711             (strcmp(datobs, "2003-04-26") >= 0 &&
     1712              strcmp(datobs, "2003-06-09") <= 0)) {
     1713    // Signalling NaN problem, e.g. 1999-07-26_1839_011106-74_009c.hpf.
     1714    // Position timestamps should always be an integral number of seconds.
     1715    double resid = nextUTC - int(nextUTC);
     1716    if (resid == 0.5) {
     1717      nextUTC -= 0.5;
     1718      return 3;
     1719    }
     1720  }
     1721
     1722  return 0;
    12121723}
    12131724
     
    12191730{
    12201731  if (cMBopen) {
    1221     jstat = 1;
    1222     rpfitsin_(&jstat, cVis, weight, &baseline, &ut, &u, &v, &w, &flag, &bin,
    1223               &if_no, &sourceno);
     1732    int jstat = 1;
     1733    rpfitsin_(&jstat, cVis, cWgt, &cBaseline, &cUTC, &cU, &cV, &cW, &cFlag,
     1734              &cBin, &cIFno, &cSrcNo);
    12241735
    12251736    if (cBeams)     delete [] cBeams;
     
    12321743    if (cRefChan)   delete [] cRefChan;
    12331744
    1234     if (cVis)       delete [] cVis;
     1745    if (cVis) delete [] cVis;
     1746    if (cWgt) delete [] cWgt;
    12351747
    12361748    if (cBeamSel)   delete [] cBeamSel;
     
    12441756  }
    12451757}
     1758
     1759//-------------------------------------------------------------------- utcDiff
     1760
     1761// Subtract two UTCs (s) allowing for any plausible number of cycles through
     1762// 86400s, returning a result in the range [-43200, +43200]s.
     1763
     1764double MBFITSreader::utcDiff(double utc1, double utc2)
     1765{
     1766  double diff = utc1 - utc2;
     1767
     1768  if (diff > 43200.0) {
     1769    diff -= 86400.0;
     1770    while (diff > 43200.0) diff -= 86400.0;
     1771  } else if (diff < -43200.0) {
     1772    diff += 86400.0;
     1773    while (diff < -43200.0) diff += 86400.0;
     1774  }
     1775
     1776  return diff;
     1777}
     1778
     1779//------------------------------------------------------- scanRate & applyRate
     1780
     1781// Compute and apply the scan rate corrected for grid convergence.  (ra0,dec0)
     1782// are the coordinates of the central beam, assumed to be the tracking centre.
     1783// The rate computed in RA will be a rate of change of angular distance in the
     1784// direction of increasing RA at the position of the central beam.  Similarly
     1785// for declination.  Angles in radian, time in s.
     1786
     1787void MBFITSreader::scanRate(
     1788  double ra0,
     1789  double dec0,
     1790  double ra1,
     1791  double dec1,
     1792  double ra2,
     1793  double dec2,
     1794  double dt,
     1795  double &raRate,
     1796  double &decRate)
     1797{
     1798  // Transform to a system where the central beam lies on the equator at 12h.
     1799  eulerx(ra1, dec1, ra0+HALFPI, -dec0, -HALFPI, ra1, dec1);
     1800  eulerx(ra2, dec2, ra0+HALFPI, -dec0, -HALFPI, ra2, dec2);
     1801
     1802  raRate  = (ra2  - ra1)  / dt;
     1803  decRate = (dec2 - dec1) / dt;
     1804}
     1805
     1806
     1807void MBFITSreader::applyRate(
     1808  double ra0,
     1809  double dec0,
     1810  double ra1,
     1811  double dec1,
     1812  double raRate,
     1813  double decRate,
     1814  double dt,
     1815  double &ra2,
     1816  double &dec2)
     1817{
     1818  // Transform to a system where the central beam lies on the equator at 12h.
     1819  eulerx(ra1, dec1, ra0+HALFPI, -dec0, -HALFPI, ra1, dec1);
     1820
     1821  ra2  = ra1  + (raRate  * dt);
     1822  dec2 = dec1 + (decRate * dt);
     1823
     1824  // Transform back.
     1825  eulerx(ra2, dec2, -HALFPI, dec0, ra0+HALFPI, ra2, dec2);
     1826}
     1827
     1828//--------------------------------------------------------------------- eulerx
     1829
     1830void MBFITSreader::eulerx(
     1831  double lng0,
     1832  double lat0,
     1833  double phi0,
     1834  double theta,
     1835  double phi,
     1836  double &lng1,
     1837  double &lat1)
     1838
     1839// Applies the Euler angle based transformation of spherical coordinates.
     1840//
     1841//     phi0  Longitude of the ascending node in the old system, radians.  The
     1842//           ascending node is the point of intersection of the equators of
     1843//           the two systems such that the equator of the new system crosses
     1844//           from south to north as viewed in the old system.
     1845//
     1846//    theta  Angle between the poles of the two systems, radians.  THETA is
     1847//           positive for a positive rotation about the ascending node.
     1848//
     1849//      phi  Longitude of the ascending node in the new system, radians.
     1850
     1851{
     1852  // Compute intermediaries.
     1853  double lng0p  = lng0 - phi0;
     1854  double slng0p = sin(lng0p);
     1855  double clng0p = cos(lng0p);
     1856  double slat0  = sin(lat0);
     1857  double clat0  = cos(lat0);
     1858  double ctheta = cos(theta);
     1859  double stheta = sin(theta);
     1860
     1861  double x = clat0*clng0p;
     1862  double y = clat0*slng0p*ctheta + slat0*stheta;
     1863
     1864  // Longitude in the new system.
     1865  if (x != 0.0 || y != 0.0) {
     1866    lng1 = phi + atan2(y, x);
     1867  } else {
     1868    // Longitude at the poles in the new system is consistent with that
     1869    // specified in the old system.
     1870    lng1 = phi + lng0p;
     1871  }
     1872  lng1 = fmod(lng1, TWOPI);
     1873  if (lng1 < 0.0) lng1 += TWOPI;
     1874
     1875  lat1 = asin(slat0*ctheta - clat0*stheta*slng0p);
     1876}
  • branches/alma/external/atnf/PKSIO/MBFITSreader.h

    r1453 r1757  
    22//# MBFITSreader.h: ATNF single-dish RPFITS reader.
    33//#---------------------------------------------------------------------------
    4 //# Copyright (C) 2000-2006
    5 //# Mark Calabretta, ATNF
     4//# livedata - processing pipeline for single-dish, multibeam spectral data.
     5//# Copyright (C) 2000-2009, Australia Telescope National Facility, CSIRO
    66//#
    7 //# This library is free software; you can redistribute it and/or modify it
    8 //# under the terms of the GNU Library General Public License as published by
    9 //# the Free Software Foundation; either version 2 of the License, or (at your
    10 //# option) any later version.
     7//# This file is part of livedata.
    118//#
    12 //# This library is distributed in the hope that it will be useful, but WITHOUT
     9//# livedata is free software: you can redistribute it and/or modify it under
     10//# the terms of the GNU General Public License as published by the Free
     11//# Software Foundation, either version 3 of the License, or (at your option)
     12//# any later version.
     13//#
     14//# livedata is distributed in the hope that it will be useful, but WITHOUT
    1315//# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    14 //# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Library General Public
    15 //# License for more details.
     16//# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
     17//# more details.
    1618//#
    17 //# You should have received a copy of the GNU Library General Public License
    18 //# along with this library; if not, write to the Free Software Foundation,
    19 //# Inc., 675 Massachusetts Ave, Cambridge, MA 02139, USA.
     19//# You should have received a copy of the GNU General Public License along
     20//# with livedata.  If not, see <http://www.gnu.org/licenses/>.
    2021//#
    21 //# Correspondence concerning this software should be addressed as follows:
    22 //#        Internet email: mcalabre@atnf.csiro.au.
    23 //#        Postal address: Dr. Mark Calabretta,
    24 //#                        Australia Telescope National Facility,
    25 //#                        P.O. Box 76,
    26 //#                        Epping, NSW, 2121,
     22//# Correspondence concerning livedata may be directed to:
     23//#        Internet email: mcalabre@atnf.csiro.au
     24//#        Postal address: Dr. Mark Calabretta
     25//#                        Australia Telescope National Facility, CSIRO
     26//#                        PO Box 76
     27//#                        Epping NSW 1710
    2728//#                        AUSTRALIA
    2829//#
    29 //# $Id$
     30//# http://www.atnf.csiro.au/computing/software/livedata.html
     31//# $Id: MBFITSreader.h,v 19.23 2009-09-29 07:33:38 cal103 Exp $
    3032//#---------------------------------------------------------------------------
    3133//# The MBFITSreader class reads single dish RPFITS files (such as Parkes
     
    3941
    4042#include <atnf/PKSIO/FITSreader.h>
    41 #include <atnf/PKSIO/PKSMBrecord.h>
     43#include <atnf/PKSIO/MBrecord.h>
     44
     45using namespace std;
    4246
    4347// <summary>
     
    7882        double antPos[3],
    7983        char   obsType[32],
     84        char   bunit[32],
    8085        float  &equinox,
    8186        char   radecsys[32],
     
    101106
    102107    // Read the next data record.
    103     virtual int read(PKSMBrecord &record);
     108    virtual int read(MBrecord &record);
    104109
    105110    // Close the RPFITS file.
     
    107112
    108113  private:
    109     char   cDateObs[10];
     114    // RPFITSIN subroutine arguments.
     115    int   cBaseline, cFlag, cBin, cIFno, cSrcNo;
     116    float cUTC, cU, cV, cW, *cVis, *cWgt;
     117
     118    char   cDateObs[12];
    110119    int    *cBeamSel, *cChanOff, cFirst, *cIFSel, cInterp, cIntTime, cMBopen,
    111            cMopra, cNBeamSel, cNBin, cRetry, *cStaleness, cTid, *cXpolOff;
    112     float  *cVis;
     120           cMopra, cNBeamSel, cNBin, cRetry, cSimulIF, cSUpos, *cXpolOff;
    113121
    114122    // The data has to be bufferred to allow positions to be interpolated.
    115123    int    cEOF, cEOS, cFlushBin, cFlushIF, cFlushing;
    116124    double *cPosUTC;
    117     PKSMBrecord *cBuffer;
     125    MBrecord *cBuffer;
    118126
     127    // Scan and cycle number bookkeeping.
    119128    int    cCycleNo, cScanNo;
    120     double cUTC;
     129    double cPrevUTC;
    121130
    122131    // Read the next data record from the RPFITS file.
    123132    int rpget(int syscalonly, int &EOS);
    124     // These are no longer define in the RPFITS.h file so moved here
    125     int jstat;
    126     float *weight;
    127     int baseline;
    128     int flag;
    129     int bin;
    130     int if_no;
    131     int sourceno;
    132     float *vis;
    133     float u;
    134     float v;
    135     float w;
    136     float ut;
    137            
     133    int rpfitsin(int &jstat);
     134
     135    // Check and, if necessary, repair a position timestamp.
     136    int    cCode5, cNRate;
     137    double cAvRate[2];
     138    int fixw(const char *datobs, int cycleNo, int beamNo, double avRate[2],
     139             double thisRA, double thisDec, double thisUTC,
     140             double nextRA, double nextDec, float &nextUTC);
     141
     142    // Subtract two UTCs (s).
     143    double utcDiff(double utc1, double utc2);
     144
     145    // Compute and apply the scan rate corrected for grid convergence.
     146    double cRA0, cDec0;
     147    void  scanRate(double ra0, double dec0,
     148                   double ra1, double dec1,
     149                   double ra2, double dec2, double dt,
     150                   double &raRate, double &decRate);
     151    void applyRate(double ra0, double dec0,
     152                   double ra1, double dec1,
     153                   double raRate, double decRate, double dt,
     154                   double &ra2, double &dec2);
     155    void eulerx(double lng0, double lat0, double phi0, double theta,
     156                double phi, double &lng1, double &lat1);
    138157};
    139158
  • branches/alma/external/atnf/PKSIO/MBrecord.cc

    r1752 r1757  
    322322  refBeam = other.refBeam;
    323323
     324  polNo = other.polNo ;
     325  srcVelocity = other.srcVelocity ;
     326
    324327  return *this;
    325328}
     
    436439  refBeam = other.refBeam;
    437440
     441  polNo = other.polNo ;
     442  srcVelocity = other.srcVelocity ;
     443
    438444  return 0;
    439445}
  • branches/alma/external/atnf/PKSIO/MBrecord.h

    r1752 r1757  
    166166    short  refBeam;             // Reference beam, in beam-switching (MX)
    167167                                // mode (added 1999/03/17).
     168    int polNo ;                 // polarization ID
     169    float srcVelocity ;         // source velocity w.r.t. reference frame
    168170
    169171  private:
  • branches/alma/external/atnf/PKSIO/PKSFITSreader.cc

    r1453 r1757  
    22//# PKSFITSreader.cc: Class to read Parkes multibeam data from a FITS file.
    33//#---------------------------------------------------------------------------
    4 //# Copyright (C) 2000-2006
    5 //# Associated Universities, Inc. Washington DC, USA.
     4//# livedata - processing pipeline for single-dish, multibeam spectral data.
     5//# Copyright (C) 2000-2009, Australia Telescope National Facility, CSIRO
    66//#
    7 //# This library is free software; you can redistribute it and/or modify it
    8 //# under the terms of the GNU Library General Public License as published by
    9 //# the Free Software Foundation; either version 2 of the License, or (at your
    10 //# option) any later version.
     7//# This file is part of livedata.
    118//#
    12 //# This library is distributed in the hope that it will be useful, but
    13 //# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
    14 //# or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Library General Public
    15 //# License for more details.
     9//# livedata is free software: you can redistribute it and/or modify it under
     10//# the terms of the GNU General Public License as published by the Free
     11//# Software Foundation, either version 3 of the License, or (at your option)
     12//# any later version.
    1613//#
    17 //# You should have received a copy of the GNU Library General Public License
    18 //# along with this library; if not, write to the Free Software Foundation,
    19 //# Inc., 675 Massachusetts Ave, Cambridge, MA 02139, USA.
     14//# livedata is distributed in the hope that it will be useful, but WITHOUT
     15//# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
     16//# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
     17//# more details.
    2018//#
    21 //# Correspondence concerning AIPS++ should be addressed as follows:
    22 //#        Internet email: aips2-request@nrao.edu.
    23 //#        Postal address: AIPS++ Project Office
    24 //#                        National Radio Astronomy Observatory
    25 //#                        520 Edgemont Road
    26 //#                        Charlottesville, VA 22903-2475 USA
     19//# You should have received a copy of the GNU General Public License along
     20//# with livedata.  If not, see <http://www.gnu.org/licenses/>.
    2721//#
    28 //# $Id$
     22//# Correspondence concerning livedata may be directed to:
     23//#        Internet email: mcalabre@atnf.csiro.au
     24//#        Postal address: Dr. Mark Calabretta
     25//#                        Australia Telescope National Facility, CSIRO
     26//#                        PO Box 76
     27//#                        Epping NSW 1710
     28//#                        AUSTRALIA
     29//#
     30//# http://www.atnf.csiro.au/computing/software/livedata.html
     31//# $Id: PKSFITSreader.cc,v 19.23 2009-09-29 07:33:38 cal103 Exp $
    2932//#---------------------------------------------------------------------------
    3033//# Original: 2000/08/02, Mark Calabretta, ATNF
     
    3437#include <atnf/PKSIO/SDFITSreader.h>
    3538#include <atnf/PKSIO/PKSFITSreader.h>
    36 #include <atnf/PKSIO/PKSMBrecord.h>
    37 
     39#include <atnf/PKSIO/PKSrecord.h>
     40
     41#include <casa/stdio.h>
    3842#include <casa/Arrays/Array.h>
    3943#include <casa/BasicMath/Math.h>
    4044#include <casa/Quanta/MVTime.h>
    41 
    42 #include <casa/stdio.h>
     45#include <casa/Logging/LogIO.h>
    4346
    4447//----------------------------------------------- PKSFITSreader::PKSFITSreader
     
    7679Int PKSFITSreader::open(
    7780        const String fitsName,
     81        const String antenna,
    7882        Vector<Bool> &beams,
    7983        Vector<Bool> &IFs,
     
    8690  int    extraSysCal, haveBase_, *haveXPol_, haveSpectra_, nBeam, *nChan_,
    8791         nIF, *nPol_, status;
    88   if ((status = cReader->open((char *)fitsName.chars(), nBeam, cBeams, nIF,
    89                               cIFs, nChan_, nPol_, haveXPol_, haveBase_,
    90                               haveSpectra_, extraSysCal))) {
     92  status = cReader->open((char *)fitsName.chars(), nBeam, cBeams, nIF, cIFs,
     93                         nChan_, nPol_, haveXPol_, haveBase_, haveSpectra_,
     94                         extraSysCal);
     95  //logMsg(cReader->getMsg());
     96  //cReader->clearMsg();
     97  if (status) {
    9198    return status;
    9299  }
     
    138145        Vector<Double> &antPosition,
    139146        String &obsType,
     147        String &bunit,
    140148        Float  &equinox,
    141149        String &dopplerFrame,
    142150        Double &mjd,
    143151        Double &refFreq,
    144         Double &bandwidth,
    145         String &fluxunit)
    146 {
    147   char   datobs[32], dopplerFrame_[32], observer_[32], obsType_[32],
    148          project_[32], radecsys[32], telescope[32];
     152        Double &bandwidth)
     153{
     154  char   bunit_[32], datobs[32], dopplerFrame_[32], observer_[32],
     155         obsType_[32], project_[32], radecsys[32], telescope[32];
     156  int    status;
    149157  float  equinox_;
    150158  double antPos[3], utc;
    151159
    152   if (cReader->getHeader(observer_, project_, telescope, antPos, obsType_,
    153                          equinox_, radecsys, dopplerFrame_, datobs, utc,
    154                          refFreq, bandwidth)) {
     160  status = cReader->getHeader(observer_, project_, telescope, antPos,
     161                              obsType_, bunit_, equinox_, radecsys,
     162                              dopplerFrame_, datobs, utc, refFreq, bandwidth);
     163  //logMsg(cReader->getMsg());
     164  //cReader->clearMsg();
     165  if (status) {
    155166    return 1;
    156167  }
    157168
    158   fluxunit = "";
    159169  observer = trim(observer_);
    160170  project  = trim(project_);
     
    165175  antPosition(2) = antPos[2];
    166176  obsType = trim(obsType_);
     177  bunit   = trim(bunit_);
    167178  equinox = equinox_;
    168179  dopplerFrame = trim(dopplerFrame_);
     
    188199  double *startfreq, *endfreq;
    189200
    190   Int status;
    191   if (!(status = cReader->getFreqInfo(nIF, startfreq, endfreq))) {
     201  Int status = cReader->getFreqInfo(nIF, startfreq, endfreq);
     202
     203  //logMsg(cReader->getMsg());
     204  //cReader->clearMsg();
     205  if (!status) {
    192206    startFreq.takeStorage(IPosition(1,nIF), startfreq, TAKE_OVER);
    193207    endFreq.takeStorage(IPosition(1,nIF), endfreq, TAKE_OVER);
     
    209223        const Bool getSpectra,
    210224        const Bool getXPol,
    211         const Bool getFeedPos)
     225        const Bool getFeedPos,
     226        const Bool getPointing,
     227        const Int  coordSys)
    212228{
    213229  // Apply beam selection.
     
    277293  cGetXPol    = getXPol;
    278294  cGetFeedPos = getFeedPos;
     295  cGetPointing = getPointing;
     296  cCoordSys   = coordSys;
    279297
    280298  uInt maxNChan = cReader->select(start, end, ref, cGetSpectra, cGetXPol,
    281                                   cGetFeedPos);
     299                                  cGetFeedPos, cGetPointing, cCoordSys);
     300  //logMsg(cReader->getMsg());
     301  //cReader->clearMsg();
    282302
    283303  delete [] end;
     
    302322  double* posns;
    303323
    304   Int status;
    305   if (!(status = cReader->findRange(nRow, nSel, dateSpan, utcSpan, posns))) {
     324  Int status = cReader->findRange(nRow, nSel, dateSpan, utcSpan, posns);
     325  //logMsg(cReader->getMsg());
     326  //cReader->clearMsg();
     327
     328  if (!status) {
    306329    timeSpan.resize(2);
    307330
     
    322345// Read the next data record.
    323346
    324 Int PKSFITSreader::read(
    325         Int             &scanNo,
    326         Int             &cycleNo,
    327         Double          &mjd,
    328         Double          &interval,
    329         String          &fieldName,
    330         String          &srcName,
    331         Vector<Double>  &srcDir,
    332         Vector<Double>  &srcPM,
    333         Double          &srcVel,
    334         String          &obsType,
    335         Int             &IFno,
    336         Double          &refFreq,
    337         Double          &bandwidth,
    338         Double          &freqInc,
    339         Vector<Double>  &restFreq,
    340         Vector<Float>   &tcal,
    341         String          &tcalTime,
    342         Float           &azimuth,
    343         Float           &elevation,
    344         Float           &parAngle,
    345         Float           &focusAxi,
    346         Float           &focusTan,
    347         Float           &focusRot,
    348         Float           &temperature,
    349         Float           &pressure,
    350         Float           &humidity,
    351         Float           &windSpeed,
    352         Float           &windAz,
    353         Int             &refBeam,
    354         Int             &beamNo,
    355         Vector<Double>  &direction,
    356         Vector<Double>  &scanRate,
    357         Vector<Float>   &tsys,
    358         Vector<Float>   &sigma,
    359         Vector<Float>   &calFctr,
    360         Matrix<Float>   &baseLin,
    361         Matrix<Float>   &baseSub,
    362         Matrix<Float>   &spectra,
    363         Matrix<uChar>   &flagged,
    364         Complex         &xCalFctr,
    365         Vector<Complex> &xPol)
    366 {
    367   Int status;
    368 
    369   if ((status = cReader->read(cMBrec))) {
     347Int PKSFITSreader::read(PKSrecord &pksrec)
     348{
     349  Int status = cReader->read(cMBrec);
     350  //logMsg(cReader->getMsg());
     351  //cReader->clearMsg();
     352
     353  if (status) {
    370354    if (status != -1) {
    371355      status = 1;
     
    379363  uInt nPol  = cMBrec.nPol[0];
    380364
    381   scanNo  = cMBrec.scanNo;
    382   cycleNo = cMBrec.cycleNo;
     365  pksrec.scanNo  = cMBrec.scanNo;
     366  pksrec.cycleNo = cMBrec.cycleNo;
     367  pksrec.polNo = cMBrec.polNo ;
    383368
    384369  // Extract MJD.
    385370  Int day, month, year;
    386   sscanf(cMBrec.datobs, "%4d-%2d-%2d", &year, &month, &day);
    387   mjd = MVTime(year, month, Double(day)).day() + cMBrec.utc/86400.0;
    388 
    389   interval  = cMBrec.exposure;
    390 
    391   fieldName = trim(cMBrec.srcName);
    392   srcName   = fieldName;
    393   srcDir(0) = cMBrec.srcRA;
    394   srcDir(1) = cMBrec.srcDec;
    395   srcPM(0)  = 0.0;
    396   srcPM(1)  = 0.0;
    397   srcVel    = 0.0;
    398   obsType   = trim(cMBrec.obsType);
    399 
    400   IFno = cMBrec.IFno[0];
     371  if ( strstr( cMBrec.datobs, "T" ) == NULL ) {
     372    sscanf(cMBrec.datobs, "%4d-%2d-%2d", &year, &month, &day);
     373    pksrec.mjd = MVTime(year, month, Double(day)).day() + cMBrec.utc/86400.0;
     374  }
     375  else {
     376    Double dd, hour, min, sec ;
     377    sscanf( cMBrec.datobs, "%4d-%2d-%2lfT%lf:%lf:%lf", &year, &month, &dd, &hour, &min, &sec ) ;
     378    dd = dd + ( hour * 3600.0 + min * 60.0 + sec ) / 86400.0 ;
     379    pksrec.mjd = MVTime(year, month, dd).day() ;
     380  }
     381
     382  pksrec.interval  = cMBrec.exposure;
     383
     384  pksrec.fieldName = trim(cMBrec.srcName);
     385  pksrec.srcName   = pksrec.fieldName;
     386
     387  int namelen = pksrec.srcName.length() ;
     388  if ( namelen > 4 ) {
     389    String srcsub = pksrec.srcName.substr( namelen-4, 4 ) ;
     390    if ( srcsub.find( "_psc" ) != string::npos ) {
     391      pksrec.fieldName = pksrec.srcName.substr( 0, namelen-4 ) ;
     392      pksrec.srcName = pksrec.fieldName + "_ps_calon" ;
     393    }
     394    else if ( srcsub.find( "_pso" ) != string::npos ) {
     395      pksrec.fieldName = pksrec.srcName.substr( 0, namelen-4 ) ;
     396      pksrec.srcName = pksrec.fieldName + "_ps" ;
     397    }
     398    else if ( srcsub.find( "_prc" ) != string::npos ) {
     399      pksrec.fieldName = pksrec.srcName.substr( 0, namelen-4 ) ;
     400      pksrec.srcName = pksrec.fieldName + "_psr_calon" ;
     401    }
     402    else if ( srcsub.find( "_pro" ) != string::npos ) {
     403      pksrec.fieldName = pksrec.srcName.substr( 0, namelen-4 ) ;
     404      pksrec.srcName = pksrec.fieldName + "_psr" ;
     405    }
     406    else if ( srcsub.find( "_fsc" ) != string::npos ) {
     407      pksrec.fieldName = pksrec.srcName.substr( 0, namelen-4 ) ;
     408      pksrec.srcName = pksrec.fieldName + "_fs_calon" ;
     409    }
     410    else if ( srcsub.find( "_fso" ) != string::npos ) {
     411      pksrec.fieldName = pksrec.srcName.substr( 0, namelen-4 ) ;
     412      pksrec.srcName = pksrec.fieldName + "_fs" ;
     413    }
     414    else if ( srcsub.find( "_frc" ) != string::npos ) {
     415      pksrec.fieldName = pksrec.srcName.substr( 0, namelen-4 ) ;
     416      pksrec.srcName = pksrec.fieldName + "_fsr_calon" ;
     417    }
     418    else if ( srcsub.find( "_fro" ) != string::npos ) {
     419      pksrec.fieldName = pksrec.srcName.substr( 0, namelen-4 ) ;
     420      pksrec.srcName = pksrec.fieldName + "_fsr" ;
     421    }
     422    else if ( srcsub.find( "_nsc" ) != string::npos || srcsub.find( "_nrc" ) != string::npos ) {
     423      pksrec.fieldName = pksrec.srcName.substr( 0, namelen-4 ) ;
     424      pksrec.srcName = pksrec.fieldName + "_nod_calon" ;
     425    }
     426    else if ( srcsub.find( "_nso" ) != string::npos || srcsub.find( "_nro" ) != string::npos ) {
     427      pksrec.fieldName = pksrec.srcName.substr( 0, namelen-4 ) ;
     428      pksrec.srcName = pksrec.fieldName + "_nod" ;
     429    }
     430  }
     431
     432  pksrec.srcDir.resize(2);
     433  pksrec.srcDir(0) = cMBrec.srcRA;
     434  pksrec.srcDir(1) = cMBrec.srcDec;
     435
     436  pksrec.srcPM.resize(2);
     437  pksrec.srcPM(0)  = 0.0;
     438  pksrec.srcPM(1)  = 0.0;
     439  pksrec.srcVel    = cMBrec.srcVelocity;
     440  pksrec.obsType   = trim(cMBrec.obsType);
     441
     442  pksrec.IFno = cMBrec.IFno[0];
    401443  Double chanWidth = fabs(cMBrec.fqDelt[0]);
    402   refFreq   = cMBrec.fqRefVal[0];
    403   bandwidth = chanWidth * nChan;
    404   freqInc   = cMBrec.fqDelt[0];
    405   //restFreq  = cMBrec.restFreq;
    406   restFreq.resize(1);
    407   restFreq(0)  = cMBrec.restFreq;
    408 
    409   tcal.resize(nPol);
     444  pksrec.refFreq   = cMBrec.fqRefVal[0];
     445  pksrec.bandwidth = chanWidth * nChan;
     446  pksrec.freqInc   = cMBrec.fqDelt[0];
     447  pksrec.restFreq.resize(1) ;
     448  pksrec.restFreq(0)  = cMBrec.restFreq;
     449
     450  pksrec.tcal.resize(nPol);
    410451  for (uInt ipol = 0; ipol < nPol; ipol++) {
    411     tcal(ipol) = cMBrec.tcal[0][ipol];
    412   }
    413   tcalTime  = trim(cMBrec.tcalTime);
    414   azimuth   = cMBrec.azimuth;
    415   elevation = cMBrec.elevation;
    416   parAngle  = cMBrec.parAngle;
    417   focusAxi  = cMBrec.focusAxi;
    418   focusTan  = cMBrec.focusTan;
    419   focusRot  = cMBrec.focusRot;
    420 
    421   temperature = cMBrec.temp;
    422   pressure    = cMBrec.pressure;
    423   humidity    = cMBrec.humidity;
    424   windSpeed   = cMBrec.windSpeed;
    425   windAz      = cMBrec.windAz;
    426 
    427   refBeam = cMBrec.refBeam;
    428   beamNo  = cMBrec.beamNo;
    429 
    430   direction(0) = cMBrec.ra;
    431   direction(1) = cMBrec.dec;
    432   scanRate(0)  = cMBrec.raRate;
    433   scanRate(1)  = cMBrec.decRate;
    434 
    435   tsys.resize(nPol);
    436   sigma.resize(nPol);
    437   calFctr.resize(nPol);
     452    pksrec.tcal(ipol) = cMBrec.tcal[0][ipol];
     453  }
     454  pksrec.tcalTime  = trim(cMBrec.tcalTime);
     455  pksrec.azimuth   = cMBrec.azimuth;
     456  pksrec.elevation = cMBrec.elevation;
     457  pksrec.parAngle  = cMBrec.parAngle;
     458
     459  pksrec.focusAxi  = cMBrec.focusAxi;
     460  pksrec.focusTan  = cMBrec.focusTan;
     461  pksrec.focusRot  = cMBrec.focusRot;
     462
     463  pksrec.temperature = cMBrec.temp;
     464  pksrec.pressure    = cMBrec.pressure;
     465  pksrec.humidity    = cMBrec.humidity;
     466  pksrec.windSpeed   = cMBrec.windSpeed;
     467  pksrec.windAz      = cMBrec.windAz;
     468
     469  pksrec.refBeam = cMBrec.refBeam;
     470  pksrec.beamNo  = cMBrec.beamNo;
     471
     472  pksrec.direction.resize(2);
     473  pksrec.direction(0) = cMBrec.ra;
     474  pksrec.direction(1) = cMBrec.dec;
     475  pksrec.pCode        = cMBrec.pCode;
     476  pksrec.rateAge      = cMBrec.rateAge;
     477  pksrec.scanRate.resize(2);
     478  pksrec.scanRate(0)  = cMBrec.raRate;
     479  pksrec.scanRate(1)  = cMBrec.decRate;
     480  pksrec.paRate       = cMBrec.paRate;
     481
     482  pksrec.tsys.resize(nPol);
     483  pksrec.sigma.resize(nPol);
     484  pksrec.calFctr.resize(nPol);
    438485  for (uInt ipol = 0; ipol < nPol; ipol++) {
    439     tsys(ipol)  = cMBrec.tsys[0][ipol];
    440     sigma(ipol) = tsys(ipol) / 0.81 / sqrt(interval * chanWidth);
    441     calFctr(ipol) = cMBrec.calfctr[0][ipol];
     486    pksrec.tsys(ipol)  = cMBrec.tsys[0][ipol];
     487    pksrec.sigma(ipol) = (pksrec.tsys(ipol) / 0.81) /
     488                            sqrt(pksrec.interval * chanWidth);
     489    pksrec.calFctr(ipol) = cMBrec.calfctr[0][ipol];
    442490  }
    443491
    444492  if (cMBrec.haveBase) {
    445     baseLin.resize(2,nPol);
    446     baseSub.resize(9,nPol);
     493    pksrec.baseLin.resize(2,nPol);
     494    pksrec.baseSub.resize(24,nPol);
    447495
    448496    for (uInt ipol = 0; ipol < nPol; ipol++) {
    449       baseLin(0,ipol) = cMBrec.baseLin[0][ipol][0];
    450       baseLin(1,ipol) = cMBrec.baseLin[0][ipol][1];
    451 
    452       for (uInt j = 0; j < 9; j++) {
    453         baseSub(j,ipol) = cMBrec.baseSub[0][ipol][j];
     497      pksrec.baseLin(0,ipol) = cMBrec.baseLin[0][ipol][0];
     498      pksrec.baseLin(1,ipol) = cMBrec.baseLin[0][ipol][1];
     499
     500      for (uInt j = 0; j < 24; j++) {
     501        pksrec.baseSub(j,ipol) = cMBrec.baseSub[0][ipol][j];
    454502      }
    455503    }
    456504
    457505  } else {
    458     baseLin.resize(0,0);
    459     baseSub.resize(0,0);
     506    pksrec.baseLin.resize(0,0);
     507    pksrec.baseSub.resize(0,0);
    460508  }
    461509
    462510  if (cGetSpectra && cMBrec.haveSpectra) {
    463     spectra.resize(nChan,nPol);
    464     spectra.takeStorage(IPosition(2,nChan,nPol), cMBrec.spectra[0], SHARE);
    465 
    466     flagged.resize(nChan,nPol);
    467     flagged.takeStorage(IPosition(2,nChan,nPol), cMBrec.flagged[0], SHARE);
     511    pksrec.spectra.resize(nChan,nPol);
     512    pksrec.spectra.takeStorage(IPosition(2,nChan,nPol), cMBrec.spectra[0],
     513      SHARE);
     514
     515    pksrec.flagged.resize(nChan,nPol);
     516    pksrec.flagged.takeStorage(IPosition(2,nChan,nPol), cMBrec.flagged[0],
     517      SHARE);
    468518
    469519  } else {
    470     spectra.resize(0,0);
    471     flagged.resize(0,0);
     520    pksrec.spectra.resize(0,0);
     521    pksrec.flagged.resize(0,0);
    472522  }
    473523
    474524  if (cGetXPol) {
    475     xCalFctr = Complex(cMBrec.xcalfctr[0][0], cMBrec.xcalfctr[0][1]);
    476     xPol.resize(nChan);
    477     xPol.takeStorage(IPosition(1,nChan), (Complex *)cMBrec.xpol[0], SHARE);
     525    pksrec.xCalFctr = Complex(cMBrec.xcalfctr[0][0],
     526                             cMBrec.xcalfctr[0][1]);
     527    pksrec.xPol.resize(nChan);
     528    pksrec.xPol.takeStorage(IPosition(1,nChan), (Complex *)cMBrec.xpol[0],
     529      SHARE);
    478530  }
    479531
     
    481533}
    482534
    483 //-------------------------------------------------------- PKSFITSreader::read
    484 
    485 // Read the next data record, just the basics.
    486 
    487 Int PKSFITSreader::read(
    488         Int           &IFno,
    489         Vector<Float> &tsys,
    490         Vector<Float> &calFctr,
    491         Matrix<Float> &baseLin,
    492         Matrix<Float> &baseSub,
    493         Matrix<Float> &spectra,
    494         Matrix<uChar> &flagged)
    495 {
    496   Int status;
    497 
    498   if ((status = cReader->read(cMBrec))) {
    499     if (status != -1) {
    500       status = 1;
    501     }
    502 
    503     return status;
    504   }
    505 
    506   IFno = cMBrec.IFno[0];
    507 
    508   uInt nChan = cMBrec.nChan[0];
    509   uInt nPol  = cMBrec.nPol[0];
    510 
    511   tsys.resize(nPol);
    512   calFctr.resize(nPol);
    513   for (uInt ipol = 0; ipol < nPol; ipol++) {
    514     tsys(ipol) = cMBrec.tsys[0][ipol];
    515     calFctr(ipol) = cMBrec.calfctr[0][ipol];
    516   }
    517 
    518   if (cMBrec.haveBase) {
    519     baseLin.resize(2,nPol);
    520     baseSub.resize(9,nPol);
    521 
    522     for (uInt ipol = 0; ipol < nPol; ipol++) {
    523       baseLin(0,ipol) = cMBrec.baseLin[0][ipol][0];
    524       baseLin(1,ipol) = cMBrec.baseLin[0][ipol][1];
    525 
    526       for (uInt j = 0; j < 9; j++) {
    527         baseSub(j,ipol) = cMBrec.baseSub[0][ipol][j];
    528       }
    529     }
    530 
    531   } else {
    532     baseLin.resize(0,0);
    533     baseSub.resize(0,0);
    534   }
    535 
    536   if (cGetSpectra && cMBrec.haveSpectra) {
    537     spectra.resize(nChan,nPol);
    538     spectra.takeStorage(IPosition(2,nChan,nPol), cMBrec.spectra[0], SHARE);
    539 
    540     flagged.resize(nChan,nPol);
    541     flagged.takeStorage(IPosition(2,nChan,nPol), cMBrec.flagged[0], SHARE);
    542 
    543   } else {
    544     spectra.resize(0,0);
    545     flagged.resize(0,0);
    546   }
    547 
    548   return 0;
    549 }
    550 
    551535//------------------------------------------------------- PKSFITSreader::close
    552536
     
    556540{
    557541  cReader->close();
     542  //logMsg(cReader->getMsg());
     543  //cReader->clearMsg();
    558544}
    559545
  • branches/alma/external/atnf/PKSIO/PKSFITSreader.h

    r1453 r1757  
    22//# PKSFITSreader.h: Class to read Parkes Multibeam data from a FITS file.
    33//#---------------------------------------------------------------------------
    4 //# Copyright (C) 2000-2006
    5 //# Associated Universities, Inc. Washington DC, USA.
     4//# livedata - processing pipeline for single-dish, multibeam spectral data.
     5//# Copyright (C) 2000-2009, Australia Telescope National Facility, CSIRO
    66//#
    7 //# This library is free software; you can redistribute it and/or modify it
    8 //# under the terms of the GNU Library General Public License as published by
    9 //# the Free Software Foundation; either version 2 of the License, or (at your
    10 //# option) any later version.
     7//# This file is part of livedata.
    118//#
    12 //# This library is distributed in the hope that it will be useful, but WITHOUT
     9//# livedata is free software: you can redistribute it and/or modify it under
     10//# the terms of the GNU General Public License as published by the Free
     11//# Software Foundation, either version 3 of the License, or (at your option)
     12//# any later version.
     13//#
     14//# livedata is distributed in the hope that it will be useful, but WITHOUT
    1315//# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    14 //# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Library General Public
    15 //# License for more details.
     16//# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
     17//# more details.
    1618//#
    17 //# You should have received a copy of the GNU Library General Public License
    18 //# along with this library; if not, write to the Free Software Foundation,
    19 //# Inc., 675 Massachusetts Ave, Cambridge, MA 02139, USA.
     19//# You should have received a copy of the GNU General Public License along
     20//# with livedata.  If not, see <http://www.gnu.org/licenses/>.
    2021//#
    21 //# Correspondence concerning AIPS++ should be addressed as follows:
    22 //#        Internet email: aips2-request@nrao.edu.
    23 //#        Postal address: AIPS++ Project Office
    24 //#                        National Radio Astronomy Observatory
    25 //#                        520 Edgemont Road
    26 //#                        Charlottesville, VA 22903-2475 USA
     22//# Correspondence concerning livedata may be directed to:
     23//#        Internet email: mcalabre@atnf.csiro.au
     24//#        Postal address: Dr. Mark Calabretta
     25//#                        Australia Telescope National Facility, CSIRO
     26//#                        PO Box 76
     27//#                        Epping NSW 1710
     28//#                        AUSTRALIA
    2729//#
    28 //# $Id$
     30//# http://www.atnf.csiro.au/computing/software/livedata.html
     31//# $Id: PKSFITSreader.h,v 19.18 2009-09-29 07:33:38 cal103 Exp $
    2932//#---------------------------------------------------------------------------
    3033//# This class is basically a wrapper class for reading data from either an
     
    3942
    4043#include <atnf/PKSIO/FITSreader.h>
     44#include <atnf/PKSIO/PKSrecord.h>
    4145#include <atnf/PKSIO/PKSreader.h>
    4246
    4347#include <casa/aips.h>
     48#include <casa/stdio.h>
    4449#include <casa/Arrays/Vector.h>
    4550#include <casa/Arrays/Matrix.h>
     
    4752#include <casa/BasicSL/String.h>
    4853
     54#include <casa/namespace.h>
     55
    4956// <summary>
    5057// Class to read Parkes Multibeam data from a FITS file.
    5158// </summary>
    5259
    53 #include <casa/namespace.h>
    5460class PKSFITSreader : public PKSreader
    5561{
     
    6773    virtual Int open(
    6874        const String fitsName,
     75        const String antenna,
    6976        Vector<Bool> &beams,
    7077        Vector<Bool> &IFs,
     
    8289        Vector<Double> &antPosition,
    8390        String &obsType,
     91        String &bunit,
    8492        Float  &equinox,
    8593        String &dopplerFrame,
    8694        Double &mjd,
    8795        Double &refFreq,
    88         Double &bandwidth,
    89         String &fluxunit);
     96        Double &bandwidth);
    9097
    9198    // Get frequency parameters for each IF.
     
    104111        const Bool getSpectra = True,
    105112        const Bool getXPol    = False,
    106         const Bool getFeedPos = False);
     113        const Bool getFeedPos = False,
     114        const Bool getPointing = False,
     115        const Int  coordSys   = 0);
    107116
    108117    // Find the range of the data selected in time and position.
     
    114123
    115124    // Read the next data record.
    116     virtual Int read(
    117         Int             &scanNo,
    118         Int             &cycleNo,
    119         Double          &mjd,
    120         Double          &interval,
    121         String          &fieldName,
    122         String          &srcName,
    123         Vector<Double>  &srcDir,
    124         Vector<Double>  &srcPM,
    125         Double          &srcVel,
    126         String          &obsType,
    127         Int             &IFno,
    128         Double          &refFreq,
    129         Double          &bandwidth,
    130         Double          &freqInc,
    131         Vector<Double>  &restFreq,
    132         Vector<Float>   &tcal,
    133         String          &tcalTime,
    134         Float           &azimuth,
    135         Float           &elevation,
    136         Float           &parAngle,
    137         Float           &focusAxi,
    138         Float           &focusTan,
    139         Float           &focusRot,
    140         Float           &temperature,
    141         Float           &pressure,
    142         Float           &humidity,
    143         Float           &windSpeed,
    144         Float           &windAz,
    145         Int             &refBeam,
    146         Int             &beamNo,
    147         Vector<Double>  &direction,
    148         Vector<Double>  &scanRate,
    149         Vector<Float>   &tsys,
    150         Vector<Float>   &sigma,
    151         Vector<Float>   &calFctr,
    152         Matrix<Float>   &baseLin,
    153         Matrix<Float>   &baseSub,
    154         Matrix<Float>   &spectra,
    155         Matrix<uChar>   &flagged,
    156         Complex         &xCalFctr,
    157         Vector<Complex> &xPol);
    158 
    159     // Read the next data record, just the basics.
    160     virtual Int read(
    161         Int           &IFno,
    162         Vector<Float> &tsys,
    163         Vector<Float> &calFctr,
    164         Matrix<Float> &baseLin,
    165         Matrix<Float> &baseSub,
    166         Matrix<Float> &spectra,
    167         Matrix<uChar> &flagged);
     125    virtual Int read(PKSrecord &pksrec);
    168126
    169127    // Close the FITS file.
     
    173131    Int    *cBeams, *cIFs;
    174132    uInt   cNBeam, cNIF;
    175     PKSMBrecord cMBrec;
     133    MBrecord cMBrec;
    176134    FITSreader  *cReader;
    177135
  • branches/alma/external/atnf/PKSIO/PKSMS2reader.cc

    r1453 r1757  
    22//# PKSMS2reader.cc: Class to read Parkes Multibeam data from a v2 MS.
    33//#---------------------------------------------------------------------------
    4 //# Copyright (C) 2000-2006
    5 //# Associated Universities, Inc. Washington DC, USA.
     4//# livedata - processing pipeline for single-dish, multibeam spectral data.
     5//# Copyright (C) 2000-2009, Australia Telescope National Facility, CSIRO
    66//#
    7 //# This library is free software; you can redistribute it and/or modify it
    8 //# under the terms of the GNU Library General Public License as published by
    9 //# the Free Software Foundation; either version 2 of the License, or (at your
    10 //# option) any later version.
     7//# This file is part of livedata.
    118//#
    12 //# This library is distributed in the hope that it will be useful, but
    13 //# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
    14 //# or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Library General Public
    15 //# License for more details.
     9//# livedata is free software: you can redistribute it and/or modify it under
     10//# the terms of the GNU General Public License as published by the Free
     11//# Software Foundation, either version 3 of the License, or (at your option)
     12//# any later version.
    1613//#
    17 //# You should have received a copy of the GNU Library General Public License
    18 //# along with this library; if not, write to the Free Software Foundation,
    19 //# Inc., 675 Massachusetts Ave, Cambridge, MA 02139, USA.
     14//# livedata is distributed in the hope that it will be useful, but WITHOUT
     15//# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
     16//# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
     17//# more details.
    2018//#
    21 //# Correspondence concerning AIPS++ should be addressed as follows:
    22 //#        Internet email: aips2-request@nrao.edu.
    23 //#        Postal address: AIPS++ Project Office
    24 //#                        National Radio Astronomy Observatory
    25 //#                        520 Edgemont Road
    26 //#                        Charlottesville, VA 22903-2475 USA
     19//# You should have received a copy of the GNU General Public License along
     20//# with livedata.  If not, see <http://www.gnu.org/licenses/>.
    2721//#
    28 //# $Id$
     22//# Correspondence concerning livedata may be directed to:
     23//#        Internet email: mcalabre@atnf.csiro.au
     24//#        Postal address: Dr. Mark Calabretta
     25//#                        Australia Telescope National Facility, CSIRO
     26//#                        PO Box 76
     27//#                        Epping NSW 1710
     28//#                        AUSTRALIA
     29//#
     30//# http://www.atnf.csiro.au/computing/software/livedata.html
     31//# $Id: PKSMS2reader.cc,v 19.23 2009-09-29 07:33:38 cal103 Exp $
    2932//#---------------------------------------------------------------------------
    3033//# Original: 2000/08/03, Mark Calabretta, ATNF
    3134//#---------------------------------------------------------------------------
    32 
    3335
    3436// AIPS++ includes.
     
    4143#include <casa/Quanta/MVAngle.h>
    4244#include <casa/BasicMath/Math.h>
     45#include <casa/Logging/LogIO.h>
     46#include <casa/Utilities/Sort.h>
    4347#include <measures/Measures/MeasConvert.h>
    4448#include <measures/Measures/MEpoch.h>
     
    4852// Parkes includes.
    4953#include <atnf/pks/pks_maths.h>
     54#include <atnf/PKSIO/PKSrecord.h>
    5055#include <atnf/PKSIO/PKSMS2reader.h>
    5156
     
    7378Int PKSMS2reader::open(
    7479        const String msName,
     80        const String antenna,
    7581        Vector<Bool> &beams,
    7682        Vector<Bool> &IFs,
     
    9197
    9298  cPKSMS  = MeasurementSet(msName);
     99
     100  // data selection by antenna
     101  if ( antenna.length() == 0 ) {
     102    cAntId.resize( 1 ) ;
     103    cAntId[0] = 0 ;
     104  }
     105  else {
     106    setupAntennaList( antenna ) ;
     107    if ( cAntId.size() > 1 ) {
     108      LogIO os( LogOrigin( "PKSMS2reader", "open()", WHERE ) ) ;
     109      os << LogIO::WARN << "PKSMS2reader is not ready for multiple antenna selection. Use first antenna id " << cAntId[0] << "."<< LogIO::POST ;
     110      Int tmp = cAntId[0] ;
     111      cAntId.resize( 1 ) ;
     112      cAntId[0] = tmp ;
     113    }
     114    stringstream ss ;
     115    ss << "SELECT FROM $1 WHERE ANTENNA1 == ANTENNA2 && ANTENNA1 IN [" ;
     116    for ( uInt i = 0 ; i < cAntId.size() ; i++ ) {
     117      ss << cAntId[i] ;
     118      if ( i == cAntId.size()-1 ) {
     119        ss << "]" ;
     120      }
     121      else {
     122        ss << "," ;
     123      }
     124    }
     125    string taql = ss.str() ;
     126    //cerr << "taql = " << taql << endl ;
     127    cPKSMS = MeasurementSet( tableCommand( taql, cPKSMS ) ) ;
     128  }
     129
    93130  // taql access to the syscal table
    94131  cHaveSysCal = False;
     
    97134  }
    98135
     136  // Lock the table for read access.
     137  cPKSMS.lock(False);
     138
    99139  cIdx    = 0;
    100140  lastmjd = 0.0;
    101141  cNRow   = cPKSMS.nrow();
    102142  cMSopen = True;
    103 
    104   // Lock the table for read access.
    105   cPKSMS.lock(False);
    106143
    107144  // Main MS table and subtable column access.
     
    140177  cSigStateCol.reference(stateCols.sig());
    141178  cRefStateCol.reference(stateCols.ref());
     179
    142180  cDataDescIdCol.reference(msCols.dataDescId());
    143181  cSpWinIdCol.reference(dataDescCols.spectralWindowId());
    144182  cChanFreqCol.reference(spWinCols.chanFreq());
     183  cTotBWCol.reference(spWinCols.totalBandwidth());
    145184
    146185  cWeatherTimeCol.reference(weatherCols.time());
     
    151190  cBeamNoCol.reference(msCols.feed1());
    152191  cPointingCol.reference(pointingCols.direction());
     192  cPointingTimeCol.reference(pointingCols.time());
    153193  cSigmaCol.reference(msCols.sigma());
    154194  cNumReceptorCol.reference(feedCols.numReceptors());
     
    182222  cHaveDataCol = False;
    183223  cHaveCorrectedDataCol = False;
    184   //String telName = antennaCols.name()(0);
    185224  ROMSObservationColumns observationCols(cPKSMS.observation());
    186   String telName = observationCols.telescopeName()(0);
    187   //cATF = (telName.contains("DA41") || telName.contains("DV01"));
    188   cATF = telName.contains("ATF");
     225  //String telName = observationCols.telescopeName()(0);
     226  cTelName = observationCols.telescopeName()(0);
     227  //cATF = cTelName.contains("ATF");
     228  //cOSF = cTelName.contains("OSF");
     229  //cALMA = cTelName.contains("ALMA");
     230  cALMA = cTelName.contains("ATF")||cTelName.contains("OSF")||
     231           cTelName.contains("ALMA");
    189232
    190233  if (cHaveDataCol = cPKSMS.isColumn(MSMainEnums::DATA)) {
    191     if (cATF) {
     234    if (cALMA) {
    192235      //try to read a single baseline interferometeric data
    193236      //and treat it as single dish data
     
    204247  }
    205248  cFlagCol.reference(msCols.flag());
    206 
    207 
    208   if (cGetXPol = (cPKSMS.isColumn(MSMainEnums::DATA) && (!cATF))) {
     249  cFlagRowCol.reference(msCols.flagRow());
     250
     251  if (cGetXPol = (cPKSMS.isColumn(MSMainEnums::DATA) && (!cALMA))) {
    209252    if ((cHaveXCalFctr = cPKSMS.tableDesc().isColumn("XCALFCTR"))) {
    210253      cXCalFctrCol.attach(cPKSMS, "XCALFCTR");
     
    228271  //uInt nIF = dataDescCols.nrow();
    229272  uInt nIF =spWinCols.nrow();
     273  Vector<Int> spWinIds = cSpWinIdCol.getColumn() ;
    230274  IFs.resize(nIF);
    231275  IFs = True;
     276  for ( Int ispw = 0 ; ispw < nIF ; ispw++ ) {
     277    if ( allNE( ispw, spWinIds ) ) {
     278      IFs(ispw) = False ;
     279    }
     280  }
    232281
    233282  // Number of polarizations and channels in each IF.
    234   ROScalarColumn<Int> spWinIdCol(dataDescCols.spectralWindowId());
    235283  ROScalarColumn<Int> numChanCol(spWinCols.numChan());
    236284
     
    241289  nPol.resize(nIF);
    242290  for (uInt iIF = 0; iIF < nIF; iIF++) {
    243     nChan(iIF) = numChanCol(spWinIdCol(iIF));
    244     nPol(iIF)  = numPolCol(polIdCol(iIF));
     291    if ( IFs(iIF) ) {
     292      nChan(iIF) = numChanCol(cSpWinIdCol(iIF)) ;
     293      nPol(iIF) = numPolCol(polIdCol(iIF)) ;
     294    }
     295    else {
     296      nChan(iIF) = 0 ;
     297      nPol(iIF) = 0 ;
     298    }
    245299  }
    246300
     
    249303  haveXPol = False;
    250304
    251   if (cGetXPol && !(cATF)) {
     305  if (cGetXPol && !(cALMA)) {
    252306    for (Int irow = 0; irow < cNRow; irow++) {
    253307      if (cDataCol.isDefined(irow)) {
     
    298352        String &antName,
    299353        Vector<Double> &antPosition,
    300         String &obsMode,
     354        // before merge...
     355        //String &obsMode,
     356        String &obsType,
     357        String &bunit,
    301358        Float  &equinox,
    302359        String &dopplerFrame,
    303360        Double &mjd,
    304361        Double &refFreq,
    305         Double &bandwidth,
    306         String &fluxunit)
     362        Double &bandwidth)
    307363{
    308364  if (!cMSopen) {
     
    317373  // Antenna name and ITRF coordinates.
    318374  ROMSAntennaColumns antennaCols(cPKSMS.antenna());
    319   antName = antennaCols.name()(0);
    320   antPosition = antennaCols.position()(0);
     375  //antName = antennaCols.name()(0);
     376  antName = antennaCols.name()(cAntId[0]);
     377  if (cALMA) {
     378     antName = cTelName + "-" + antName;
     379  }
     380  //antPosition = antennaCols.position()(0);
     381  antPosition = antennaCols.position()(cAntId[0]);
    321382
    322383  // Observation type.
    323384  if (cObsModeCol.nrow()) {
    324     obsMode = cObsModeCol(0);
    325     if (obsMode == "\0") obsMode = "RF";
     385    obsType = cObsModeCol(0);
     386    if (obsType == "\0") obsType = "RF";
    326387  } else {
    327     obsMode = "RF";
    328   }
    329 
    330   fluxunit = "";
     388    obsType = "RF";
     389  }
     390
     391  bunit = "";
    331392  if (cHaveDataCol) {
    332393    const TableRecord& keywordSet2
    333394       = cDataCol.columnDesc().keywordSet();
    334395    if(keywordSet2.isDefined("UNIT")) {
    335       fluxunit = keywordSet2.asString("UNIT");
     396      bunit = keywordSet2.asString("UNIT");
    336397    }
    337398  } else {
     
    339400       = cFloatDataCol.columnDesc().keywordSet();
    340401    if(keywordSet.isDefined("UNIT")) {
    341       fluxunit = keywordSet.asString("UNIT");
     402      bunit = keywordSet.asString("UNIT");
    342403    }
    343404  }
     
    354415  String dirref = pointingCols.direction().keywordSet().asRecord("MEASINFO").
    355416                    asString("Ref");
     417  cDirRef = dirref;
     418  if (dirref =="AZELGEO" || dirref == "AZEL") {
     419     dirref = "J2000";
     420  }
    356421  sscanf(dirref.chars()+1, "%f", &equinox);
    357422
     
    422487        const Bool getSpectra,
    423488        const Bool getXPol,
    424         const Bool getFeedPos)
     489        const Bool getFeedPos,
     490        const Bool getPointing,
     491        const Int  coordSys)
    425492{
    426493  if (!cMSopen) {
     
    504571  cGetFeedPos = False;
    505572
     573  // Get Pointing data (for MS)
     574  cGetPointing = getPointing;
     575
     576  // Coordinate system?  (Only equatorial available.)
     577  cCoordSys = 0;
     578
    506579  return maxNChan;
    507580}
     
    555628// Read the next data record.
    556629
     630/**
    557631Int PKSMS2reader::read(
    558632        Int             &scanNo,
     
    595669        Matrix<Float>   &spectra,
    596670        Matrix<uChar>   &flagged,
     671        uInt            &flagrow,
    597672        Complex         &xCalFctr,
    598673        Vector<Complex> &xPol)
     674**/
     675Int PKSMS2reader::read(PKSrecord &pksrec)
    599676{
     677  LogIO os( LogOrigin( "PKSMS2reader", "read()", WHERE ) ) ;
     678
    600679  if (!cMSopen) {
    601680    return 1;
     
    627706  // Renumerate scan no. Here still is 1-based
    628707  //scanNo = cScanNoCol(cIdx) - cScanNoCol(0) + 1;
    629   scanNo = cScanNoCol(cIdx);
    630  
    631   if (scanNo != cScanNo) {
     708  //scanNo = cScanNoCol(cIdx);
     709  pksrec.scanNo = cScanNoCol(cIdx);
     710
     711  if (pksrec.scanNo != cScanNo) {
    632712    // Start of new scan.
    633     cScanNo  = scanNo;
     713    cScanNo  = pksrec.scanNo;
    634714    cCycleNo = 1;
    635715    cTime    = cTimeCol(cIdx);
     
    637717
    638718  Double time = cTimeCol(cIdx);
    639   mjd      = time/86400.0;
    640   interval = cIntervalCol(cIdx);
     719  pksrec.mjd      = time/86400.0;
     720  pksrec.interval = cIntervalCol(cIdx);
    641721
    642722  // Reconstruct the integration cycle number; due to small latencies the
    643723  // integration time is usually slightly less than the time between cycles,
    644724  // resetting cTime will prevent the difference from accumulating.
    645   cCycleNo += nint((time - cTime)/interval);
    646   cycleNo = cCycleNo;
    647   cTime   = time;
     725  cCycleNo += nint((time - cTime)/pksrec.interval);
     726  pksrec.cycleNo = cCycleNo;
     727  cTime = time;
    648728
    649729  Int fieldId = cFieldIdCol(cIdx);
    650   fieldName = cFieldNameCol(fieldId);
     730  pksrec.fieldName = cFieldNameCol(fieldId);
    651731
    652732  Int srcId = cSrcIdCol(fieldId);
     
    656736  for (uInt irow = 0; irow < cSrcId2Col.nrow(); irow++) {
    657737    if (cSrcId2Col(irow) == srcId) {
    658       srcName = cSrcNameCol(irow);
    659     }
    660   }
    661 
    662   srcDir  = cSrcDirCol(srcId);
    663   srcPM   = cSrcPMCol(srcId);
     738      //srcName = cSrcNameCol(irow);
     739      pksrec.srcName = cSrcNameCol(irow);
     740    }
     741  }
     742
     743  pksrec.srcDir  = cSrcDirCol(srcId);
     744  pksrec.srcPM   = cSrcPMCol(srcId);
    664745
    665746  // Systemic velocity.
    666   if (!cHaveSrcVel || cATF) {
    667     srcVel = 0.0f;
     747  if (!cHaveSrcVel || cALMA) {
     748    pksrec.srcVel = 0.0f;
    668749  } else {
    669     srcVel = cSrcVelCol(srcId)(IPosition(1,0));
     750    pksrec.srcVel = cSrcVelCol(srcId)(IPosition(1,0));
    670751  }
    671752
    672753  ROMSAntennaColumns antennaCols(cPKSMS.antenna());
    673   String telescope = antennaCols.name()(0);
     754  //String telescope = antennaCols.name()(0);
     755  String telescope = antennaCols.name()(cAntId[0]);
    674756  Bool cGBT = telescope.contains("GBT");
     757  //Bool cPM = telescope.contains("PM"); // ACA TP antenna
     758  //Bool cDV = telescope.contains("DV"); // VERTEX
     759  //Bool cCM = telescope.contains("CM"); // ACA 7m antenna
     760  //Bool cALMA = cPM || cDV || cCM ;
    675761  // Observation type.
    676762  // check if State Table exist
     
    680766  StateNRow=cObsModeCol.nrow();
    681767  if (Table::isReadable(cPKSMS.stateTableName())) {
    682         obsMode = " ";
     768        pksrec.obsType = " ";
    683769    if (StateNRow > 0) {
    684770      stateId = cStateIdCol(cIdx);
    685771      if (stateId == -1) {
    686         //obsMode = " ";
     772        //pksrec.obsType = " ";
    687773      } else {
    688         obsMode = cObsModeCol(stateId);
     774        pksrec.obsType = cObsModeCol(stateId);
    689775        Bool sigState =cSigStateCol(stateId);
    690776        Bool refState =cRefStateCol(stateId);
    691777        //DEBUG
    692         //cerr <<"stateid="<<stateId<<" obsmode="<<obsMode<<endl;
     778        //cerr <<"stateid="<<stateId<<" obsmode="<<pksrec.obsType<<endl;
    693779        if (cGBT) {
    694           // split the obsMode string and append a proper label
     780          // split the obsType string and append a proper label
    695781          // (these are GBT specific)
    696           int epos = obsMode.find_first_of(':');
    697           int nextpos = obsMode.find_first_of(':',epos+1);
    698           string obsMode1 = obsMode.substr(0,epos);
    699           string obsMode2 = obsMode.substr(epos+1,nextpos-epos-1);
     782          int epos = pksrec.obsType.find_first_of(':');
     783          int nextpos = pksrec.obsType.find_first_of(':',epos+1);
     784          string obsMode1 = pksrec.obsType.substr(0,epos);
     785          string obsMode2 = pksrec.obsType.substr(epos+1,nextpos-epos-1);
    700786     
    701787          //cerr <<"obsMode2= "<<obsMode2<<endl;
    702           if (!srcName.contains("_ps")
    703               &&!srcName.contains("_psr")
    704               &&!srcName.contains("_nod")
    705               &&!srcName.contains("_fs")
    706               &&!srcName.contains("_fsr")) {
     788          if (!pksrec.srcName.contains("_ps")
     789              &&!pksrec.srcName.contains("_psr")
     790              &&!pksrec.srcName.contains("_nod")
     791              &&!pksrec.srcName.contains("_fs")
     792              &&!pksrec.srcName.contains("_fsr")) {
    707793            // if Nod mode observation , append '_nod'
    708794            if (obsMode1 == "Nod") {
    709               srcName.append("_nod");
     795              //pksrec.srcName.append("_nod");
     796              pksrec.srcType = SrcType::NOD ;
    710797            } else if (obsMode1 == "OffOn") {
    711798            // for GBT position switch observations (OffOn or OnOff)
    712               if (obsMode2 == "PSWITCHON") srcName.append("_ps");
    713               if (obsMode2 == "PSWITCHOFF") srcName.append("_psr");
     799              //if (obsMode2 == "PSWITCHON") pksrec.srcName.append("_ps");
     800              //if (obsMode2 == "PSWITCHOFF") pksrec.srcName.append("_psr");
     801              if (obsMode2 == "PSWITCHON") pksrec.srcType = SrcType::PSON ;
     802              if (obsMode2 == "PSWITCHOFF") pksrec.srcType = SrcType::PSOFF ;
    714803            } else {
    715804              if (obsMode2 == "FSWITCH") {
    716805              // for GBT frequency switch mode
    717                 if (sigState) srcName.append("_fs");
    718                 if (refState) srcName.append("_fsr");
     806                //if (sigState) pksrec.srcName.append("_fs");
     807                //if (refState) pksrec.srcName.append("_fsr");
     808                if (sigState) pksrec.srcType = SrcType::FSON ;
     809                if (refState) pksrec.srcType = SrcType::FSOFF ;
    719810              }
    720811            }
    721812          }
    722813        }
     814        else if (cALMA) {
     815          // ALMA tag
     816          // split the obsType string and append a proper label
     817          string substr[1] ;
     818          int numSubstr = split( pksrec.obsType, substr, 1, "," );
     819          String obsType = String( substr[0] );
     820          int epos = obsType.find_first_of('.');
     821          int nextpos = obsType.find_first_of('.',epos+1);
     822          string obsMode1 = obsType.substr(0,epos);
     823          string obsMode2 = obsType.substr(epos+1,nextpos-epos-1);
     824     
     825          //cerr <<"obsMode2= "<<obsMode2<<endl;
     826          // Current OBS_MODE format:
     827          //
     828          //     ON: OBSERVE_TARGET.ON_SOURCE
     829          //    OFF: OBSERVE_TARGET.OFF_SOURCE
     830          //
     831          if (obsMode1 == "OBSERVE_TARGET") {
     832            //if (obsMode2 == "ON_SOURCE") pksrec.srcName.append("_pson");
     833            //if (obsMode2 == "OFF_SOURCE") pksrec.srcName.append("_psoff");
     834            if (obsMode2 == "ON_SOURCE") pksrec.srcType = SrcType::PSON ;
     835            if (obsMode2 == "OFF_SOURCE") pksrec.srcType = SrcType::PSOFF ;
     836          }
     837        }
    723838      }
    724839    }
     
    733848  }
    734849  if (cGBT) {
    735     if (Cal > 0 && !srcName.contains("_calon")) {
    736       srcName.append("_calon");
    737     }
    738   }
    739 
    740   IFno = iIF + 1;
     850    if (Cal > 0 && !pksrec.srcName.contains("_calon")) {
     851      //pksrec.srcName.append("_calon");
     852      if ( pksrec.srcType == SrcType::NOD )
     853        pksrec.srcType = SrcType::NODCAL ;
     854      else if ( pksrec.srcType == SrcType::PSON )
     855        pksrec.srcType = SrcType::PONCAL ;
     856      else if ( pksrec.srcType == SrcType::PSOFF )
     857        pksrec.srcType = SrcType::POFFCAL ;
     858      else if ( pksrec.srcType == SrcType::FSON )
     859        pksrec.srcType = SrcType::FONCAL ;
     860      else if ( pksrec.srcType == SrcType::FSOFF )
     861        pksrec.srcType = SrcType::FOFFCAL ;
     862      else
     863        pksrec.srcName.append("_calon");
     864    }
     865  }
     866
     867  pksrec.IFno = iIF + 1;
    741868  Int nChan = abs(cEndChan(iIF) - cStartChan(iIF)) + 1;
    742869 
    743870  // Minimal handling on continuum data.
    744871  Vector<Double> chanFreq = cChanFreqCol(iIF);
     872  pksrec.nchan = nChan;
    745873  if (nChan == 1) {
    746     freqInc  = chanFreq(0);
    747     refFreq  = chanFreq(0);
    748     restFreq = 0.0f;
     874    //pksrec.freqInc  = chanFreq(0);
     875    pksrec.freqInc  = cTotBWCol(iIF);
     876    pksrec.refFreq  = chanFreq(0);
     877    pksrec.restFreq.resize(1);
     878    pksrec.restFreq[0] = 0.0f;
    749879  } else {
    750880 
    751881    if (cStartChan(iIF) <= cEndChan(iIF)) {
    752       freqInc = chanFreq(1) - chanFreq(0);
     882      pksrec.freqInc = chanFreq(1) - chanFreq(0);
    753883    } else {
    754       freqInc = chanFreq(0) - chanFreq(1);
    755     }
    756     refFreq  = chanFreq(cRefChan(iIF)-1);
     884      pksrec.freqInc = chanFreq(0) - chanFreq(1);
     885    }
     886
     887    pksrec.refFreq  = chanFreq(cRefChan(iIF)-1);
     888
    757889    Bool HaveSrcRestFreq= cSrcRestFrqCol.isDefined(srcId);
    758890    if (HaveSrcRestFreq) {
    759891      //restFreq = cSrcRestFrqCol(srcId)(IPosition(1,0));
    760       restFreq = cSrcRestFrqCol(srcId);
     892      //restFreq = cSrcRestFrqCol(srcId);
     893      pksrec.restFreq = cSrcRestFrqCol(srcId);
    761894    } else {
    762       restFreq = 0.0f;
    763     }
    764   }
    765   bandwidth = abs(freqInc * nChan);
    766 
    767   tcal.resize(cNPol(iIF));
    768   tcal      = 0.0f;
    769   tcalTime  = "";
    770   //azimuth   = 0.0f;
    771   //elevation = 0.0f;
    772   parAngle  = 0.0f;
    773   focusAxi  = 0.0f;
    774   focusTan  = 0.0f;
    775   focusRot  = 0.0f;
     895      pksrec.restFreq.resize(1);
     896      pksrec.restFreq[0] = 0.0f;
     897    }
     898  }
     899  //pksrec.bandwidth = abs(pksrec.freqInc * nChan);
     900  pksrec.bandwidth = abs(cTotBWCol(0));
     901
     902  pksrec.tcal.resize(cNPol(iIF));
     903  pksrec.tcal      = 0.0f;
     904  pksrec.tcalTime  = "";
     905//  pksrec.azimuth   = 0.0f;
     906//  pksrec.elevation = 0.0f;
     907  pksrec.parAngle  = 0.0f;
     908
     909  pksrec.focusAxi  = 0.0f;
     910  pksrec.focusTan  = 0.0f;
     911  pksrec.focusRot  = 0.0f;
    776912
    777913  // Find the appropriate entry in the WEATHER subtable.
     
    787923    }
    788924  }
     925
    789926  if (weatherIdx < 0 || !cHaveWeatherTab) {
    790927    // No appropriate WEATHER entry.
    791     pressure    = 0.0f;
    792     humidity    = 0.0f;
    793     temperature = 0.0f;
     928    pksrec.temperature = 0.0f;
     929    pksrec.pressure    = 0.0f;
     930    pksrec.humidity    = 0.0f;
    794931  } else {
    795     pressure    = cPressureCol(weatherIdx);
    796     humidity    = cHumidityCol(weatherIdx);
    797     temperature = cTemperatureCol(weatherIdx);
    798   }
    799 
    800   windSpeed = 0.0f;
    801   windAz    = 0.0f;
    802 
    803   refBeam = 0;
    804   beamNo  = ibeam + 1;
    805 
    806   //Matrix<Double> pointingDir = cPointingCol(fieldId);
    807   //pointingDir = cPointingCol(fieldId);
    808   //direction = pointingDir.column(0);
    809   //uInt ncols = pointingDir.ncolumn();
    810   //if (ncols == 1) {
    811   //  scanRate = 0.0f;
    812   //} else {
    813   //  scanRate  = pointingDir.column(1);
    814   //}
    815 
     932    pksrec.temperature = cTemperatureCol(weatherIdx);
     933    pksrec.pressure    = cPressureCol(weatherIdx);
     934    pksrec.humidity    = cHumidityCol(weatherIdx);
     935  }
     936
     937  pksrec.windSpeed = 0.0f;
     938  pksrec.windAz    = 0.0f;
     939
     940  pksrec.refBeam = 0;
     941  pksrec.beamNo  = ibeam + 1;
     942
     943  //pointing/azel
     944  MVPosition mvpos(antennaCols.position()(cAntId[0]));
     945  MPosition mp(mvpos);
     946  Quantum<Double> qt(time,"s");
     947  MVEpoch mvt(qt);
     948  MEpoch me(mvt);
     949  MeasFrame frame(mp, me);
     950  MDirection md;
     951  pksrec.pCode = 0;
     952  pksrec.rateAge = 0.0f;
     953  pksrec.paRate = 0.0f;
     954  if (cGetPointing) {
     955    //cerr << "get pointing data ...." << endl;
     956    ROScalarColumn<Int> pAntIdCol ;
     957    ROScalarColumn<Double> psTimeCol ;
     958    Table ptTable = cPKSMS.pointing() ;
     959    MSPointing selPtTab( ptTable( ptTable.col("ANTENNA_ID") == cAntId[0] ) ) ;
     960    pAntIdCol.attach( selPtTab, "ANTENNA_ID" ) ;
     961    Vector<Int> antIds = pAntIdCol.getColumn() ;
     962    psTimeCol.attach( selPtTab, "TIME" ) ;
     963    Vector<Double> pTimes = psTimeCol.getColumn();
     964    Bool doInterp = False ;
     965    Int PtIdx=-1;
     966    for (PtIdx = pTimes.nelements()-1; PtIdx >= 0; PtIdx--) {
     967      if ( pTimes[PtIdx] == time ) {
     968        break ;
     969      }
     970      else if ( pTimes[PtIdx] < time ) {
     971        if ( PtIdx != pTimes.nelements()-1 ) {
     972          doInterp = True ;
     973        }
     974        break ;
     975      }
     976    }
     977    if ( PtIdx == -1 ) {
     978      PtIdx = 0 ;
     979    }
     980    //cerr << "got index=" << PtIdx << endl;
     981    Matrix<Double> pointingDir = cPointingCol(PtIdx);
     982    ROMSPointingColumns PtCols( selPtTab ) ;
     983    Vector<Double> pointingDirVec ;
     984    if ( doInterp ) {
     985      Double dt1 = time - pTimes[PtIdx] ;
     986      Double dt2 = pTimes[PtIdx+1] - time ;
     987      Vector<Double> dirVec1 = pointingDir.column(0) ;
     988      Matrix<Double> pointingDir2 = cPointingCol(PtIdx+1) ;
     989      Vector<Double> dirVec2 = pointingDir2.column(0) ;
     990      pointingDirVec = (dt1*dirVec2+dt2*dirVec1)/(dt1+dt2) ;
     991      Vector<MDirection> vmd1(1) ;
     992      Vector<MDirection> vmd2(1) ;
     993      PtCols.directionMeasCol().get(PtIdx,vmd1) ;
     994      Vector<Double> angle1 = vmd1(0).getAngle().getValue("rad") ;
     995      PtCols.directionMeasCol().get(PtIdx+1,vmd2) ;
     996      Vector<Double> angle2 = vmd2(0).getAngle().getValue("rad") ;
     997      Vector<Double> angle = (dt1*angle2+dt2*angle1)/(dt1+dt2) ;
     998      Quantum< Vector<Double> > qangle( angle, "rad" ) ;
     999      String typeStr = vmd1(0).getRefString() ;
     1000      //cerr << "vmd1.getRefString()=" << typeStr << endl ;
     1001      MDirection::Types mdType ;
     1002      MDirection::getType( mdType, typeStr ) ;
     1003      //cerr << "mdType=" << mdType << endl ;
     1004      md = MDirection( qangle, mdType ) ;
     1005      //cerr << "md=" << md.getAngle().getValue("rad") << endl ;
     1006    }
     1007    else {
     1008      pointingDirVec = pointingDir.column(0) ;
     1009      Vector<MDirection> vmd(1);
     1010      PtCols.directionMeasCol().get(PtIdx,vmd);
     1011      md = vmd[0];
     1012    }
     1013    // put J2000 coordinates in "direction"
     1014    if (cDirRef =="J2000") {
     1015      pksrec.direction = pointingDirVec ;
     1016    }
     1017    else {
     1018      pksrec.direction =
     1019        MDirection::Convert(md, MDirection::Ref(MDirection::J2000,
     1020                                                frame)
     1021                            )().getAngle("rad").getValue();
     1022     
     1023    }
     1024    uInt ncols = pointingDir.ncolumn();
     1025    pksrec.scanRate.resize(2);
     1026    if (ncols == 1) {
     1027      pksrec.scanRate = 0.0f;
     1028    } else {
     1029      pksrec.scanRate(0) = pointingDir.column(1)(0);
     1030      pksrec.scanRate(1) = pointingDir.column(1)(1);
     1031    }
     1032  }
     1033  else {
    8161034  // Get direction from FIELD table
    8171035  // here, assume direction to be the field direction not pointing
    818   Matrix<Double> delayDir = cFieldDelayDirCol(fieldId);
    819   direction = delayDir.column(0);
    820   uInt ncols = delayDir.ncolumn();
    821   if (ncols == 1) {
    822     scanRate = 0.0f;
    823   } else {
    824     scanRate  = delayDir.column(1);
    825   }
    826 
     1036    Matrix<Double> delayDir = cFieldDelayDirCol(fieldId);
     1037    pksrec.direction = delayDir.column(0);
     1038    uInt ncols = delayDir.ncolumn();
     1039    pksrec.scanRate.resize(2);
     1040    if (ncols == 1) {
     1041      pksrec.scanRate = 0.0f;
     1042    } else {
     1043      pksrec.scanRate(0)  = delayDir.column(1)(0);
     1044      pksrec.scanRate(1)  = delayDir.column(1)(1);
     1045    }
     1046  }
    8271047  // caluculate azimuth and elevation
    8281048  // first, get the reference frame
     1049 /**
    8291050  MVPosition mvpos(antennaCols.position()(0));
    8301051  MPosition mp(mvpos);
     
    8331054  MEpoch me(mvt);
    8341055  MeasFrame frame(mp, me);
     1056  **/
    8351057  //
    8361058  ROMSFieldColumns fldCols(cPKSMS.field());
    8371059  Vector<MDirection> vmd(1);
    838   MDirection md;
     1060  //MDirection md;
    8391061  fldCols.delayDirMeasCol().get(fieldId,vmd);
    8401062  md = vmd[0];
     
    8471069                            )().getAngle("rad").getValue();
    8481070  //cerr<<"azel="<<azel<<endl;
    849   azimuth = azel[0];
    850   elevation = azel[1];
     1071  pksrec.azimuth = azel[0];
     1072  pksrec.elevation = azel[1];
    8511073
    8521074  // Get Tsys assuming that entries in the SYSCAL table match the main table.
     
    8581080  }
    8591081  if (cHaveTsys) {
    860     cTsysCol.get(cIdx, tsys, True);
     1082    cTsysCol.get(cIdx, pksrec.tsys, True);
    8611083  } else {
    8621084    Int numReceptor;
    8631085    cNumReceptorCol.get(0, numReceptor);
    864     tsys.resize(numReceptor);
    865     tsys = 1.0f;
    866   }
    867   cSigmaCol.get(cIdx, sigma, True);
     1086    pksrec.tsys.resize(numReceptor);
     1087    pksrec.tsys = 1.0f;
     1088  }
     1089  cSigmaCol.get(cIdx, pksrec.sigma, True);
    8681090
    8691091  //get Tcal if available
     
    8751097    if (nTcalColRow > 0) { 
    8761098    // find tcal match with the data with the data time stamp
    877       Double mjds = mjd*(24*3600);
     1099      Double mjds = pksrec.mjd*(24*3600);
    8781100      Double dtcalTime;
    879       if ( mjd > lastmjd || cIdx==0 ) {
     1101      if ( pksrec.mjd > lastmjd || cIdx==0 ) {
    8801102        //Table tmptab = cSysCalTab(near(cSysCalTab.col("TIME"),mjds));
    8811103        tmptab = cSysCalTab(near(cSysCalTab.col("TIME"),mjds), nrws);
     
    8981120      ROScalarColumn<Double> tcalTimeCol(tmptab2, "TIME");
    8991121      if (syscalrow==0) {
    900         cerr<<"Cannot find any matching Tcal at/near the data timestamp."
    901            << " Set Tcal=0.0"<<endl;
     1122        os << LogIO::NORMAL
     1123           <<"Cannot find any matching Tcal at/near the data timestamp."
     1124           << " Set Tcal=0.0" << LogIO::POST ;
    9021125      } else {
    903         tcalCol.get(0, tcal);
     1126        tcalCol.get(0, pksrec.tcal);
    9041127        tcalTimeCol.get(0,dtcalTime);
    905         tcalTime = MVTime(dtcalTime/(24*3600)).string(MVTime::YMD);
     1128        pksrec.tcalTime = MVTime(dtcalTime/(24*3600)).string(MVTime::YMD);
    9061129        //DEBUG
    9071130        //cerr<<"cIdx:"<<cIdx<<" tcal="<<tcal<<" tcalTime="<<tcalTime<<endl;
     
    9101133      }
    9111134    }
    912     lastmjd = mjd;
     1135    lastmjd = pksrec.mjd;
    9131136  }
    9141137
    9151138  // Calibration factors (if available).
    916   calFctr.resize(cNPol(iIF));
     1139  pksrec.calFctr.resize(cNPol(iIF));
    9171140  if (cHaveCalFctr) {
    918     cCalFctrCol.get(cIdx, calFctr);
     1141    cCalFctrCol.get(cIdx, pksrec.calFctr);
    9191142  } else {
    920     calFctr = 0.0f;
     1143    pksrec.calFctr = 0.0f;
    9211144  }
    9221145
    9231146  // Baseline parameters (if available).
    9241147  if (cHaveBaseLin) {
    925     baseLin.resize(2,cNPol(iIF));
    926     cBaseLinCol.get(cIdx, baseLin);
    927 
    928     baseSub.resize(9,cNPol(iIF));
    929     cBaseSubCol.get(cIdx, baseSub);
     1148    pksrec.baseLin.resize(2,cNPol(iIF));
     1149    cBaseLinCol.get(cIdx, pksrec.baseLin);
     1150
     1151    pksrec.baseSub.resize(24,cNPol(iIF));
     1152    cBaseSubCol.get(cIdx, pksrec.baseSub);
    9301153
    9311154  } else {
    932     baseLin.resize(0,0);
    933     baseSub.resize(0,0);
    934   }
     1155    pksrec.baseLin.resize(0,0);
     1156    pksrec.baseSub.resize(0,0);
     1157  }
     1158
     1159
    9351160  // Get spectral data.
    9361161  if (cGetSpectra) {
     
    9601185    // Transpose spectra.
    9611186    Int nPol = tmpData.nrow();
    962     spectra.resize(nChan, nPol);
    963     flagged.resize(nChan, nPol);
     1187    pksrec.spectra.resize(nChan, nPol);
     1188    pksrec.flagged.resize(nChan, nPol);
    9641189    if (cEndChan(iIF) >= cStartChan(iIF)) {
    9651190      // Simple transposition.
    9661191      for (Int ipol = 0; ipol < nPol; ipol++) {
    9671192        for (Int ichan = 0; ichan < nChan; ichan++) {
    968           spectra(ichan,ipol) = tmpData(ipol,ichan);
    969           flagged(ichan,ipol) = tmpFlag(ipol,ichan);
     1193          pksrec.spectra(ichan,ipol) = tmpData(ipol,ichan);
     1194          pksrec.flagged(ichan,ipol) = tmpFlag(ipol,ichan);
    9701195        }
    9711196      }
     
    9761201      for (Int ipol = 0; ipol < nPol; ipol++) {
    9771202        for (Int ichan = 0; ichan < nChan; ichan++, jchan--) {
    978           spectra(ichan,ipol) = tmpData(ipol,jchan);
    979           flagged(ichan,ipol) = tmpFlag(ipol,jchan);
     1203          pksrec.spectra(ichan,ipol) = tmpData(ipol,jchan);
     1204          pksrec.flagged(ichan,ipol) = tmpFlag(ipol,jchan);
    9801205        }
    9811206      }
    9821207    }
     1208
     1209    // Row-based flagging info. (True:1, False:0)
     1210    pksrec.flagrow = (cFlagRowCol(cIdx) ? 1 : 0);
    9831211  }
    9841212
     
    9891217
    9901218    if (cHaveXCalFctr) {
    991       cXCalFctrCol.get(cIdx, xCalFctr);
     1219      cXCalFctrCol.get(cIdx, pksrec.xCalFctr);
    9921220    } else {
    993       xCalFctr = Complex(0.0f, 0.0f);
    994     }
    995 
    996     if(!cATF) {
    997       cDataCol.get(cIdx, xPol, True);
     1221      pksrec.xCalFctr = Complex(0.0f, 0.0f);
     1222    }
     1223
     1224    if(!cALMA) {
     1225      cDataCol.get(cIdx, pksrec.xPol, True);
    9981226
    9991227      if (cEndChan(iIF) < cStartChan(iIF)) {
     
    10011229        Int jchan = nChan - 1;
    10021230        for (Int ichan = 0; ichan < nChan/2; ichan++, jchan--) {
    1003           ctmp = xPol(ichan);
    1004           xPol(ichan) = xPol(jchan);
    1005           xPol(jchan) = ctmp;
     1231          ctmp = pksrec.xPol(ichan);
     1232          pksrec.xPol(ichan) = pksrec.xPol(jchan);
     1233          pksrec.xPol(jchan) = ctmp;
    10061234        }
    10071235      }
     
    10971325    cBaseLinCol.get(cIdx, baseLin);
    10981326
    1099     baseSub.resize(9,cNPol(iIF));
     1327    baseSub.resize(24,cNPol(iIF));
    11001328    cBaseSubCol.get(cIdx, baseSub);
    11011329
     
    11581386  cMSopen = False;
    11591387}
     1388
     1389//-------------------------------------------------------- PKSMS2reader::splitAntenanSelectionString
     1390
     1391// split antenna selection string
     1392// delimiter is ','
     1393
     1394Vector<String> PKSMS2reader::splitAntennaSelectionString( const String s )
     1395{
     1396  Char delim = ',' ;
     1397  Int n = s.freq( delim ) + 1 ;
     1398  Vector<String> antlist ;
     1399  string sl[n] ;
     1400  Int numSubstr = split( s, sl, n, "," );
     1401  antlist.resize( numSubstr ) ;
     1402  for ( Int i = 0 ; i < numSubstr ; i++ ) {
     1403    antlist[i] = String( sl[i] ) ;
     1404    antlist[i].trim() ;
     1405  }
     1406  //cerr << "antlist = " << antlist << endl ;
     1407  return antlist ;
     1408}
     1409
     1410//-------------------------------------------------------- PKSMS2reader::setupAntennaList
     1411
     1412// Fill cAntenna and cAntId
     1413
     1414void PKSMS2reader::setupAntennaList( const String s )
     1415{
     1416  LogIO os( LogOrigin( "PKSMS2reader", "setupAntennaList()", WHERE ) ) ;
     1417  //cerr << "antenna specification: " << s << endl ;
     1418  ROMSAntennaColumns antennaCols(cPKSMS.antenna());
     1419  ROScalarColumn<String> antNames = antennaCols.name();
     1420  Int nrow = antNames.nrow() ;
     1421  Vector<String> antlist = splitAntennaSelectionString( s ) ;
     1422  Int len = antlist.size() ;
     1423  Vector<Int> AntId( len ) ;
     1424  Regex re( "[0-9]+" ) ;
     1425  for ( Int i = 0 ; i < len ; i++ ) {
     1426    if ( antlist[i].matches( re ) ) {
     1427      AntId[i] = atoi( antlist[i].c_str() ) ;
     1428      if ( AntId[i] >= nrow ) {
     1429        os << LogIO::SEVERE << "Antenna index out of range: " << AntId[i] << LogIO::EXCEPTION ;
     1430      }
     1431    }
     1432    else {
     1433      AntId[i] = -1 ;
     1434      for ( uInt j = 0 ; j < antNames.nrow() ; j++ ) {
     1435        if ( antlist[i] == antNames(j) ) {
     1436          AntId[i] = j ;
     1437          break ;
     1438        }
     1439      }
     1440      if ( AntId[i] == -1 ) {
     1441        os << LogIO::SEVERE << "Specified antenna name not found: " << antlist[i] << LogIO::EXCEPTION ;
     1442      }
     1443    }
     1444  }
     1445  //cerr << "AntId = " << AntId << endl ;
     1446  vector<Int> uniqId ;
     1447  uniqId.push_back( AntId(0) ) ;
     1448  for ( uInt i = 1 ; i < AntId.size() ; i++ ) {
     1449    if ( count(uniqId.begin(),uniqId.end(),AntId[i]) == 0 ) {
     1450      uniqId.push_back( AntId[i] ) ;
     1451    }
     1452  }
     1453  Vector<Int> newAntId( uniqId ) ;
     1454  cAntId.assign( newAntId ) ;
     1455  //cerr << "cAntId = " << cAntId << endl ;
     1456}
  • branches/alma/external/atnf/PKSIO/PKSMS2reader.h

    r1453 r1757  
    22//# PKSMS2reader.h: Class to read Parkes Multibeam data from a v2 MS.
    33//#---------------------------------------------------------------------------
    4 //# Copyright (C) 2000-2006
    5 //# Associated Universities, Inc. Washington DC, USA.
    6 //#
    7 //# This library is free software; you can redistribute it and/or modify it
    8 //# under the terms of the GNU Library General Public License as published by
    9 //# the Free Software Foundation; either version 2 of the License, or (at your
    10 //# option) any later version.
    11 //#
    12 //# This library is distributed in the hope that it will be useful, but WITHOUT
     4//# livedata - processing pipeline for single-dish, multibeam spectral data.
     5//# Copyright (C) 2000-2009, Australia Telescope National Facility, CSIRO
     6//#
     7//# This file is part of livedata.
     8//#
     9//# livedata is free software: you can redistribute it and/or modify it under
     10//# the terms of the GNU General Public License as published by the Free
     11//# Software Foundation, either version 3 of the License, or (at your option)
     12//# any later version.
     13//#
     14//# livedata is distributed in the hope that it will be useful, but WITHOUT
    1315//# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    14 //# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Library General Public
    15 //# License for more details.
    16 //#
    17 //# You should have received a copy of the GNU Library General Public License
    18 //# along with this library; if not, write to the Free Software Foundation,
    19 //# Inc., 675 Massachusetts Ave, Cambridge, MA 02139, USA.
    20 //#
    21 //# Correspondence concerning AIPS++ should be addressed as follows:
    22 //#        Internet email: aips2-request@nrao.edu.
    23 //#        Postal address: AIPS++ Project Office
    24 //#                        National Radio Astronomy Observatory
    25 //#                        520 Edgemont Road
    26 //#                        Charlottesville, VA 22903-2475 USA
    27 //#
    28 //# $Id$
     16//# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
     17//# more details.
     18//#
     19//# You should have received a copy of the GNU General Public License along
     20//# with livedata.  If not, see <http://www.gnu.org/licenses/>.
     21//#
     22//# Correspondence concerning livedata may be directed to:
     23//#        Internet email: mcalabre@atnf.csiro.au
     24//#        Postal address: Dr. Mark Calabretta
     25//#                        Australia Telescope National Facility, CSIRO
     26//#                        PO Box 76
     27//#                        Epping NSW 1710
     28//#                        AUSTRALIA
     29//#
     30//# http://www.atnf.csiro.au/computing/software/livedata.html
     31//# $Id: PKSMS2reader.h,v 19.18 2009-09-29 07:33:38 cal103 Exp $
    2932//#---------------------------------------------------------------------------
    3033//# Original: 2000/08/03, Mark Calabretta, ATNF
     
    3538
    3639#include <atnf/PKSIO/PKSreader.h>
     40#include <atnf/PKSIO/PKSrecord.h>
    3741
    3842#include <casa/aips.h>
     
    4650#include <tables/Tables/ScalarColumn.h>
    4751
     52#include <casa/namespace.h>
     53
    4854// <summary>
    4955// Class to read Parkes Multibeam data from a v2 MS.
    5056// </summary>
    51 
    52 #include <casa/namespace.h>
    5357
    5458class PKSMS2reader : public PKSreader
     
    6468    virtual Int open(
    6569        const String msName,
     70        const String antenna,
    6671        Vector<Bool> &beams,
    6772        Vector<Bool> &IFs,
     
    7984        Vector<Double> &antPosition,
    8085        String &obsMode,
     86        String &bunit,
    8187        Float  &equinox,
    82         String &freqRef,
     88        //String &freqRef,
     89        String &dopplerFrame,
    8390        Double &mjd,
    8491        Double &refFreq,
    85         Double &bandwidth,
    86         String &fluxunit);
     92        Double &bandwidth);
    8793
    8894    // Get frequency parameters for each IF.
     
    101107        const Bool getSpectra = True,
    102108        const Bool getXPol    = False,
    103         const Bool getFeedPos = False);
     109        const Bool getFeedPos = False,
     110        const Bool getPointing = False,
     111        const Int  coordSys   = 0);
     112
    104113
    105114    // Find the range of the data selected in time and position.
     
    111120
    112121    // Read the next data record.
     122/**
    113123    virtual Int read(
    114124        Int             &scanNo,
     
    153163        Complex         &xCalFctr,
    154164        Vector<Complex> &xPol);
     165**/
     166    virtual Int read(PKSrecord &pksrec);
     167
    155168
    156169    // Read the next data record, just the basics.
     
    168181
    169182  private:
     183    Vector<String> splitAntennaSelectionString( const String s );
     184    void setupAntennaList( const String s ) ;
     185
    170186    Bool   cHaveBaseLin, cHaveCalFctr, cHaveSrcVel, cHaveTsys, cHaveXCalFctr,
    171            cMSopen, cHaveTcal, cHaveDataCol, cATF, cHaveSysCal, cHaveCorrectedDataCol;
     187           cMSopen, cHaveTcal, cHaveDataCol, cALMA, cHaveSysCal, cHaveCorrectedDataCol;
    172188    Int    cCycleNo, cIdx, cNRow, cScanNo;
    173189    Double cTime, lastmjd;
     
    175191    Vector<Bool>   cBeams, cIFs;
    176192    Vector<Slicer> cDataSel;
     193    String         cDirRef, cTelName;
    177194    MeasurementSet cPKSMS;
    178195    Table          cSysCalTab, tmptab, tmptab2;
     196
     197    //Vector<String> cAntenna;
     198    Vector<Int> cAntId;
    179199
    180200    ROScalarColumn<Int>     cScanNoCol;
     
    197217    ROScalarColumn<Int>     cSpWinIdCol;
    198218    ROArrayColumn<Double>   cChanFreqCol;
     219    ROScalarColumn<Double>   cTotBWCol;
    199220    ROScalarColumn<Double>  cWeatherTimeCol;
    200221    ROScalarColumn<Float>   cTemperatureCol;
     
    204225    ROScalarColumn<Int>     cBeamNoCol;
    205226    ROArrayColumn<Double>   cPointingCol;
     227    ROScalarColumn<Double>  cPointingTimeCol;
    206228    ROArrayColumn<Float>    cTsysCol;
    207229    ROArrayColumn<Float>    cSigmaCol;
     
    211233    ROArrayColumn<Float>    cFloatDataCol;
    212234    ROArrayColumn<Bool>     cFlagCol;
     235    ROScalarColumn<Bool>    cFlagRowCol;
    213236    ROScalarColumn<Complex> cXCalFctrCol;
    214237    ROArrayColumn<Complex>  cDataCol;
  • branches/alma/external/atnf/PKSIO/PKSMS2writer.cc

    r1453 r1757  
    22//# PKSMS2writer.cc: Class to write Parkes multibeam data to a measurementset.
    33//#---------------------------------------------------------------------------
    4 //# Copyright (C) 2000-2006
    5 //# Associated Universities, Inc. Washington DC, USA.
     4//# livedata - processing pipeline for single-dish, multibeam spectral data.
     5//# Copyright (C) 2000-2009, Australia Telescope National Facility, CSIRO
    66//#
    7 //# This library is free software; you can redistribute it and/or modify it
    8 //# under the terms of the GNU Library General Public License as published by
    9 //# the Free Software Foundation; either version 2 of the License, or (at your
    10 //# option) any later version.
     7//# This file is part of livedata.
    118//#
    12 //# This library is distributed in the hope that it will be useful, but
    13 //# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
    14 //# or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Library General Public
    15 //# License for more details.
     9//# livedata is free software: you can redistribute it and/or modify it under
     10//# the terms of the GNU General Public License as published by the Free
     11//# Software Foundation, either version 3 of the License, or (at your option)
     12//# any later version.
    1613//#
    17 //# You should have received a copy of the GNU Library General Public License
    18 //# along with this library; if not, write to the Free Software Foundation,
    19 //# Inc., 675 Massachusetts Ave, Cambridge, MA 02139, USA.
     14//# livedata is distributed in the hope that it will be useful, but WITHOUT
     15//# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
     16//# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
     17//# more details.
    2018//#
    21 //# Correspondence concerning AIPS++ should be addressed as follows:
    22 //#        Internet email: aips2-request@nrao.edu.
    23 //#        Postal address: AIPS++ Project Office
    24 //#                        National Radio Astronomy Observatory
    25 //#                        520 Edgemont Road
    26 //#                        Charlottesville, VA 22903-2475 USA
     19//# You should have received a copy of the GNU General Public License along
     20//# with livedata.  If not, see <http://www.gnu.org/licenses/>.
    2721//#
    28 //# $Id: PKSMS2writer.cc,v 19.11 2006/11/06 22:25:22 mmarquar Exp $
     22//# Correspondence concerning livedata may be directed to:
     23//#        Internet email: mcalabre@atnf.csiro.au
     24//#        Postal address: Dr. Mark Calabretta
     25//#                        Australia Telescope National Facility, CSIRO
     26//#                        PO Box 76
     27//#                        Epping NSW 1710
     28//#                        AUSTRALIA
     29//#
     30//# http://www.atnf.csiro.au/computing/software/livedata.html
     31//# $Id: PKSMS2writer.cc,v 19.16 2009-09-29 07:33:38 cal103 Exp $
    2932//#---------------------------------------------------------------------------
    3033
     34#include <atnf/PKSIO/PKSrecord.h>
    3135#include <atnf/PKSIO/PKSMS2writer.h>
    3236
     
    4953#include <tables/Tables/TiledShapeStMan.h>
    5054
     55// Class name
     56const string className = "PKSMS2writer" ;
     57
    5158//------------------------------------------------- PKSMS2writer::PKSMS2writer
    5259
     
    5562PKSMS2writer::PKSMS2writer()
    5663{
     64  cPKSMS = 0x0;
    5765}
    5866
     
    7785        const Vector<Double> antPosition,
    7886        const String obsMode,
     87        const String bunit,
    7988        const Float  equinox,
    8089        const String dopplerFrame,
     
    8291        const Vector<uInt> nPol,
    8392        const Vector<Bool> haveXPol,
    84         const Bool   haveBase,
    85         const String fluxUnit)
    86 {
     93        const Bool   haveBase)
     94{
     95  const string methodName = "create()" ;
     96  LogIO os( LogOrigin( className, methodName, WHERE ) ) ;
     97
     98  if (cPKSMS) {
     99    os << LogIO::SEVERE << "Output MS already open, close it first." << LogIO::POST ;
     100    return 1;
     101  }
     102
    87103  // Open a MS table.
    88104  TableDesc pksDesc = MS::requiredTableDesc();
     
    93109
    94110  Int maxNPol = max(cNPol);
    95   cGBT = cAPEX = cSMT = cALMA = False;
    96 
     111  cGBT = cAPEX = cSMT = cALMA = cATF = False;
     112
     113  String telName = antName;
    97114  // check if it is GBT data
    98115  if (antName.contains("GBT")) {
     
    108125    cALMA = True;
    109126  }
     127  else if (antName.contains("ATF")) {
     128    cATF = True;
     129    telName="ATF";
     130  }
    110131 
    111 
    112    
    113   //cGBT = antName.contains("GBT");
    114   //cAPEX = antName.contains("APEX");
    115   //cSMT = antName.contains("HHT");
    116   //cALMA = antName.contains("ALMA");
    117 
    118132  // Add the non-standard CALFCTR column.
    119133  pksDesc.addColumn(ArrayColumnDesc<Float>("CALFCTR", "Calibration factors",
     
    125139  //              define("UNIT", String("Jy"));
    126140  pksDesc.rwColumnDesc(MS::columnName(MS::FLOAT_DATA)).rwKeywordSet().
    127                 define("UNIT", fluxUnit);
     141                define("UNIT", bunit);
    128142  pksDesc.rwColumnDesc(MS::columnName(MS::FLOAT_DATA)).rwKeywordSet().
    129143                define("MEASURE_TYPE", "");
     
    134148                IPosition(2,2,maxNPol), ColumnDesc::Direct));
    135149    pksDesc.addColumn(ArrayColumnDesc<Float>("BASESUB", "Baseline subtracted",
    136                 IPosition(2,9,maxNPol), ColumnDesc::Direct));
     150                IPosition(2,24,maxNPol), ColumnDesc::Direct));
    137151  }
    138152
     
    147161    //            define("UNIT", "Jy");
    148162    pksDesc.rwColumnDesc(MS::columnName(MS::DATA)).rwKeywordSet().
    149                 define("UNIT", fluxUnit);
     163                define("UNIT", bunit);
    150164    pksDesc.rwColumnDesc(MS::columnName(MS::DATA)).rwKeywordSet().
    151165                define("MEASURE_TYPE", "");
     
    387401  addFeedEntry();
    388402  //addObservationEntry(observer, project);
    389   addObservationEntry(observer, project, antName);
     403  addObservationEntry(observer, project, telName);
    390404  addProcessorEntry();
    391405
     
    397411// Write the next data record.
    398412
     413/**
    399414Int PKSMS2writer::write(
    400415        const Int             scanNo,
     
    438453        const Matrix<Float>   &spectra,
    439454        const Matrix<uChar>   &flagged,
     455        const uInt            flagrow,
    440456        const Complex         xCalFctr,
    441457        const Vector<Complex> &xPol)
     458**/
     459Int PKSMS2writer::write(
     460        const PKSrecord &pksrec)
    442461{
    443462  // Extend the time range in the OBSERVATION subtable.
    444463  Vector<Double> timerange(2);
    445464  cObservationCols->timeRange().get(0, timerange);
    446   Double time = mjd*86400.0;
     465  Double time = pksrec.mjd*86400.0;
    447466  if (timerange(0) == 0.0) {
    448467    timerange(0) = time;
     
    451470  cObservationCols->timeRange().put(0, timerange);
    452471
    453   Int iIF = IFno - 1;
     472  Int iIF = pksrec.IFno - 1;
    454473  Int nChan = cNChan(iIF);
    455474  Int nPol  = cNPol(iIF);
     
    457476  // IFno is the 1-relative row number in the DATA_DESCRIPTION,
    458477  // SPECTRAL_WINDOW, and POLARIZATION subtables.
    459   if (Int(cDataDescription.nrow()) < IFno) {
     478  if (Int(cDataDescription.nrow()) < pksrec.IFno) {
    460479    // Add a new entry to each subtable.
    461     addDataDescriptionEntry(IFno);
    462     addSpectralWindowEntry(IFno, nChan, refFreq, bandwidth, freqInc);
    463     addPolarizationEntry(IFno, nPol);
     480    addDataDescriptionEntry(pksrec.IFno);
     481    addSpectralWindowEntry(pksrec.IFno, nChan, pksrec.refFreq,
     482      pksrec.bandwidth, pksrec.freqInc);
     483    addPolarizationEntry(pksrec.IFno, nPol);
    464484  }
    465485
    466486  // Find or add the source to the SOURCE subtable.
    467   Int srcId = addSourceEntry(srcName, srcDir, srcPM, restFreq, srcVel);
     487  Int srcId = addSourceEntry(pksrec.srcName, pksrec.srcDir, pksrec.srcPM,
     488    pksrec.restFreq, pksrec.srcVel);
    468489
    469490  // Find or add the obsMode to the STATE subtable.
    470   Int stateId = addStateEntry(obsMode);
     491  Int stateId = addStateEntry(pksrec.obsType);
    471492
    472493  // FIELD subtable.
    473   Int fieldId = addFieldEntry(fieldName, time, direction, scanRate, srcId);
     494  //Vector<Double> scanRate(2);
     495  //scanRate(0) = pksrec.scanRate(0);
     496  //scanRate(1) = pksrec.scanRate(1);
     497  Int fieldId = addFieldEntry(pksrec.fieldName, time, pksrec.direction,
     498    pksrec.scanRate, srcId);
    474499
    475500  // POINTING subtable.
    476   addPointingEntry(time, interval, fieldName, direction, scanRate);
     501  addPointingEntry(time, pksrec.interval, pksrec.fieldName, pksrec.direction,
     502    pksrec.scanRate);
    477503
    478504  // SYSCAL subtable.
    479   addSysCalEntry(beamNo, iIF, time, interval, tcal, tsys, nPol);
    480 
     505  addSysCalEntry(pksrec.beamNo, iIF, time, pksrec.interval, pksrec.tcal,
     506    pksrec.tsys, nPol);
    481507
    482508  // Handle weather information.
     
    484510  Int nWeather = wTime.nrow();
    485511  if (nWeather == 0 || time > wTime(nWeather-1)) {
    486     addWeatherEntry(time, interval, pressure, humidity, temperature);
     512    addWeatherEntry(time, pksrec.interval, pksrec.pressure, pksrec.humidity,
     513      pksrec.temperature);
    487514  }
    488515
     
    496523  cMSCols->antenna1().put(irow, 0);
    497524  cMSCols->antenna2().put(irow, 0);
    498   cMSCols->feed1().put(irow, beamNo-1);
    499   cMSCols->feed2().put(irow, beamNo-1);
     525  cMSCols->feed1().put(irow, pksrec.beamNo-1);
     526  cMSCols->feed2().put(irow, pksrec.beamNo-1);
    500527  cMSCols->dataDescId().put(irow, iIF);
    501528  cMSCols->processorId().put(irow, 0);
     
    503530
    504531  // Non-key attributes.
    505   cMSCols->interval().put(irow, interval);
    506   cMSCols->exposure().put(irow, interval);
     532  cMSCols->interval().put(irow, pksrec.interval);
     533  cMSCols->exposure().put(irow, pksrec.interval);
    507534  cMSCols->timeCentroid().put(irow, time);
    508   cMSCols->scanNumber().put(irow, scanNo);
     535  cMSCols->scanNumber().put(irow, pksrec.scanNo);
    509536  cMSCols->arrayId().put(irow, 0);
    510537  cMSCols->observationId().put(irow, 0);
     
    516543  // Baseline fit parameters.
    517544  if (cHaveBase) {
    518     cBaseLinCol->put(irow, baseLin);
    519 
    520     if (baseSub.nrow() == 9) {
    521       cBaseSubCol->put(irow, baseSub);
     545    cBaseLinCol->put(irow, pksrec.baseLin);
     546
     547    if (pksrec.baseSub.nrow() == 24) {
     548      cBaseSubCol->put(irow, pksrec.baseSub);
    522549
    523550    } else {
    524       Matrix<Float> tmp(9, 2, 0.0f);
     551      Matrix<Float> tmp(24, 2, 0.0f);
    525552      for (Int ipol = 0; ipol < nPol; ipol++) {
    526         for (uInt j = 0; j < baseSub.nrow(); j++) {
    527           tmp(j,ipol) = baseSub(j,ipol);
     553        for (uInt j = 0; j < pksrec.baseSub.nrow(); j++) {
     554          tmp(j,ipol) = pksrec.baseSub(j,ipol);
    528555        }
    529556      }
     
    531558    }
    532559  }
     560
    533561  // Transpose spectra.
    534562  Matrix<Float> tmpData(nPol, nChan);
     
    536564  for (Int ipol = 0; ipol < nPol; ipol++) {
    537565    for (Int ichan = 0; ichan < nChan; ichan++) {
    538       tmpData(ipol,ichan) = spectra(ichan,ipol);
    539       tmpFlag(ipol,ichan) = flagged(ichan,ipol);
     566      tmpData(ipol,ichan) = pksrec.spectra(ichan,ipol);
     567      tmpFlag(ipol,ichan) = pksrec.flagged(ichan,ipol);
    540568    }
    541569  }
    542   cCalFctrCol->put(irow, calFctr);
     570
     571  cCalFctrCol->put(irow, pksrec.calFctr);
    543572  cMSCols->floatData().put(irow, tmpData);
    544573  cMSCols->flag().put(irow, tmpFlag);
     
    546575  // Cross-polarization spectra.
    547576  if (cHaveXPol(iIF)) {
    548     cXCalFctrCol->put(irow, xCalFctr);
    549     cMSCols->data().put(irow, xPol);
    550   }
    551 
    552   cMSCols->sigma().put(irow, sigma);
     577    cXCalFctrCol->put(irow, pksrec.xCalFctr);
     578    cMSCols->data().put(irow, pksrec.xPol);
     579  }
     580
     581  cMSCols->sigma().put(irow, pksrec.sigma);
    553582
    554583  //Vector<Float> weight(1, 1.0f);
     
    563592  //cMSCols->flag().put(irow, flags.xyPlane(0));
    564593  cMSCols->flagCategory().put(irow, flags);
    565   cMSCols->flagRow().put(irow, False);
     594  // Row-based flagging info. (True:>0, False:0)
     595  cMSCols->flagRow().put(irow, (pksrec.flagrow > 0));
     596
    566597
    567598  return 0;
     
    601632    delete cXCalFctrCol; cXCalFctrCol=0;
    602633  }
    603  
     634
    604635  // Release all subtables.
    605636  cAntenna         = MSAntenna();
     
    620651  cWeather         = MSWeather();
    621652  // Release the main table.
    622   delete cPKSMS; cPKSMS=0;
     653  delete cPKSMS;
     654  cPKSMS=0x0;
    623655}
    624656
     
    649681  }
    650682  else if (cALMA) {
     683    // this needs to be changed in future...
    651684    cAntennaCols->station().put(n, "CHAJNANTOR");
     685    cAntennaCols->dishDiameter().put(n, 12.0);
     686  }
     687  else if (cATF) {
     688    //pad name for the antenna is static...
     689    String stname="unknown";
     690    if (antName.contains("DV")) {
     691       stname="PAD001";
     692    }
     693    if (antName.contains("DA")) {
     694       stname="PAD002";
     695    }
     696    cAntennaCols->station().put(n, stname);
    652697    cAntennaCols->dishDiameter().put(n, 12.0);
    653698  }
     
    10951140
    10961141Int PKSMS2writer::addStateEntry(
    1097         const String obsMode)
     1142        const String obsType)
    10981143{
    10991144  // Look for an entry in the STATE subtable.
    11001145  for (uInt n = 0; n < cStateCols->nrow(); n++) {
    1101     if (cStateCols->obsMode()(n) == obsMode) {
     1146    if (cStateCols->obsMode()(n) == obsType) {
    11021147      return n;
    11031148    }
     
    11091154
    11101155  // Data.
    1111   if (obsMode.contains("RF")) {
     1156  if (obsType.contains("RF")) {
    11121157    cStateCols->sig().put(n, False);
    11131158    cStateCols->ref().put(n, True);
    1114   } else if (!obsMode.contains("PA")) {
     1159  } else if (!obsType.contains("PA")) {
    11151160    // Signal and reference are both false for "paddle" data.
    11161161    cStateCols->sig().put(n, True);
     
    11211166  cStateCols->cal().put(n, 0.0);
    11221167  cStateCols->subScan().put(n, 0);
    1123   cStateCols->obsMode().put(n, obsMode);
     1168  cStateCols->obsMode().put(n, obsType);
    11241169
    11251170  // Flags.
  • branches/alma/external/atnf/PKSIO/PKSMS2writer.h

    r1453 r1757  
    22//# PKSMS2writer.h: Class to write Parkes Multibeam data to a measurementset.
    33//#---------------------------------------------------------------------------
    4 //# Copyright (C) 2000-2006
    5 //# Associated Universities, Inc. Washington DC, USA.
    6 //#
    7 //# This library is free software; you can redistribute it and/or modify it
    8 //# under the terms of the GNU Library General Public License as published by
    9 //# the Free Software Foundation; either version 2 of the License, or (at your
    10 //# option) any later version.
    11 //#
    12 //# This library is distributed in the hope that it will be useful, but WITHOUT
     4//# livedata - processing pipeline for single-dish, multibeam spectral data.
     5//# Copyright (C) 2000-2009, Australia Telescope National Facility, CSIRO
     6//#
     7//# This file is part of livedata.
     8//#
     9//# livedata is free software: you can redistribute it and/or modify it under
     10//# the terms of the GNU General Public License as published by the Free
     11//# Software Foundation, either version 3 of the License, or (at your option)
     12//# any later version.
     13//#
     14//# livedata is distributed in the hope that it will be useful, but WITHOUT
    1315//# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    14 //# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Library General Public
    15 //# License for more details.
    16 //#
    17 //# You should have received a copy of the GNU Library General Public License
    18 //# along with this library; if not, write to the Free Software Foundation,
    19 //# Inc., 675 Massachusetts Ave, Cambridge, MA 02139, USA.
    20 //#
    21 //# Correspondence concerning AIPS++ should be addressed as follows:
    22 //#        Internet email: aips2-request@nrao.edu.
    23 //#        Postal address: AIPS++ Project Office
    24 //#                        National Radio Astronomy Observatory
    25 //#                        520 Edgemont Road
    26 //#                        Charlottesville, VA 22903-2475 USA
    27 //#
    28 //# $Id$
     16//# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
     17//# more details.
     18//#
     19//# You should have received a copy of the GNU General Public License along
     20//# with livedata.  If not, see <http://www.gnu.org/licenses/>.
     21//#
     22//# Correspondence concerning livedata may be directed to:
     23//#        Internet email: mcalabre@atnf.csiro.au
     24//#        Postal address: Dr. Mark Calabretta
     25//#                        Australia Telescope National Facility, CSIRO
     26//#                        PO Box 76
     27//#                        Epping NSW 1710
     28//#                        AUSTRALIA
     29//#
     30//# http://www.atnf.csiro.au/computing/software/livedata.html
     31//# $Id: PKSMS2writer.h,v 19.14 2009-09-29 07:33:38 cal103 Exp $
    2932//#---------------------------------------------------------------------------
    3033
     
    3235#define ATNF_PKSMS2WRITER_H
    3336
     37#include <atnf/PKSIO/PKSrecord.h>
    3438#include <atnf/PKSIO/PKSwriter.h>
    3539
     
    3842#include <casa/Arrays/Vector.h>
    3943#include <casa/BasicSL/Complex.h>
     44#include <casa/BasicSL/String.h>
    4045#include <ms/MeasurementSets/MeasurementSet.h>
    4146#include <ms/MeasurementSets/MSColumns.h>
    42 #include <casa/BasicSL/String.h>
     47
     48#include <casa/namespace.h>
    4349
    4450// <summary>
     
    4652// </summary>
    4753
    48 #include <casa/namespace.h>
    4954class PKSMS2writer : public PKSwriter
    5055{
     
    6469        const Vector<Double> antPosition,
    6570        const String obsMode,
     71        const String bunit,
    6672        const Float  equinox,
    6773        const String dopplerFrame,
     
    6975        const Vector<uInt> nPol,
    7076        const Vector<Bool> haveXPol,
    71         const Bool   haveBase,
    72         const String fluxUnit);
     77        const Bool   haveBase);
    7378
    7479    // Write the next data record.
     80/**
    7581    virtual Int write(
    7682        const Int             scanNo,
     
    114120        const Matrix<Float>   &spectra,
    115121        const Matrix<uChar>   &flagged,
     122        const uInt            flagrow,
    116123        const Complex         xCalFctr,
    117124        const Vector<Complex> &xPol);
     125**/
     126    virtual Int write(
     127        const PKSrecord &pksrec);
    118128
    119129    // Close the MS, flushing all associated Tables.
     
    168178
    169179    // for handling parameters specific to GBT and other telescopes
    170     Bool cGBT;
    171     Bool cSMT;
    172     Bool cAPEX;
    173     Bool cALMA;
     180    Bool cGBT, cSMT, cAPEX, cALMA, cATF;
    174181
    175182    // Add an entry to the ANTENNA subtable.
  • branches/alma/external/atnf/PKSIO/PKSSDwriter.cc

    r1453 r1757  
    22//# PKSSDwriter.cc: Class to write Parkes multibeam data to an SDFITS file.
    33//#---------------------------------------------------------------------------
    4 //# Copyright (C) 2000-2006
    5 //# Associated Universities, Inc. Washington DC, USA.
    6 //#
    7 //# This library is free software; you can redistribute it and/or modify it
    8 //# under the terms of the GNU Library General Public License as published by
    9 //# the Free Software Foundation; either version 2 of the License, or (at your
    10 //# option) any later version.
    11 //#
    12 //# This library is distributed in the hope that it will be useful, but
    13 //# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
    14 //# or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Library General Public
    15 //# License for more details.
    16 //#
    17 //# You should have received a copy of the GNU Library General Public License
    18 //# along with this library; if not, write to the Free Software Foundation,
    19 //# Inc., 675 Massachusetts Ave, Cambridge, MA 02139, USA.
    20 //#
    21 //# Correspondence concerning AIPS++ should be addressed as follows:
    22 //#        Internet email: aips2-request@nrao.edu.
    23 //#        Postal address: AIPS++ Project Office
    24 //#                        National Radio Astronomy Observatory
    25 //#                        520 Edgemont Road
    26 //#                        Charlottesville, VA 22903-2475 USA
    27 //#
    28 //# $Id$
     4//# livedata - processing pipeline for single-dish, multibeam spectral data.
     5//# Copyright (C) 2000-2009, Australia Telescope National Facility, CSIRO
     6//#
     7//# This file is part of livedata.
     8//#
     9//# livedata is free software: you can redistribute it and/or modify it under
     10//# the terms of the GNU General Public License as published by the Free
     11//# Software Foundation, either version 3 of the License, or (at your option)
     12//# any later version.
     13//#
     14//# livedata is distributed in the hope that it will be useful, but WITHOUT
     15//# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
     16//# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
     17//# more details.
     18//#
     19//# You should have received a copy of the GNU General Public License along
     20//# with livedata.  If not, see <http://www.gnu.org/licenses/>.
     21//#
     22//# Correspondence concerning livedata may be directed to:
     23//#        Internet email: mcalabre@atnf.csiro.au
     24//#        Postal address: Dr. Mark Calabretta
     25//#                        Australia Telescope National Facility, CSIRO
     26//#                        PO Box 76
     27//#                        Epping NSW 1710
     28//#                        AUSTRALIA
     29//#
     30//# http://www.atnf.csiro.au/computing/software/livedata.html
     31//# $Id: PKSSDwriter.cc,v 19.17 2009-09-29 07:33:38 cal103 Exp $
    2932//#---------------------------------------------------------------------------
    3033
    31 #include <atnf/PKSIO/PKSMBrecord.h>
     34#include <atnf/PKSIO/MBrecord.h>
    3235#include <atnf/PKSIO/PKSSDwriter.h>
    3336
     37#include <casa/Logging/LogIO.h>
     38
     39#include <casa/stdio.h>
    3440#include <casa/Quanta/MVTime.h>
    3541
     42#include <string>
     43#include <cstring>
     44
     45// Class name
     46const string className = "PKSSDwriter" ;
    3647
    3748//--------------------------------------------------- PKSSDwriter::PKSSDwriter
     
    6374        const Vector<Double> antPosition,
    6475        const String obsMode,
     76        const String bunit,
    6577        const Float  equinox,
    6678        const String dopplerFrame,
     
    6880        const Vector<uInt> nPol,
    6981        const Vector<Bool> haveXPol,
    70         const Bool   haveBase,
    71         const String fluxUnit)
    72 {
     82        const Bool   haveBase)
     83{
     84  const string methodName = "create()" ;
     85  LogIO os( LogOrigin( className, methodName, WHERE ) ) ;
     86
    7387  double antPos[3];
    7488  antPos[0] = antPosition(0);
     
    7892  cNIF = nChan.nelements();
    7993  if (nPol.nelements() != cNIF || haveXPol.nelements() != cNIF) {
    80     cerr << "PKSSDwriter::create: "
    81          << "Inconsistent number of IFs for nChan, nPol, and/or haveXPol."
    82          << endl;
     94    os << LogIO::SEVERE << "Inconsistent number of IFs for nChan, nPol, and/or haveXPol." << LogIO::POST ;
    8395    return 1;
    8496  }
     
    102114  Int status = cSDwriter.create((char *)sdName.chars(),
    103115        (char *)observer.chars(), (char *)project.chars(),
    104         (char *)antName.chars(), antPos, (char *)obsMode.chars(), equinox,
    105         (char *)dopplerFrame.chars(), cNIF,
     116        (char *)antName.chars(), antPos, (char *)obsMode.chars(),
     117        (char *)bunit.chars(), equinox, (char *)dopplerFrame.chars(), cNIF,
    106118        (int *)cNChan.getStorage(deleteIt),
    107119        (int *)cNPol.getStorage(deleteIt),
    108120        (int *)cHaveXPol.getStorage(deleteIt), (int)cHaveBase, 1);
     121  //logMsg(cSDwriter.getMsg());
     122  //cSDwriter.clearMsg();
    109123  if (status) {
    110     cSDwriter.reportError();
    111124    cSDwriter.deleteFile();
    112125    close();
     
    121134
    122135Int PKSSDwriter::write(
    123         const Int             scanNo,
    124         const Int             cycleNo,
    125         const Double          mjd,
    126         const Double          interval,
    127         const String          fieldName,
    128         const String          srcName,
    129         const Vector<Double>  srcDir,
    130         const Vector<Double>  srcPM,
    131         const Double          srcVel,
    132         const String          obsMode,
    133         const Int             IFno,
    134         const Double          refFreq,
    135         const Double          bandwidth,
    136         const Double          freqInc,
    137         //const Double          restFreq,
    138         const Vector<Double>  restFreq,
    139         const Vector<Float>   tcal,
    140         const String          tcalTime,
    141         const Float           azimuth,
    142         const Float           elevation,
    143         const Float           parAngle,
    144         const Float           focusAxi,
    145         const Float           focusTan,
    146         const Float           focusRot,
    147         const Float           temperature,
    148         const Float           pressure,
    149         const Float           humidity,
    150         const Float           windSpeed,
    151         const Float           windAz,
    152         const Int             refBeam,
    153         const Int             beamNo,
    154         const Vector<Double>  direction,
    155         const Vector<Double>  scanRate,
    156         const Vector<Float>   tsys,
    157         const Vector<Float>   sigma,
    158         const Vector<Float>   calFctr,
    159         const Matrix<Float>   baseLin,
    160         const Matrix<Float>   baseSub,
    161         const Matrix<Float>   &spectra,
    162         const Matrix<uChar>   &flagged,
    163         const Complex         xCalFctr,
    164         const Vector<Complex> &xPol)
    165 {
     136        const PKSrecord &pksrec)
     137{
     138  const string methodName = "write()" ;
     139  LogIO os( LogOrigin( className, methodName, WHERE ) ) ;
     140
    166141  // Do basic checks.
     142  Int IFno = pksrec.IFno;
    167143  uInt iIF = IFno - 1;
    168144  if (IFno < 1 || Int(cNIF) < IFno) {
    169     cerr << "PKSDwriter::write: "
    170          << "Invalid IF number " << IFno
    171          << " (maximum " << cNIF << ")." << endl;
     145    os << LogIO::SEVERE
     146       << "Invalid IF number " << IFno
     147       << " (maximum " << cNIF << ")." << LogIO::POST ;
    172148    return 1;
    173149  }
    174150
    175   uInt nChan = spectra.nrow();
     151  uInt nChan = pksrec.spectra.nrow();
    176152  if (nChan != cNChan(iIF)) {
    177     cerr << "PKSDwriter::write: "
    178          << "Wrong number of channels for IF " << IFno << "," << endl
    179          << "                   "
     153    os << LogIO::SEVERE << "Wrong number of channels for IF " << IFno << "," << endl
    180154         << "got " << nChan << " should be " << cNChan(iIF) << "." << endl;
     155    os << LogIO::POST ;
    181156    return 1;
    182157  }
    183158
    184   uInt nPol = spectra.ncolumn();
     159  uInt nPol = pksrec.spectra.ncolumn();
    185160  if (nPol != cNPol(iIF)) {
    186     cerr << "PKSDwriter::write: "
    187          << "Wrong number of polarizations for IF " << IFno << "," << endl
    188          << "                   "
    189          << "got " << nPol << " should be " << cNPol(iIF) << "." << endl;
     161    os << LogIO::SEVERE << "Wrong number of polarizations for IF " << IFno << "," << endl
     162       << "got " << nPol << " should be " << cNPol(iIF) << "." << endl;
     163    os << LogIO::POST ;
    190164    return 1;
    191165  }
    192166
    193   // Extract calendar information from mjd.
    194   MVTime time(mjd);
     167  // Extract calendar information frrom mjd.
     168  MVTime time(pksrec.mjd);
    195169  Int year  = time.year();
    196170  Int month = time.month();
    197171  Int day   = time.monthday();
    198172
    199   // Transfer data to a single-IF PKSMBrecord.
    200   PKSMBrecord mbrec(1);
     173  // Transfer data to a single-IF MBrecord.
     174  MBrecord mbrec(1);
    201175
    202176  // Start with basic beam- and IF-independent bookkeeping information.
    203   mbrec.scanNo  = scanNo;
    204   mbrec.cycleNo = cycleNo;
     177  mbrec.scanNo  = pksrec.scanNo;
     178  mbrec.cycleNo = pksrec.cycleNo;
    205179
    206180  sprintf(mbrec.datobs, "%4.4d-%2.2d-%2.2d", year, month, day);
    207   mbrec.utc      = fmod(mjd, 1.0) * 86400.0;
    208   mbrec.exposure = float(interval);
    209 
    210   strncpy(mbrec.srcName, (char *)srcName.chars(), 17);
    211   mbrec.srcRA    = srcDir(0);
    212   mbrec.srcDec   = srcDir(1);
    213 
    214   //mbrec.restFreq = restFreq;
    215   mbrec.restFreq = restFreq(0);
    216 
    217   strncpy(mbrec.obsType, (char *)obsMode.chars(), 16);
     181  mbrec.utc      = fmod(pksrec.mjd, 1.0) * 86400.0;
     182  mbrec.exposure = float(pksrec.interval);
     183
     184  strncpy(mbrec.srcName, (char *)pksrec.srcName.chars(), 17);
     185  mbrec.srcRA    = pksrec.srcDir(0);
     186  mbrec.srcDec   = pksrec.srcDir(1);
     187  if (pksrec.restFreq.shape()==0) {
     188     mbrec.restFreq = 0;
     189  }
     190  else {
     191     mbrec.restFreq = pksrec.restFreq(0);
     192  }
     193  strncpy(mbrec.obsType, (char *)pksrec.obsType.chars(), 16);
    218194
    219195  // Now beam-dependent parameters.
    220   mbrec.beamNo   = beamNo;
    221   mbrec.ra       = direction(0);
    222   mbrec.dec      = direction(1);
    223   mbrec.raRate   = scanRate(0);
    224   mbrec.decRate  = scanRate(1);
     196  mbrec.beamNo   = pksrec.beamNo;
     197  mbrec.ra       = pksrec.direction(0);
     198  mbrec.dec      = pksrec.direction(1);
     199  mbrec.raRate   = pksrec.scanRate(0);
     200  mbrec.decRate  = pksrec.scanRate(1);
    225201
    226202  // Now IF-dependent parameters.
     
    231207
    232208  mbrec.fqRefPix[0] = (nChan/2) + 1;
    233   mbrec.fqRefVal[0] = refFreq;
    234   mbrec.fqDelt[0]   = freqInc;
     209  mbrec.fqRefVal[0] = pksrec.refFreq;
     210  mbrec.fqDelt[0]   = pksrec.freqInc;
    235211
    236212  // Now the data itself.
    237   for (uInt i = 0; i < tsys.nelements(); i++) {
    238     mbrec.tsys[0][i] = tsys(i);
     213  for (uInt i = 0; i < pksrec.tsys.nelements(); i++) {
     214    mbrec.tsys[0][i] = pksrec.tsys(i);
    239215  }
    240216
    241217  for (uInt ipol = 0; ipol < nPol; ipol++) {
    242     mbrec.calfctr[0][ipol] = calFctr(ipol);
     218    mbrec.calfctr[0][ipol] = pksrec.calFctr(ipol);
    243219  }
    244220
    245221  if (cHaveXPol(iIF)) {
    246     mbrec.xcalfctr[0][0] = xCalFctr.real();
    247     mbrec.xcalfctr[0][1] = xCalFctr.imag();
     222    mbrec.xcalfctr[0][0] = pksrec.xCalFctr.real();
     223    mbrec.xcalfctr[0][1] = pksrec.xCalFctr.imag();
    248224  } else {
    249225    mbrec.xcalfctr[0][0] = 0.0f;
     
    255231
    256232    for (uInt ipol = 0; ipol < nPol; ipol++) {
    257       mbrec.baseLin[0][ipol][0] = baseLin(0,ipol);
    258       mbrec.baseLin[0][ipol][1] = baseLin(1,ipol);
    259 
    260       for (uInt j = 0; j < baseSub.nrow(); j++) {
    261         mbrec.baseSub[0][ipol][j] = baseSub(j,ipol);
     233      mbrec.baseLin[0][ipol][0] = pksrec.baseLin(0,ipol);
     234      mbrec.baseLin[0][ipol][1] = pksrec.baseLin(1,ipol);
     235
     236      for (uInt j = 0; j < pksrec.baseSub.nrow(); j++) {
     237        mbrec.baseSub[0][ipol][j] = pksrec.baseSub(j,ipol);
    262238      }
    263       for (uInt j = baseSub.nrow(); j < 9; j++) {
     239      for (uInt j = pksrec.baseSub.nrow(); j < 24; j++) {
    264240        mbrec.baseSub[0][ipol][j] = 0.0f;
    265241      }
     
    271247
    272248  Bool delSpectra = False;
    273   const Float *specstor = spectra.getStorage(delSpectra);
     249  const Float *specstor = pksrec.spectra.getStorage(delSpectra);
    274250  mbrec.spectra[0] = (float *)specstor;
    275251
    276252  Bool delFlagged = False;
    277   const uChar *flagstor = flagged.getStorage(delFlagged);
     253  const uChar *flagstor = pksrec.flagged.getStorage(delFlagged);
    278254  mbrec.flagged[0] = (unsigned char *)flagstor;
    279255
     
    281257  const Complex *xpolstor;
    282258  if (cHaveXPol(iIF)) {
    283     xpolstor = xPol.getStorage(delXPol);
     259    xpolstor = pksrec.xPol.getStorage(delXPol);
    284260  } else {
    285261    xpolstor = 0;
     
    289265  // Finish off with system calibration parameters.
    290266  mbrec.extraSysCal = 1;
    291   mbrec.refBeam     = refBeam;
    292   for (uInt i = 0; i < tcal.nelements(); i++) {
    293     mbrec.tcal[0][i] = tcal(i);
    294   }
    295   strncpy(mbrec.tcalTime, (char *)tcalTime.chars(), 16);
    296   mbrec.azimuth   = azimuth;
    297   mbrec.elevation = elevation;
    298   mbrec.parAngle  = parAngle;
    299   mbrec.focusAxi  = focusAxi;
    300   mbrec.focusTan  = focusTan;
    301   mbrec.focusRot  = focusRot;
    302   mbrec.temp      = temperature;
    303   mbrec.pressure  = pressure;
    304   mbrec.humidity  = humidity;
    305   mbrec.windSpeed = windSpeed;
    306   mbrec.windAz    = windAz;
     267  mbrec.refBeam     = pksrec.refBeam;
     268  for (uInt i = 0; i < pksrec.tcal.nelements(); i++) {
     269    mbrec.tcal[0][i] = pksrec.tcal(i);
     270  }
     271  strncpy(mbrec.tcalTime, (char *)pksrec.tcalTime.chars(), 16);
     272  mbrec.azimuth   = pksrec.azimuth;
     273  mbrec.elevation = pksrec.elevation;
     274  mbrec.parAngle  = pksrec.parAngle;
     275  mbrec.focusAxi  = pksrec.focusAxi;
     276  mbrec.focusTan  = pksrec.focusTan;
     277  mbrec.focusRot  = pksrec.focusRot;
     278  mbrec.temp      = pksrec.temperature;
     279  mbrec.pressure  = pksrec.pressure;
     280  mbrec.humidity  = pksrec.humidity;
     281  mbrec.windSpeed = pksrec.windSpeed;
     282  mbrec.windAz    = pksrec.windAz;
    307283
    308284  Int status = cSDwriter.write(mbrec);
     285  //logMsg(cSDwriter.getMsg());
     286  //cSDwriter.clearMsg();
    309287  if (status) {
    310     cSDwriter.reportError();
    311288    status = 1;
    312289  }
    313290
    314   spectra.freeStorage(specstor, delSpectra);
    315   flagged.freeStorage(flagstor, delFlagged);
    316   xPol.freeStorage(xpolstor, delXPol);
     291  pksrec.spectra.freeStorage(specstor, delSpectra);
     292  pksrec.flagged.freeStorage(flagstor, delFlagged);
     293  pksrec.xPol.freeStorage(xpolstor, delXPol);
    317294
    318295  return status;
    319296}
    320297
     298//------------------------------------------------------- PKSSDwriter::history
     299
     300// Write a history record.
     301
     302Int PKSSDwriter::history(const String text)
     303{
     304  return cSDwriter.history((char *)text.chars());
     305}
     306
     307Int PKSSDwriter::history(const char *text)
     308{
     309  return cSDwriter.history((char *)text);
     310}
     311
    321312//--------------------------------------------------------- PKSSDwriter::close
    322313
     
    326317{
    327318  cSDwriter.close();
    328 }
     319  //logMsg(cSDwriter.getMsg());
     320  //cSDwriter.clearMsg();
     321}
  • branches/alma/external/atnf/PKSIO/PKSSDwriter.h

    r1453 r1757  
    11//#---------------------------------------------------------------------------
    2 //# PKSSDWriter.h: Class to write Parkes multibeam data to an SDFITS file.
     2//# PKSSDwriter.h: Class to write Parkes multibeam data to an SDFITS file.
    33//#---------------------------------------------------------------------------
    4 //# Copyright (C) 2000-2006
    5 //# Associated Universities, Inc. Washington DC, USA.
     4//# livedata - processing pipeline for single-dish, multibeam spectral data.
     5//# Copyright (C) 2000-2009, Australia Telescope National Facility, CSIRO
    66//#
    7 //# This library is free software; you can redistribute it and/or modify it
    8 //# under the terms of the GNU Library General Public License as published by
    9 //# the Free Software Foundation; either version 2 of the License, or (at your
    10 //# option) any later version.
     7//# This file is part of livedata.
    118//#
    12 //# This library is distributed in the hope that it will be useful, but WITHOUT
     9//# livedata is free software: you can redistribute it and/or modify it under
     10//# the terms of the GNU General Public License as published by the Free
     11//# Software Foundation, either version 3 of the License, or (at your option)
     12//# any later version.
     13//#
     14//# livedata is distributed in the hope that it will be useful, but WITHOUT
    1315//# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    14 //# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Library General Public
    15 //# License for more details.
     16//# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
     17//# more details.
    1618//#
    17 //# You should have received a copy of the GNU Library General Public License
    18 //# along with this library; if not, write to the Free Software Foundation,
    19 //# Inc., 675 Massachusetts Ave, Cambridge, MA 02139, USA.
     19//# You should have received a copy of the GNU General Public License along
     20//# with livedata.  If not, see <http://www.gnu.org/licenses/>.
    2021//#
    21 //# Correspondence concerning AIPS++ should be addressed as follows:
    22 //#        Internet email: aips2-request@nrao.edu.
    23 //#        Postal address: AIPS++ Project Office
    24 //#                        National Radio Astronomy Observatory
    25 //#                        520 Edgemont Road
    26 //#                        Charlottesville, VA 22903-2475 USA
     22//# Correspondence concerning livedata may be directed to:
     23//#        Internet email: mcalabre@atnf.csiro.au
     24//#        Postal address: Dr. Mark Calabretta
     25//#                        Australia Telescope National Facility, CSIRO
     26//#                        PO Box 76
     27//#                        Epping NSW 1710
     28//#                        AUSTRALIA
    2729//#
    28 //# $Id$
     30//# http://www.atnf.csiro.au/computing/software/livedata.html
     31//# $Id: PKSSDwriter.h,v 19.17 2009-09-29 07:33:38 cal103 Exp $
    2932//# Original: 2000/07/21, Mark Calabretta, ATNF
    3033//#---------------------------------------------------------------------------
     
    3437
    3538#include <atnf/PKSIO/PKSwriter.h>
     39#include <atnf/PKSIO/PKSrecord.h>
    3640#include <atnf/PKSIO/SDFITSwriter.h>
    3741
    3842#include <casa/aips.h>
     43#include <casa/stdio.h>
    3944#include <casa/Arrays/Vector.h>
    4045#include <casa/Arrays/Matrix.h>
     
    4247#include <casa/BasicSL/String.h>
    4348
     49#include <casa/namespace.h>
     50
    4451// <summary>
    4552// Class to write Parkes multibeam data to an SDFITS file.
    4653// </summary>
    4754
    48 #include <casa/namespace.h>
    4955class PKSSDwriter : public PKSwriter
    5056{
     
    6470        const Vector<Double> antPosition,
    6571        const String obsMode,
     72        const String bunit,
    6673        const Float  equinox,
    6774        const String dopplerFrame,
     
    6976        const Vector<uInt> nPol,
    7077        const Vector<Bool> haveXPol,
    71         const Bool   haveBase,
    72         const String fluxUnit);
     78        const Bool   haveBase);
    7379
    7480    // Write the next data record.
    7581    virtual Int write(
    76         const Int             scanNo,
    77         const Int             cycleNo,
    78         const Double          mjd,
    79         const Double          interval,
    80         const String          fieldName,
    81         const String          srcName,
    82         const Vector<Double>  srcDir,
    83         const Vector<Double>  srcPM,
    84         const Double          srcVel,
    85         const String          obsMode,
    86         const Int             IFno,
    87         const Double          refFreq,
    88         const Double          bandwidth,
    89         const Double          freqInc,
    90         //const Double          restFreq,
    91         const Vector<Double>  restFreq,
    92         const Vector<Float>   tcal,
    93         const String          tcalTime,
    94         const Float           azimuth,
    95         const Float           elevation,
    96         const Float           parAngle,
    97         const Float           focusAxi,
    98         const Float           focusTan,
    99         const Float           focusRot,
    100         const Float           temperature,
    101         const Float           pressure,
    102         const Float           humidity,
    103         const Float           windSpeed,
    104         const Float           windAz,
    105         const Int             refBeam,
    106         const Int             beamNo,
    107         const Vector<Double>  direction,
    108         const Vector<Double>  scanRate,
    109         const Vector<Float>   tsys,
    110         const Vector<Float>   sigma,
    111         const Vector<Float>   calFctr,
    112         const Matrix<Float>   baselin,
    113         const Matrix<Float>   basesub,
    114         const Matrix<Float>   &spectra,
    115         const Matrix<uChar>   &flagged,
    116         const Complex         xCalFctr,
    117         const Vector<Complex> &xPol);
     82        const PKSrecord &pksrec);
     83
     84    // Write a history record.
     85    virtual Int history(const String text);
     86    virtual Int history(const char *text);
    11887
    11988    // Close the SDFITS file.
  • branches/alma/external/atnf/PKSIO/PKSreader.cc

    r1453 r1757  
    22//# PKSreader.cc: Class to read Parkes multibeam data.
    33//#---------------------------------------------------------------------------
    4 //# Copyright (C) 2000-2006
    5 //# Associated Universities, Inc. Washington DC, USA.
    6 //#
    7 //# This library is free software; you can redistribute it and/or modify it
    8 //# under the terms of the GNU Library General Public License as published by
    9 //# the Free Software Foundation; either version 2 of the License, or (at your
    10 //# option) any later version.
    11 //#
    12 //# This library is distributed in the hope that it will be useful, but WITHOUT
     4//# livedata - processing pipeline for single-dish, multibeam spectral data.
     5//# Copyright (C) 2000-2009, Australia Telescope National Facility, CSIRO
     6//#
     7//# This file is part of livedata.
     8//#
     9//# livedata is free software: you can redistribute it and/or modify it under
     10//# the terms of the GNU General Public License as published by the Free
     11//# Software Foundation, either version 3 of the License, or (at your option)
     12//# any later version.
     13//#
     14//# livedata is distributed in the hope that it will be useful, but WITHOUT
    1315//# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    14 //# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Library General Public
    15 //# License for more details.
    16 //#
    17 //# You should have received a copy of the GNU Library General Public License
    18 //# along with this library; if not, write to the Free Software Foundation,
    19 //# Inc., 675 Massachusetts Ave, Cambridge, MA 02139, USA.
    20 //#
    21 //# Correspondence concerning AIPS++ should be addressed as follows:
    22 //#        Internet email: aips2-request@nrao.edu.
    23 //#        Postal address: AIPS++ Project Office
    24 //#                        National Radio Astronomy Observatory
    25 //#                        520 Edgemont Road
    26 //#                        Charlottesville, VA 22903-2475 USA
    27 //#
    28 //# $Id$
     16//# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
     17//# more details.
     18//#
     19//# You should have received a copy of the GNU General Public License along
     20//# with livedata.  If not, see <http://www.gnu.org/licenses/>.
     21//#
     22//# Correspondence concerning livedata may be directed to:
     23//#        Internet email: mcalabre@atnf.csiro.au
     24//#        Postal address: Dr. Mark Calabretta
     25//#                        Australia Telescope National Facility, CSIRO
     26//#                        PO Box 76
     27//#                        Epping NSW 1710
     28//#                        AUSTRALIA
     29//#
     30//# http://www.atnf.csiro.au/computing/software/livedata.html
     31//# $Id: PKSreader.cc,v 19.13 2009-09-29 07:33:39 cal103 Exp $
    2932//#---------------------------------------------------------------------------
    3033//# Original: 2000/08/23, Mark Calabretta, ATNF
     
    4144#include <casa/OS/File.h>
    4245
    43 
    4446//--------------------------------------------------------------- getPKSreader
    4547
     
    5052        const Int retry,
    5153        const Int interpolate,
    52         String &format,
    53         Vector<Bool> &beams,
    54         Vector<Bool> &IFs,
    55         Vector<uInt> &nChan,
    56         Vector<uInt> &nPol,
    57         Vector<Bool> &haveXPol,
    58         Bool   &haveBase,
    59         Bool   &haveSpectra)
     54        String &format)
    6055{
    6156  // Check accessibility of the input.
     
    6358  if (!inFile.exists()) {
    6459    format = "DATASET NOT FOUND";
    65     return 0;
     60    return 0x0;
    6661  }
    6762
    6863  if (!inFile.isReadable()) {
    6964    format = "DATASET UNREADABLE";
    70     return 0;
     65    return 0x0;
    7166  }
    7267
    7368  // Determine the type of input.
    74   PKSreader *reader = 0;
     69  PKSreader *reader = 0x0;
    7570  if (inFile.isRegular()) {
    7671    // Is it MBFITS or SDFITS?
    77     RegularFileIO file(name);
    78     char buf[32];
    79     file.read(30, buf, False);
    80     buf[30] = '\0';
    81     if (String(buf) == "SIMPLE  =                    T") {
    82       // Looks like SDFITS.
     72    if (strstr(name.chars(), ".sdfits")) {
     73      // Looks like SDFITS, possibly gzip'd.
    8374      format = "SDFITS";
    8475      reader = new PKSFITSreader("SDFITS");
    8576
    8677    } else {
    87       // Assume it's MBFITS.
    88       format = "MBFITS";
    89       reader = new PKSFITSreader("MBFITS", retry, interpolate);
     78      RegularFileIO file(name);
     79      char buf[32];
     80      file.read(30, buf, False);
     81      buf[30] = '\0';
     82      if (String(buf) == "SIMPLE  =                    T") {
     83        // Looks like SDFITS.
     84        format = "SDFITS";
     85        reader = new PKSFITSreader("SDFITS");
     86
     87       } else {
     88         // Assume it's MBFITS.
     89         format = "MBFITS";
     90         reader = new PKSFITSreader("MBFITS", retry, interpolate);
     91       }
    9092    }
    9193
     
    104106    format = "UNRECOGNIZED INPUT FORMAT";
    105107  }
    106 
     108  return reader;
     109}
     110
     111//--------------------------------------------------------------- getPKSreader
     112
     113// Search a list of directories for a Parkes Multibeam dataset and return an
     114
     115PKSreader* getPKSreader(
     116        const String name,
     117        const Vector<String> directories,
     118        const Int retry,
     119        const Int interpolate,
     120        Int    &iDir,
     121        String &format)
     122{
     123  PKSreader *reader = 0x0;
     124
     125  iDir = -1;
     126  Int nDir = directories.nelements();
     127  for (Int i = 0; i < nDir; i++) {
     128    String inName = directories(i) + "/" + name;
     129    reader = getPKSreader(inName, retry, interpolate, format);
     130    if (reader) {
     131      iDir = i;
     132      break;
     133    }
     134  }
     135
     136  return reader;
     137}
     138
     139//--------------------------------------------------------------- getPKSreader
     140
     141// Open an appropriate PKSreader for a Parkes Multibeam dataset.
     142
     143PKSreader* getPKSreader(
     144        const String name,
     145        const String antenna,
     146        const Int retry,
     147        const Int interpolate,
     148        String &format,
     149        Vector<Bool> &beams,
     150        Vector<Bool> &IFs,
     151        Vector<uInt> &nChan,
     152        Vector<uInt> &nPol,
     153        Vector<Bool> &haveXPol,
     154        Bool   &haveBase,
     155        Bool   &haveSpectra)
     156{
     157  PKSreader *reader = getPKSreader(name, retry, interpolate, format);
    107158
    108159  // Try to open it.
    109160  if (reader) {
    110     if (reader->open(name, beams, IFs, nChan, nPol, haveXPol, haveBase,
    111                      haveSpectra)) {
     161    if (reader->open(name, antenna, beams, IFs, nChan, nPol, haveXPol,
     162                     haveBase, haveSpectra)) {
    112163      format += " OPEN ERROR";
    113164      delete reader;
    114     } else {
    115       return reader;
    116     }
    117   }
    118 
    119   return 0;
    120 }
    121 
     165      reader = 0x0;
     166    }
     167  }
     168
     169  return reader;
     170}
    122171
    123172//--------------------------------------------------------------- getPKSreader
     
    125174// Search a list of directories for a Parkes Multibeam dataset and return an
    126175// appropriate PKSreader for it.
    127 
    128 PKSreader* getPKSreader(
    129         const String name,
     176PKSreader* getPKSreader(
     177        const String name,
     178        const String antenna,
    130179        const Vector<String> directories,
    131180        const Int retry,
     
    141190        Bool   &haveSpectra)
    142191{
    143   Int nDir = directories.nelements();
    144   for (iDir = 0; iDir < nDir; iDir++) {
    145     String inName = directories(iDir) + "/" + name;
    146     PKSreader *reader = getPKSreader(inName, retry, interpolate, format,
    147                                      beams, IFs, nChan, nPol, haveXPol,
    148                                      haveBase, haveSpectra);
    149     if (reader != 0) {
    150       return reader;
    151     }
    152   }
    153 
    154   iDir = -1;
    155   return 0;
    156 }
     192  PKSreader *reader = getPKSreader(name, directories, retry, interpolate,
     193                                   iDir, format);
     194
     195  // Try to open it.
     196  if (reader) {
     197    if (reader->open(name, antenna, beams, IFs, nChan, nPol, haveXPol,
     198                     haveBase, haveSpectra)) {
     199      format += " OPEN ERROR";
     200      delete reader;
     201      reader = 0x0;
     202    }
     203  }
     204
     205  return reader;
     206}
  • branches/alma/external/atnf/PKSIO/PKSreader.h

    r1453 r1757  
    22//# PKSreader.h: Class to read Parkes multibeam data.
    33//#---------------------------------------------------------------------------
    4 //# Copyright (C) 2000-2006
    5 //# Associated Universities, Inc. Washington DC, USA.
    6 //#
    7 //# This library is free software; you can redistribute it and/or modify it
    8 //# under the terms of the GNU Library General Public License as published by
    9 //# the Free Software Foundation; either version 2 of the License, or (at your
    10 //# option) any later version.
    11 //#
    12 //# This library is distributed in the hope that it will be useful, but WITHOUT
     4//# livedata - processing pipeline for single-dish, multibeam spectral data.
     5//# Copyright (C) 2000-2009, Australia Telescope National Facility, CSIRO
     6//#
     7//# This file is part of livedata.
     8//#
     9//# livedata is free software: you can redistribute it and/or modify it under
     10//# the terms of the GNU General Public License as published by the Free
     11//# Software Foundation, either version 3 of the License, or (at your option)
     12//# any later version.
     13//#
     14//# livedata is distributed in the hope that it will be useful, but WITHOUT
    1315//# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    14 //# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Library General Public
    15 //# License for more details.
    16 //#
    17 //# You should have received a copy of the GNU Library General Public License
    18 //# along with this library; if not, write to the Free Software Foundation,
    19 //# Inc., 675 Massachusetts Ave, Cambridge, MA 02139, USA.
    20 //#
    21 //# Correspondence concerning AIPS++ should be addressed as follows:
    22 //#        Internet email: aips2-request@nrao.edu.
    23 //#        Postal address: AIPS++ Project Office
    24 //#                        National Radio Astronomy Observatory
    25 //#                        520 Edgemont Road
    26 //#                        Charlottesville, VA 22903-2475 USA
    27 //#
    28 //# $Id$
     16//# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
     17//# more details.
     18//#
     19//# You should have received a copy of the GNU General Public License along
     20//# with livedata.  If not, see <http://www.gnu.org/licenses/>.
     21//#
     22//# Correspondence concerning livedata may be directed to:
     23//#        Internet email: mcalabre@atnf.csiro.au
     24//#        Postal address: Dr. Mark Calabretta
     25//#                        Australia Telescope National Facility, CSIRO
     26//#                        PO Box 76
     27//#                        Epping NSW 1710
     28//#                        AUSTRALIA
     29//#
     30//# http://www.atnf.csiro.au/computing/software/livedata.html
     31//# $Id: PKSreader.h,v 19.24 2009-09-29 07:33:39 cal103 Exp $
    2932//#---------------------------------------------------------------------------
    3033//# Original: 2000/08/02, Mark Calabretta, ATNF
     
    3336#ifndef ATNF_PKSREADER_H
    3437#define ATNF_PKSREADER_H
     38
     39#include <atnf/PKSIO/PKSrecord.h>
     40#include <atnf/PKSIO/SrcType.h>
    3541
    3642#include <casa/aips.h>
     
    4046#include <casa/BasicSL/String.h>
    4147
     48#include <casa/namespace.h>
     49
    4250// <summary>
    4351// Class to read Parkes multibeam data.
    4452// </summary>
    4553
    46 #include <casa/namespace.h>
     54// Return an appropriate PKSreader for a Parkes Multibeam dataset.
     55class PKSreader* getPKSreader(
     56        const String name,
     57        const Int retry,
     58        const Int interpolate,
     59        String &format);
     60
     61// As above, but search a list of directories for it.
     62class PKSreader* getPKSreader(
     63        const String name,
     64        const Vector<String> directories,
     65        const Int retry,
     66        const Int interpolate,
     67        Int    &iDir,
     68        String &format);
    4769
    4870// Open an appropriate PKSreader for a Parkes Multibeam dataset.
    4971class PKSreader* getPKSreader(
    5072        const String name,
     73        const String antenna,
    5174        const Int retry,
    5275        const Int interpolate,
     
    6386class PKSreader* getPKSreader(
    6487        const String name,
     88        const String antenna,
    6589        const Vector<String> directories,
    6690        const Int retry,
     
    86110    virtual Int open(
    87111        const String inName,
     112        const String antenna,
    88113        Vector<Bool> &beams,
    89114        Vector<Bool> &IFs,
     
    101126        Vector<Double> &antPosition,
    102127        String &obsType,
     128        String &bunit,
    103129        Float  &equinox,
    104130        String &dopplerFrame,
    105131        Double &mjd,
    106132        Double &refFreq,
    107         Double &bandwidth,
    108         String &fluxunit) = 0;
     133        Double &bandwidth) = 0;
    109134
    110135    // Get frequency parameters for each IF.
     
    115140    // Set data selection criteria.  Channel numbering is 1-relative, zero or
    116141    // negative channel numbers are taken to be offsets from the last channel.
     142    // Coordinate system selection (only supported for SDFITS input):
     143    //   0: equatorial (RA,Dec),
     144    //   1: horizontal (Az,El),
     145    //   2: feed-plane,
     146    //   3: zenithal position angle of feed and elevation, (ZPA,El).
    117147    virtual uInt select(
    118148        const Vector<Bool> beamSel,
     
    123153        const Bool getSpectra = True,
    124154        const Bool getXPol    = False,
    125         const Bool getFeedPos = False) = 0;
     155        const Bool getFeedPos = False,
     156        const Bool getPointing = False,
     157        const Int  coordSys   = 0) = 0;
     158
    126159
    127160    // Find the range of the data selected in time and position.
     
    132165        Matrix<Double> &positions) = 0;
    133166
    134     // Read the next data record.
     167    // Read the next data record.
     168/**
    135169    virtual Int read(
    136170        Int             &scanNo,
     
    175209        Complex         &xCalFctr,
    176210        Vector<Complex> &xPol) = 0;
    177 
     211**/
     212/**
    178213    // Read the next data record, just the basics.
    179214    virtual Int read(
     
    185220        Matrix<Float> &spectra,
    186221        Matrix<uChar> &flagged) = 0;
     222**/
     223    virtual Int read(PKSrecord &pksrec) = 0;
    187224
    188225    // Close the input file.
     
    190227
    191228  protected:
    192     Bool   cGetFeedPos, cGetSpectra, cGetXPol;
     229    Bool   cGetFeedPos, cGetSpectra, cGetXPol, cGetPointing;
     230    Int   cCoordSys;
    193231
    194232    Vector<uInt> cNChan, cNPol;
  • branches/alma/external/atnf/PKSIO/PKSrecord.h

    r1752 r1757  
    6767    Double          bandwidth;
    6868    Double          freqInc;
    69     Double          restFreq;
     69    Int             nchan;
     70    Vector<Double>  restFreq;
    7071    Vector<Float>   tcal;
    7172    String          tcalTime;
     
    8687    Int             pCode;
    8788    Float           rateAge;
    88     Vector<Float>   scanRate;
     89    Vector<Double>  scanRate;
    8990    Float           paRate;
    9091    Vector<Float>   tsys;
     
    9596    Matrix<Float>   spectra;
    9697    Matrix<uChar>   flagged;
     98    uInt            flagrow;
    9799    Complex         xCalFctr;
    98100    Vector<Complex> xPol;
     101    Int             polNo ;
     102    Int             srcType ;
    99103};
    100104
  • branches/alma/external/atnf/PKSIO/PKSwriter.h

    r1453 r1757  
    22//# PKSwriter.h: Class to write out Parkes multibeam data.
    33//#---------------------------------------------------------------------------
    4 //# Copyright (C) 2000-2006
    5 //# Associated Universities, Inc. Washington DC, USA.
     4//# livedata - processing pipeline for single-dish, multibeam spectral data.
     5//# Copyright (C) 2000-2009, Australia Telescope National Facility, CSIRO
    66//#
    7 //# This library is free software; you can redistribute it and/or modify it
    8 //# under the terms of the GNU Library General Public License as published by
    9 //# the Free Software Foundation; either version 2 of the License, or (at your
    10 //# option) any later version.
     7//# This file is part of livedata.
    118//#
    12 //# This library is distributed in the hope that it will be useful, but WITHOUT
     9//# livedata is free software: you can redistribute it and/or modify it under
     10//# the terms of the GNU General Public License as published by the Free
     11//# Software Foundation, either version 3 of the License, or (at your option)
     12//# any later version.
     13//#
     14//# livedata is distributed in the hope that it will be useful, but WITHOUT
    1315//# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    14 //# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Library General Public
    15 //# License for more details.
     16//# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
     17//# more details.
    1618//#
    17 //# You should have received a copy of the GNU Library General Public License
    18 //# along with this library; if not, write to the Free Software Foundation,
    19 //# Inc., 675 Massachusetts Ave, Cambridge, MA 02139, USA.
     19//# You should have received a copy of the GNU General Public License along
     20//# with livedata.  If not, see <http://www.gnu.org/licenses/>.
    2021//#
    21 //# Correspondence concerning AIPS++ should be addressed as follows:
    22 //#        Internet email: aips2-request@nrao.edu.
    23 //#        Postal address: AIPS++ Project Office
    24 //#                        National Radio Astronomy Observatory
    25 //#                        520 Edgemont Road
    26 //#                        Charlottesville, VA 22903-2475 USA
     22//# Correspondence concerning livedata may be directed to:
     23//#        Internet email: mcalabre@atnf.csiro.au
     24//#        Postal address: Dr. Mark Calabretta
     25//#                        Australia Telescope National Facility, CSIRO
     26//#                        PO Box 76
     27//#                        Epping NSW 1710
     28//#                        AUSTRALIA
    2729//#
    28 //# $Id$
     30//# http://www.atnf.csiro.au/computing/software/livedata.html
     31//# $Id: PKSwriter.h,v 19.17 2009-09-29 07:33:39 cal103 Exp $
    2932//#---------------------------------------------------------------------------
    3033
    3134#ifndef ATNF_PKSWRITER_H
    3235#define ATNF_PKSWRITER_H
     36
     37#include <atnf/PKSIO/PKSrecord.h>
    3338
    3439#include <casa/aips.h>
     
    3843#include <casa/BasicSL/String.h>
    3944
     45#include <casa/namespace.h>
     46
    4047// <summary>
    4148// Class to write out Parkes multibeam data.
    4249// </summary>
    4350
    44 #include <casa/namespace.h>
    4551class PKSwriter
    4652{
     
    5763        const Vector<Double> antPosition,
    5864        const String obsMode,
     65        const String bunit,
    5966        const Float  equinox,
    6067        const String dopplerFrame,
     
    6269        const Vector<uInt> nPol,
    6370        const Vector<Bool> haveXPol,
    64         const Bool havebase,
    65         const String fluxUnit) = 0;
     71        const Bool havebase) = 0;
    6672
    6773    // Write the next data record.
    6874    virtual Int write (
    69         const Int             scanNo,
    70         const Int             cycleNo,
    71         const Double          mjd,
    72         const Double          interval,
    73         const String          fieldName,
    74         const String          srcName,
    75         const Vector<Double>  srcDir,
    76         const Vector<Double>  srcPM,
    77         const Double          srcVel,
    78         const String          obsMode,
    79         const Int             IFno,
    80         const Double          refFreq,
    81         const Double          bandwidth,
    82         const Double          freqInc,
    83         //const Double          restFreq,
    84         const Vector<Double>  restFreq,
    85         const Vector<Float>   tcal,
    86         const String          tcalTime,
    87         const Float           azimuth,
    88         const Float           elevation,
    89         const Float           parAngle,
    90         const Float           focusAxi,
    91         const Float           focusTan,
    92         const Float           focusRot,
    93         const Float           temperature,
    94         const Float           pressure,
    95         const Float           humidity,
    96         const Float           windSpeed,
    97         const Float           windAz,
    98         const Int             refBeam,
    99         const Int             beamNo,
    100         const Vector<Double>  direction,
    101         const Vector<Double>  scanRate,
    102         const Vector<Float>   tsys,
    103         const Vector<Float>   sigma,
    104         const Vector<Float>   calFctr,
    105         const Matrix<Float>   baseLin,
    106         const Matrix<Float>   baseSub,
    107         const Matrix<Float>   &spectra,
    108         const Matrix<uChar>   &flagged,
    109         const Complex         xCalFctr,
    110         const Vector<Complex> &xPol) = 0;
     75        const PKSrecord &pksrec) = 0;
     76
     77    // Write a history record.
     78    virtual Int history(const String text) {return 0;};
     79    virtual Int history(const char *text)  {return 0;};
    11180
    11281    // Close the output file.
  • branches/alma/external/atnf/PKSIO/SDFITSreader.cc

    r1453 r1757  
    11//#---------------------------------------------------------------------------
    2 //# SDFITSreader.cc: ATNF CFITSIO interface class for SDFITS input.
     2//# SDFITSreader.cc: ATNF interface class for SDFITS input using CFITSIO.
    33//#---------------------------------------------------------------------------
    4 //# Copyright (C) 2000-2006
    5 //# Associated Universities, Inc. Washington DC, USA.
     4//# livedata - processing pipeline for single-dish, multibeam spectral data.
     5//# Copyright (C) 2000-2009, Australia Telescope National Facility, CSIRO
    66//#
    7 //# This library is free software; you can redistribute it and/or modify it
    8 //# under the terms of the GNU Library General Public License as published by
    9 //# the Free Software Foundation; either version 2 of the License, or (at your
    10 //# option) any later version.
     7//# This file is part of livedata.
    118//#
    12 //# This library is distributed in the hope that it will be useful, but WITHOUT
     9//# livedata is free software: you can redistribute it and/or modify it under
     10//# the terms of the GNU General Public License as published by the Free
     11//# Software Foundation, either version 3 of the License, or (at your option)
     12//# any later version.
     13//#
     14//# livedata is distributed in the hope that it will be useful, but WITHOUT
    1315//# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    14 //# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Library General Public
    15 //# License for more details.
     16//# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
     17//# more details.
    1618//#
    17 //# You should have received a copy of the GNU Library General Public License
    18 //# along with this library; if not, write to the Free Software Foundation,
    19 //# Inc., 675 Massachusetts Ave, Cambridge, MA 02139, USA.
     19//# You should have received a copy of the GNU General Public License along
     20//# with livedata.  If not, see <http://www.gnu.org/licenses/>.
    2021//#
    21 //# Correspondence concerning this software should be addressed as follows:
    22 //#        Internet email: aips2-request@nrao.edu.
    23 //#        Postal address: AIPS++ Project Office
    24 //#                        National Radio Astronomy Observatory
    25 //#                        520 Edgemont Road
    26 //#                        Charlottesville, VA 22903-2475 USA
     22//# Correspondence concerning livedata may be directed to:
     23//#        Internet email: mcalabre@atnf.csiro.au
     24//#        Postal address: Dr. Mark Calabretta
     25//#                        Australia Telescope National Facility, CSIRO
     26//#                        PO Box 76
     27//#                        Epping NSW 1710
     28//#                        AUSTRALIA
    2729//#
    28 //# $Id$
     30//# http://www.atnf.csiro.au/computing/software/livedata.html
     31//# $Id: SDFITSreader.cc,v 19.45 2009-09-30 07:23:48 cal103 Exp $
    2932//#---------------------------------------------------------------------------
    3033//# The SDFITSreader class reads single dish FITS files such as those written
     
    3437//#---------------------------------------------------------------------------
    3538
     39#include <atnf/pks/pks_maths.h>
     40#include <atnf/PKSIO/MBrecord.h>
     41#include <atnf/PKSIO/SDFITSreader.h>
     42
     43#include <casa/Logging/LogIO.h>
     44#include <casa/Quanta/MVTime.h>
     45#include <casa/math.h>
     46#include <casa/stdio.h>
     47
    3648#include <algorithm>
    3749#include <strings.h>
    38 
    39 // AIPS++ includes.
    40 #include <casa/iostream.h>
    41 #include <casa/math.h>
    42 #include <casa/stdio.h>
    43 
    44 // ATNF includes.
    45 #include <atnf/pks/pks_maths.h>
    46 #include <atnf/PKSIO/PKSMBrecord.h>
    47 #include <atnf/PKSIO/SDFITSreader.h>
    48 
     50#include <cstring>
    4951
    5052class FITSparm
     
    5759    long nelem;         // Column data repeat count; < 0 for vardim.
    5860    int  tdimcol;       // TDIM column number; 0 for keyword; -1 absent.
     61    char units[32];     // Units from TUNITn keyword.
    5962};
    6063
     
    6467// Factor to convert radians to degrees.
    6568const double D2R = PI / 180.0;
     69
     70// Class name
     71const string className = "SDFITSreader" ;
     72
     73//---------------------------------------------------- SDFITSreader::(statics)
     74
     75int SDFITSreader::sInit  = 1;
     76int SDFITSreader::sReset = 0;
     77int (*SDFITSreader::sALFAcalNon)[2]   = (int (*)[2])(new float[16]);
     78int (*SDFITSreader::sALFAcalNoff)[2]  = (int (*)[2])(new float[16]);
     79float (*SDFITSreader::sALFAcalOn)[2]  = (float (*)[2])(new float[16]);
     80float (*SDFITSreader::sALFAcalOff)[2] = (float (*)[2])(new float[16]);
     81float (*SDFITSreader::sALFAcal)[2]    = (float (*)[2])(new float[16]);
    6682
    6783//------------------------------------------------- SDFITSreader::SDFITSreader
     
    7086{
    7187  // Default constructor.
    72   cSDptr = 0;
     88  cSDptr = 0x0;
    7389
    7490  // Allocate space for data descriptors.
     
    85101  cEndChan   = 0x0;
    86102  cRefChan   = 0x0;
     103  cPols      = 0x0;
    87104}
    88105
     
    113130        int    &extraSysCal)
    114131{
     132  const string methodName = "open()" ;
     133
    115134  if (cSDptr) {
    116135    close();
     
    120139  cStatus = 0;
    121140  if (fits_open_file(&cSDptr, sdName, READONLY, &cStatus)) {
    122     cerr << "Failed to open SDFITS file: " << sdName << endl;
    123     reportError();
     141    sprintf(cMsg, "ERROR: Failed to open SDFITS file\n       %s", sdName);
     142    log(LogOrigin( className, methodName, WHERE ), LogIO::SEVERE, cMsg);
    124143    return 1;
    125144  }
     
    138157        cALFA_CIMA = 1;
    139158
     159        // Check for later versions of CIMAFITS.
     160        float version;
     161        readParm("VERSION", TFLOAT, &version);
     162        if (version >= 2.0f) cALFA_CIMA = int(version);
     163
    140164      } else {
    141         cerr << "Failed to locate SDFITS binary table." << endl;
    142         reportError();
     165        log(LogOrigin( className, methodName, WHERE ), LogIO::SEVERE, "Failed to locate SDFITS binary table.");
    143166        close();
    144167        return 1;
     
    148171    // Arecibo ALFA data of some kind.
    149172    cALFA = 1;
    150     for (int iBeam = 0; iBeam < 8; iBeam++) {
    151       for (int iPol = 0; iPol < 2; iPol++) {
    152         cALFAcalOn[iBeam][iPol]  = 0.0f;
    153         cALFAcalOff[iBeam][iPol] = 0.0f;
    154 
    155         // Nominal factor to calibrate spectra in Jy.
    156         cALFAcal[iBeam][iPol] = 3.0f;
    157       }
     173    if (sInit) {
     174      for (int iBeam = 0; iBeam < 8; iBeam++) {
     175        for (int iPol = 0; iPol < 2; iPol++) {
     176          sALFAcalOn[iBeam][iPol]  = 0.0f;
     177          sALFAcalOff[iBeam][iPol] = 0.0f;
     178
     179          // Nominal factor to calibrate spectra in Jy.
     180          sALFAcal[iBeam][iPol] = 3.0f;
     181        }
     182      }
     183
     184      sInit = 0;
    158185    }
    159186  }
     
    165192         strncmp(telescope, "NRAO_GBT", 8) == 0;
    166193
    167   cRow = 0;
    168 
    169194
    170195  // Check that the DATA array column is present.
     
    172197  haveSpectra = cHaveSpectra = cData[DATA].colnum > 0;
    173198
     199  cNAxisTime = 0;
    174200  if (cHaveSpectra) {
    175201    // Find the number of data axes (must be the same for each IF).
    176     cNAxis = 5;
    177     if (readDim(DATA, 1, &cNAxis, cNAxes)) {
    178       reportError();
     202    cNAxes = 5;
     203    if (readDim(DATA, 1, &cNAxes, cNAxis)) {
     204      log(LogOrigin( className, methodName, WHERE ), LogIO::SEVERE);
    179205      close();
    180206      return 1;
     
    182208
    183209    if (cALFA_BD) {
    184       // ALFA BDFITS: variable length arrays don't actually vary and there is 
     210      // ALFA BDFITS: variable length arrays don't actually vary and there is
    185211      // no TDIM (or MAXISn) card; use the LAGS_IN value.
    186       cNAxis = 5;
    187       readParm("LAGS_IN", TLONG, cNAxes);
    188       cNAxes[1] = 1;
    189       cNAxes[2] = 1;
    190       cNAxes[3] = 1;
    191       cNAxes[4] = 1;
    192       cData[DATA].nelem = cNAxes[0];
    193     }
    194 
    195     if (cNAxis < 4) {
     212      cNAxes = 5;
     213      readParm("LAGS_IN", TLONG, cNAxis);
     214      cNAxis[1] = 1;
     215      cNAxis[2] = 1;
     216      cNAxis[3] = 1;
     217      cNAxis[4] = 1;
     218      cData[DATA].nelem = cNAxis[0];
     219    }
     220
     221    if (cNAxes < 4) {
    196222      // Need at least four axes (for now).
    197       cerr << "DATA array contains fewer than four axes." << endl;
     223      log(LogOrigin( className, methodName, WHERE ), LogIO::SEVERE, "DATA array contains fewer than four axes.");
    198224      close();
    199225      return 1;
    200     } else if (cNAxis > 5) {
     226    } else if (cNAxes > 5) {
    201227      // We support up to five axes.
    202       cerr << "DATA array contains more than five axes." << endl;
     228      log(LogOrigin( className, methodName, WHERE ), LogIO::SEVERE, "DATA array contains more than five axes.");
    203229      close();
    204230      return 1;
     
    211237    findData(DATAXED, "DATAXED", TSTRING);
    212238    if (cData[DATAXED].colnum < 0) {
    213       cerr << "DATA array column absent from binary table." << endl;
     239      log(LogOrigin( className, methodName, WHERE ), LogIO::SEVERE, "DATA array column absent from binary table.");
    214240      close();
    215241      return 1;
     
    220246    readParm("DATAXED", TSTRING, dataxed);
    221247
    222     for (int iaxis = 0; iaxis < 5; iaxis++) cNAxes[iaxis] = 0;
    223     sscanf(dataxed, "(%ld,%ld,%ld,%ld,%ld)", cNAxes, cNAxes+1, cNAxes+2,
    224       cNAxes+3, cNAxes+4);
     248    for (int iaxis = 0; iaxis < 5; iaxis++) cNAxis[iaxis] = 0;
     249    sscanf(dataxed, "(%ld,%ld,%ld,%ld,%ld)", cNAxis, cNAxis+1, cNAxis+2,
     250      cNAxis+3, cNAxis+4);
    225251    for (int iaxis = 4; iaxis > -1; iaxis--) {
    226       if (cNAxes[iaxis] == 0) cNAxis = iaxis;
     252      if (cNAxis[iaxis] == 0) cNAxes = iaxis;
    227253    }
    228254  }
     
    235261  // Find required DATA array axes.
    236262  char ctype[5][72];
    237   for (int iaxis = 0; iaxis < cNAxis; iaxis++) {
     263  for (int iaxis = 0; iaxis < cNAxes; iaxis++) {
    238264    strcpy(ctype[iaxis], "");
    239265    readParm(CTYPE[iaxis], TSTRING, ctype[iaxis]);      // Core.
     
    241267
    242268  if (cStatus) {
    243     reportError();
     269    log(LogOrigin( className, methodName, WHERE ), LogIO::SEVERE);
    244270    close();
    245271    return 1;
    246272  }
    247273
    248   char *fqCRPIX  = 0;
    249274  char *fqCRVAL  = 0;
    250275  char *fqCDELT  = 0;
     276  char *fqCRPIX  = 0;
    251277  char *raCRVAL  = 0;
    252278  char *decCRVAL = 0;
    253279  char *timeCRVAL = 0;
     280  char *timeCDELT = 0;
     281  char *timeCRPIX = 0;
    254282  char *beamCRVAL = 0;
    255 
    256   for (int iaxis = 0; iaxis < cNAxis; iaxis++) {
     283  char *polCRVAL = 0;
     284
     285  cFreqAxis   = -1;
     286  cStokesAxis = -1;
     287  cRaAxis     = -1;
     288  cDecAxis    = -1;
     289  cTimeAxis   = -1;
     290  cBeamAxis   = -1;
     291
     292  for (int iaxis = 0; iaxis < cNAxes; iaxis++) {
    257293    if (strncmp(ctype[iaxis], "FREQ", 4) == 0) {
    258       cReqax[0] = iaxis;
    259       fqCRPIX  = CRPIX[iaxis];
    260       fqCRVAL  = CRVAL[iaxis];
    261       fqCDELT  = CDELT[iaxis];
     294      cFreqAxis = iaxis;
     295      fqCRVAL   = CRVAL[iaxis];
     296      fqCDELT   = CDELT[iaxis];
     297      fqCRPIX   = CRPIX[iaxis];
    262298
    263299    } else if (strncmp(ctype[iaxis], "STOKES", 6) == 0) {
    264       cReqax[1] = iaxis;
     300      cStokesAxis = iaxis;
     301      polCRVAL = CRVAL[iaxis];
    265302
    266303    } else if (strncmp(ctype[iaxis], "RA", 2) == 0) {
    267       cReqax[2] = iaxis;
    268       raCRVAL  = CRVAL[iaxis];
     304      cRaAxis  = iaxis;
     305      raCRVAL   = CRVAL[iaxis];
    269306
    270307    } else if (strncmp(ctype[iaxis], "DEC", 3) == 0) {
    271       cReqax[3] = iaxis;
    272       decCRVAL = CRVAL[iaxis];
     308      cDecAxis = iaxis;
     309      decCRVAL  = CRVAL[iaxis];
    273310
    274311    } else if (strcmp(ctype[iaxis], "TIME") == 0) {
    275       // TIME (UTC seconds since midnight) can be a keyword or axis type.
     312      // TIME (UTC seconds since midnight); axis type, if present, takes
     313      // precedence over keyword.
     314      cTimeAxis = iaxis;
    276315      timeCRVAL = CRVAL[iaxis];
     316
     317      // Check for non-degeneracy.
     318      if ((cNAxisTime = cNAxis[iaxis]) > 1) {
     319        timeCDELT = CDELT[iaxis];
     320        timeCRPIX = CRPIX[iaxis];
     321        sprintf(cMsg, "DATA array contains a TIME axis of length %ld.",
     322          cNAxisTime);
     323        //logMsg(cMsg);
     324        log(LogOrigin( className, methodName, WHERE ), LogIO::NORMAL, cMsg);
     325      }
    277326
    278327    } else if (strcmp(ctype[iaxis], "BEAM") == 0) {
    279328      // BEAM can be a keyword or axis type.
     329      cBeamAxis = iaxis;
    280330      beamCRVAL = CRVAL[iaxis];
    281331    }
     
    284334  if (cALFA_BD) {
    285335    // Fixed in ALFA CIMAFITS.
    286     cReqax[2] = 2;
     336    cRaAxis = 2;
    287337    raCRVAL = "CRVAL2A";
    288338
    289     cReqax[3] = 3;
     339    cDecAxis = 3;
    290340    decCRVAL = "CRVAL3A";
    291341  }
    292342
    293   // Check that all are present.
    294   for (int iaxis = 0; iaxis < 4; iaxis++) {
    295     if (cReqax[iaxis] < 0) {
    296       cerr << "Could not find required DATA array axes." << endl;
    297       close();
    298       return 1;
    299     }
     343
     344  // Check that required axes are present.
     345  if (cFreqAxis < 0 || cStokesAxis < 0 || cRaAxis < 0 || cDecAxis < 0) {
     346    log(LogOrigin( className, methodName, WHERE ), LogIO::SEVERE, "Could not find required DATA array axes.");
     347    close();
     348    return 1;
    300349  }
    301350
     
    304353  findData(CYCLE,    "CYCLE",    TINT);         // Additional.
    305354  findData(DATE_OBS, "DATE-OBS", TSTRING);      // Core.
    306   findData(TIME,     "TIME",     TDOUBLE);      // Core.
     355
     356  if (cTimeAxis >= 0) {
     357    // The DATA array has a TIME axis.
     358    if (cNAxisTime > 1) {
     359      // Non-degenerate.
     360      findData(TimeRefVal, timeCRVAL, TDOUBLE); // Time reference value.
     361      findData(TimeDelt,   timeCDELT, TDOUBLE); // Time increment.
     362      findData(TimeRefPix, timeCRPIX, TFLOAT);  // Time reference pixel.
     363    } else {
     364      // Degenerate, treat its like a simple TIME keyword.
     365      findData(TIME, timeCRVAL,  TDOUBLE);
     366    }
     367
     368  } else {
     369    findData(TIME,   "TIME",     TDOUBLE);      // Core.
     370  }
     371
    307372  findData(EXPOSURE, "EXPOSURE", TFLOAT);       // Core.
    308373  findData(OBJECT,   "OBJECT",   TSTRING);      // Core.
     
    314379  findData(BEAM,     "BEAM",     TSHORT);       // Additional.
    315380  findData(IF,       "IF",       TSHORT);       // Additional.
    316   findData(FqRefPix,  fqCRPIX,   TFLOAT);       // Frequency reference pixel.
    317381  findData(FqRefVal,  fqCRVAL,   TDOUBLE);      // Frequency reference value.
    318382  findData(FqDelt,    fqCDELT,   TDOUBLE);      // Frequency increment.
     383  findData(FqRefPix,  fqCRPIX,   TFLOAT);       // Frequency reference pixel.
    319384  findData(RA,        raCRVAL,   TDOUBLE);      // Right ascension.
    320385  findData(DEC,      decCRVAL,   TDOUBLE);      // Declination.
     
    343408  findData(WINDDIRE, "WINDDIRE", TFLOAT);       // Shared.
    344409
     410  findData(STOKES,    polCRVAL,  TINT);
     411  findData(SIG,       "SIG",     TSTRING);
     412  findData(CAL,       "CAL",     TSTRING);
     413
     414  findData(RVSYS,     "RVSYS",   TDOUBLE);
     415  findData(VFRAME,    "VFRAME",  TDOUBLE);
     416  findData(VELDEF,    "VELDEF",  TSTRING);
     417
    345418  if (cStatus) {
    346     reportError();
     419    log(LogOrigin( className, methodName, WHERE ), LogIO::SEVERE);
    347420    close();
    348421    return 1;
     
    355428    cALFAscan = 0;
    356429    cScanNo = 0;
    357     if (cALFA_BD) {
     430    if (cALFA_CIMA) {
     431      findData(SCAN,  "SCAN_ID", TINT);
     432      if (cALFA_CIMA > 1) {
     433        // Note that RECNUM increases by cNAxisTime per row.
     434        findData(CYCLE, "RECNUM", TINT);
     435      } else {
     436        findData(CYCLE, "SUBSCAN", TINT);
     437      }
     438    } else if (cALFA_BD) {
    358439      findData(SCAN,  "SCAN_NUMBER", TINT);
    359440      findData(CYCLE, "PATTERN_NUMBER", TINT);
    360     } else if (cALFA_CIMA) {
    361       findData(SCAN,  "SCAN_ID", TINT);
    362       findData(CYCLE, "SUBSCAN", TINT);
    363441    }
    364442  } else {
     
    368446  cCycleNo = 0;
    369447  cLastUTC = 0.0;
     448  for ( int i = 0 ; i < 4 ; i++ ) {
     449    cGLastUTC[i] = 0.0 ;
     450    cGLastScan[i] = -1 ;
     451    cGCycleNo[i] = 0 ;
     452  }
    370453
    371454  // Beam number, 1-relative by default.
    372455  cBeam_1rel = 1;
    373   if (cData[BEAM].colnum < 0) {
     456  if (cALFA) {
     457    // ALFA INPUT_ID, 0-relative (overrides BEAM column if present).
     458    findData(BEAM, "INPUT_ID", TSHORT);
     459    cBeam_1rel = 0;
     460
     461  } else if (cData[BEAM].colnum < 0) {
    374462    if (beamCRVAL) {
    375463      // There is a BEAM axis.
    376464      findData(BEAM, beamCRVAL, TDOUBLE);
    377 
    378465    } else {
    379       if (cALFA) {
    380         // ALFA data, 0-relative.
    381         findData(BEAM, "INPUT_ID", TSHORT);
    382       } else {
    383         // ms2sdfits output, 0-relative "feed" number.
    384         findData(BEAM, "MAIN_FEED1", TSHORT);
    385       }
    386 
     466      // ms2sdfits output, 0-relative "feed" number.
     467      findData(BEAM, "MAIN_FEED1", TSHORT);
    387468      cBeam_1rel = 0;
    388469    }
     
    393474  if (cALFA && cData[IF].colnum < 0) {
    394475    // ALFA data, 0-relative.
    395     findData(IF, "IFVAL", TSHORT);
     476    if (cALFA_CIMA > 1) {
     477      findData(IF, "IFN", TSHORT);
     478    } else {
     479      findData(IF, "IFVAL", TSHORT);
     480    }
    396481    cIF_1rel = 0;
    397   }
    398 
    399   if (cData[TIME].colnum < 0) {
    400     if (timeCRVAL) {
    401       // There is a TIME axis.
    402       findData(TIME, timeCRVAL, TDOUBLE);
    403     }
    404482  }
    405483
     
    476554  fits_get_num_rows(cSDptr, &cNRow, &cStatus);
    477555  if (!cNRow) {
    478     cerr << "Table contains no entries." << endl;
     556    log(LogOrigin( className, methodName, WHERE ), LogIO::SEVERE, "Table contains no entries.");
    479557    close();
    480558    return 1;
     
    489567    if (fits_read_col(cSDptr, TSHORT, cData[BEAM].colnum, 1, 1, cNRow,
    490568                      &beamNul, beamCol, &anynul, &cStatus)) {
    491       reportError();
    492569      delete [] beamCol;
     570      log(LogOrigin( className, methodName, WHERE ), LogIO::SEVERE);
    493571      close();
    494572      return 1;
     
    504582      // Check validity.
    505583      if (beamCol[irow] < cBeam_1rel) {
    506         cerr << "SDFITS file contains invalid beam number." << endl;
    507584        delete [] beamCol;
     585        log(LogOrigin( className, methodName, WHERE ), LogIO::SEVERE, "SDFITS file contains invalid beam number.");
    508586        close();
    509587        return 1;
     
    545623    if (fits_read_col(cSDptr, TSHORT, cData[IF].colnum, 1, 1, cNRow,
    546624                      &IFNul, IFCol, &anynul, &cStatus)) {
    547       reportError();
    548625      delete [] IFCol;
     626      log(LogOrigin( className, methodName, WHERE ), LogIO::SEVERE);
    549627      close();
    550628      return 1;
     
    560638      // Check validity.
    561639      if (IFCol[irow] < cIF_1rel) {
    562         cerr << "SDFITS file contains invalid IF number." << endl;
    563640        delete [] IFCol;
     641        log(LogOrigin( className, methodName, WHERE ), LogIO::SEVERE, "SDFITS file contains invalid IF number.");
    564642        close();
    565643        return 1;
     
    592670          if (cData[DATA].nelem < 0) {
    593671            // Variable dimension array.
    594             if (readDim(DATA, irow+1, &cNAxis, cNAxes)) {
    595               reportError();
     672            if (readDim(DATA, irow+1, &cNAxes, cNAxis)) {
     673              log(LogOrigin( className, methodName, WHERE ), LogIO::SEVERE);
    596674              close();
    597675              return 1;
     
    604682            readParm("DATAXED", TSTRING, dataxed);
    605683
    606             sscanf(dataxed, "(%ld,%ld,%ld,%ld,%ld)", cNAxes, cNAxes+1,
    607               cNAxes+2, cNAxes+3, cNAxes+4);
     684            sscanf(dataxed, "(%ld,%ld,%ld,%ld,%ld)", cNAxis, cNAxis+1,
     685              cNAxis+2, cNAxis+3, cNAxis+4);
    608686          }
    609687        }
    610688
    611689        // Number of channels and polarizations.
    612         cNChan[iIF]    = cNAxes[cReqax[0]];
    613         cNPol[iIF]     = cNAxes[cReqax[1]];
     690        cNChan[iIF]    = cNAxis[cFreqAxis];
     691        cNPol[iIF]     = cNAxis[cStokesAxis];
    614692        cHaveXPol[iIF] = 0;
    615693
     
    621699
    622700          if (readDim(XPOLDATA, irow+1, &nAxis, nAxes)) {
    623             reportError();
     701            log(LogOrigin( className, methodName, WHERE ), LogIO::SEVERE );
    624702            close();
    625703            return 1;
     
    650728
    651729    // Number of channels and polarizations.
    652     cNChan[0] = cNAxes[cReqax[0]];
    653     cNPol[0]  = cNAxes[cReqax[1]];
     730    cNChan[0] = cNAxis[cFreqAxis];
     731    cNPol[0]  = cNAxis[cStokesAxis];
    654732    cHaveXPol[0] = 0;
    655733  }
    656734
    657   if (cALFA) {
    658     // ALFA labels each polarization as a separate IF.
     735  if (cALFA && cALFA_CIMA < 2) {
     736    // Older ALFA data labels each polarization as a separate IF.
    659737    cNPol[0] = cNIF;
    660738    cNIF = 1;
     739  }
     740
     741  // For GBT data that stores spectra for each polarization in separate rows
     742  if ( cData[STOKES].colnum > 0 ) {
     743    int *stokesCol = new int[cNRow];
     744    int stokesNul = 1;
     745    int   anynul;
     746    if (fits_read_col(cSDptr, TINT, cData[STOKES].colnum, 1, 1, cNRow,
     747                      &stokesNul, stokesCol, &anynul, &cStatus)) {
     748      delete [] stokesCol;
     749      log(LogOrigin( className, methodName, WHERE ), LogIO::SEVERE);
     750      close();
     751      return 1;
     752    }
     753
     754    vector<int> pols ;
     755    pols.push_back( stokesCol[0] ) ;
     756    for ( int i = 0 ; i < cNRow ; i++ ) {
     757      bool pmatch = false ;
     758      for ( uint j = 0 ; j < pols.size() ; j++ ) {
     759        if ( stokesCol[i] == pols[j] ) {
     760          pmatch = true ;
     761          break ;
     762        }
     763      }
     764      if ( !pmatch ) {
     765        pols.push_back( stokesCol[i] ) ;
     766      }
     767    }
     768
     769    cPols = new int[pols.size()] ;
     770    for ( uint i = 0 ; i < pols.size() ; i++ ) {
     771      cPols[i] = pols[i] ;
     772    }
     773
     774    for ( int i = 0 ; i < cNIF ; i++ ) {
     775      cNPol[i] = pols.size() ;
     776    }
     777
     778    delete [] stokesCol ;
    661779  }
    662780
     
    712830  extraSysCal = cExtraSysCal;
    713831
     832
     833  // Extras for ALFA data.
     834  cALFAacc = 0.0f;
     835  if (cALFA_CIMA > 1) {
     836    // FFTs per second when the Mock correlator operates in RFI blanking mode.
     837    readData("PHFFTACC", TFLOAT, 0, &cALFAacc);
     838  }
     839
     840
     841  cRow = 0;
     842  cTimeIdx = cNAxisTime;
     843
    714844  return 0;
    715845}
     
    725855        double antPos[3],
    726856        char   obsMode[32],
     857        char   bunit[32],
    727858        float  &equinox,
    728859        char   radecsys[32],
     
    733864        double &bandwidth)
    734865{
     866  const string methodName = "getHeader()" ;
     867 
    735868  // Has the file been opened?
    736869  if (!cSDptr) {
     
    773906  readData(OBSMODE, 1, obsMode);                        // Shared.
    774907
     908  // Brightness unit.
     909  if (cData[DATAXED].colnum >= 0) {
     910    strcpy(bunit, "Jy");
     911  } else {
     912    strcpy(bunit, cData[DATA].units);
     913  }
     914
     915  if (strcmp(bunit, "JY") == 0) {
     916    bunit[1] = 'y';
     917  } else if (strcmp(bunit, "JY/BEAM") == 0) {
     918    strcpy(bunit, "Jy/beam");
     919  }
     920
    775921  readParm("EQUINOX",  TFLOAT,  &equinox);              // Shared.
    776922  if (cStatus == 405) {
     
    793939
    794940    // Look for VELFRAME, written by earlier versions of Livedata.
     941    //
     942    // Added few more codes currently (as of 2009 Oct) used in the GBT
     943    // SDFITS (based io_sdfits_define.pro of GBTIDL). - TT
    795944    if (readParm("VELFRAME", TSTRING, dopplerFrame)) {  // Additional.
    796945      // No, try digging it out of the CTYPE card (AIPS convention).
    797946      char keyw[9], ctype[9];
    798       sprintf(keyw, "CTYPE%ld", cReqax[0]+1);
     947      sprintf(keyw, "CTYPE%ld", cFreqAxis+1);
    799948      readParm(keyw, TSTRING, ctype);
    800949
     
    804953          // LSR unqualified usually means LSR (kinematic).
    805954          strcpy(dopplerFrame, "LSRK");
     955        } else if (strcmp(dopplerFrame, "LSD") == 0) {
     956          // LSR as a dynamical defintion
     957          strcpy(dopplerFrame, "LSRD");
    806958        } else if (strcmp(dopplerFrame, "HEL") == 0) {
    807959          // Almost certainly barycentric.
    808960          strcpy(dopplerFrame, "BARYCENT");
     961        } else if (strcmp(dopplerFrame, "BAR") == 0) {
     962          // barycentric.
     963          strcpy(dopplerFrame, "BARYCENT");
     964        } else if (strcmp(dopplerFrame, "OBS") == 0) {
     965          // observed or topocentric.
     966          strcpy(dopplerFrame, "TOPO");
     967        } else if (strcmp(dopplerFrame, "GEO") == 0) {
     968          // geocentric
     969          strcpy(dopplerFrame, "GEO");
     970        } else if (strcmp(dopplerFrame, "GAL") == 0) {
     971          // galactic
     972          strcpy(dopplerFrame, "GAL");
     973        } else if (strcmp(dopplerFrame, "LGR") == 0) {
     974          // Local group
     975          strcpy(dopplerFrame, "LGROUP");
     976        } else if (strcmp(dopplerFrame, "CMB") == 0) {
     977          // Cosimic Microwave Backgroup
     978          strcpy(dopplerFrame, "CMB");
    809979        }
    810980      } else {
     
    812982      }
    813983    }
    814 
    815984    // Translate to FITS standard names.
    816985    if (strncmp(dopplerFrame, "TOP", 3) == 0) {
     
    822991    } else if (strncmp(dopplerFrame, "BARY", 4) == 0) {
    823992      strcpy(dopplerFrame, "BARYCENT");
    824     }
    825   }
    826 
     993    } else if (strncmp(dopplerFrame, "GAL", 3) == 0) {
     994      strcpy(dopplerFrame, "GALACTOC");
     995    } else if (strncmp(dopplerFrame, "LGROUP", 6) == 0) {
     996      strcpy(dopplerFrame, "LOCALGRP");
     997    } else if (strncmp(dopplerFrame, "CMB", 3) == 0) {
     998      strcpy(dopplerFrame, "CMBDIPOL");
     999    }
     1000  }
     1001 
    8271002  if (cStatus) {
    828     reportError();
     1003    log(LogOrigin( className, methodName, WHERE ), LogIO::SEVERE);
    8291004    return 1;
    8301005  }
    8311006
    8321007  // Get parameters from first row of table.
    833   readData(DATE_OBS, 1, datobs);
    834   readData(TIME,     1, &utc);
     1008  readTime(1, 1, datobs, utc);
    8351009  readData(FqRefVal, 1, &refFreq);
    8361010  readParm("BANDWID", TDOUBLE, &bandwidth);             // Core.
    8371011
    838   if (cALFA_BD) utc *= 3600.0;
    839 
    8401012  if (cStatus) {
    841     reportError();
     1013    log(LogOrigin( className, methodName, WHERE ), LogIO::SEVERE);
    8421014    return 1;
    843   }
    844 
    845   // Check DATE-OBS format.
    846   if (datobs[2] == '/') {
    847     // Translate an old-format DATE-OBS.
    848     datobs[9] = datobs[1];
    849     datobs[8] = datobs[0];
    850     datobs[2] = datobs[6];
    851     datobs[5] = datobs[3];
    852     datobs[3] = datobs[7];
    853     datobs[6] = datobs[4];
    854     datobs[7] = '-';
    855     datobs[4] = '-';
    856     datobs[1] = '9';
    857     datobs[0] = '1';
    858     datobs[10] = '\0';
    859 
    860   } else if (datobs[10] == 'T' && cData[TIME].colnum < 0) {
    861     // Dig UTC out of a new-format DATE-OBS.
    862     int   hh, mm;
    863     float ss;
    864     sscanf(datobs+11, "%d:%d:%f", &hh, &mm, &ss);
    865     utc = (hh*60 + mm)*60 + ss;
    866     datobs[10] = '\0';
    8671015  }
    8681016
     
    8791027        double* &endFreq)
    8801028{
     1029  const string methodName = "getFreqInfo()" ;
     1030
    8811031  float  fqRefPix;
    8821032  double fqDelt, fqRefVal;
     
    8921042    if (fits_read_col(cSDptr, TSHORT, cData[IF].colnum, 1, 1, cNRow,
    8931043                      &IFNul, IFCol, &anynul, &cStatus)) {
    894       reportError();
    8951044      delete [] IFCol;
     1045      log(LogOrigin( className, methodName, WHERE ), LogIO::SEVERE);
    8961046      close();
    8971047      return 1;
     
    9561106        double* &positions)
    9571107{
    958   int anynul;
     1108  const string methodName = "findRange()" ;
    9591109
    9601110  // Has the file been opened?
     
    9661116
    9671117  // Find the number of rows selected.
    968   short *sel = new short[nRow];
    969   for (int irow = 0; irow < nRow; irow++) {
     1118  short *sel = new short[cNRow];
     1119  for (int irow = 0; irow < cNRow; irow++) {
    9701120    sel[irow] = 1;
    9711121  }
    9721122
     1123  int anynul;
    9731124  if (cData[BEAM].colnum > 0) {
    9741125    short *beamCol = new short[cNRow];
     
    9761127    if (fits_read_col(cSDptr, TSHORT, cData[BEAM].colnum, 1, 1, cNRow,
    9771128                      &beamNul, beamCol, &anynul, &cStatus)) {
    978       reportError();
    9791129      delete [] beamCol;
    9801130      delete [] sel;
     1131      log(LogOrigin( className, methodName, WHERE ), LogIO::SEVERE);
    9811132      return 1;
    9821133    }
    9831134
    984     for (int irow = 0; irow < nRow; irow++) {
     1135    for (int irow = 0; irow < cNRow; irow++) {
    9851136      if (!cBeams[beamCol[irow]-cBeam_1rel]) {
    9861137        sel[irow] = 0;
     
    9961147    if (fits_read_col(cSDptr, TSHORT, cData[IF].colnum, 1, 1, cNRow,
    9971148                      &IFNul, IFCol, &anynul, &cStatus)) {
    998       reportError();
    9991149      delete [] IFCol;
    10001150      delete [] sel;
     1151      log(LogOrigin( className, methodName, WHERE ), LogIO::SEVERE);
    10011152      return 1;
    10021153    }
    10031154
    1004     for (int irow = 0; irow < nRow; irow++) {
     1155    for (int irow = 0; irow < cNRow; irow++) {
    10051156      if (!cIFs[IFCol[irow]-cIF_1rel]) {
    10061157        sel[irow] = 0;
     
    10121163
    10131164  nSel = 0;
    1014   for (int irow = 0; irow < nRow; irow++) {
     1165  for (int irow = 0; irow < cNRow; irow++) {
    10151166    nSel += sel[irow];
    10161167  }
     
    10181169
    10191170  // Find the time range assuming the data is in chronological order.
    1020   readData(DATE_OBS, 1,    dateSpan[0]);
    1021   readData(DATE_OBS, nRow, dateSpan[1]);
    1022   readData(TIME, 1,    utcSpan);
    1023   readData(TIME, nRow, utcSpan+1);
    1024 
    1025   if (cALFA_BD) {
    1026     utcSpan[0] *= 3600.0;
    1027     utcSpan[1] *= 3600.0;
    1028   }
    1029 
    1030   // Check DATE-OBS format.
    1031   for (int i = 0; i < 2; i++) {
    1032     if (dateSpan[0][2] == '/') {
    1033       // Translate an old-format DATE-OBS.
    1034       dateSpan[i][9] = dateSpan[i][1];
    1035       dateSpan[i][8] = dateSpan[i][0];
    1036       dateSpan[i][2] = dateSpan[i][6];
    1037       dateSpan[i][5] = dateSpan[i][3];
    1038       dateSpan[i][3] = dateSpan[i][7];
    1039       dateSpan[i][6] = dateSpan[i][4];
    1040       dateSpan[i][7] = '-';
    1041       dateSpan[i][4] = '-';
    1042       dateSpan[i][1] = '9';
    1043       dateSpan[i][0] = '1';
    1044       dateSpan[i][10] = '\0';
    1045     }
    1046 
    1047     if (dateSpan[i][10] == 'T' && cData[TIME].colnum < 0) {
    1048       // Dig UTC out of a new-format DATE-OBS.
    1049       int   hh, mm;
    1050       float ss;
    1051       sscanf(dateSpan[i]+11, "%d:%d:%f", &hh, &mm, &ss);
    1052       utcSpan[i] = (hh*60 + mm)*60 + ss;
    1053     }
    1054   }
     1171  readTime(1, 1, dateSpan[0], utcSpan[0]);
     1172  readTime(cNRow, cNAxisTime, dateSpan[1], utcSpan[1]);
    10551173
    10561174
    10571175  // Retrieve positions for selected data.
    1058   double *ra  = new double[cNRow];
    1059   double *dec = new double[cNRow];
    1060   fits_read_col(cSDptr, TDOUBLE, cData[RA].colnum,  1, 1, nRow, 0, ra,
    1061                 &anynul, &cStatus);
    1062   fits_read_col(cSDptr, TDOUBLE, cData[DEC].colnum, 1, 1, nRow, 0, dec,
    1063                 &anynul, &cStatus);
    1064 
    1065   if (cALFA_BD) {
    1066     for (int irow = 0; irow < nRow; irow++) {
    1067       // Convert hours to degrees.
    1068       ra[irow] *= 15.0;
    1069     }
    1070   }
    1071 
    10721176  int isel = 0;
    10731177  positions = new double[2*nSel];
    10741178
    1075   // Parameters needed to compute feed-plane coordinates.
    1076   double *srcRA, *srcDec;
    1077   float  *par, *rot;
    1078   if (cGetFeedPos) {
    1079     srcRA  = new double[cNRow];
    1080     srcDec = new double[cNRow];
    1081     par    = new float[cNRow];
    1082     rot    = new float[cNRow];
    1083     fits_read_col(cSDptr, TDOUBLE, cData[OBJ_RA].colnum,   1, 1, nRow, 0,
    1084                   srcRA,  &anynul, &cStatus);
    1085     fits_read_col(cSDptr, TDOUBLE, cData[OBJ_DEC].colnum,  1, 1, nRow, 0,
    1086                   srcDec, &anynul, &cStatus);
    1087     fits_read_col(cSDptr, TFLOAT,  cData[PARANGLE].colnum, 1, 1, nRow, 0,
    1088                   par,    &anynul, &cStatus);
    1089     fits_read_col(cSDptr, TFLOAT,  cData[FOCUSROT].colnum, 1, 1, nRow, 0,
    1090                   rot,    &anynul, &cStatus);
    1091 
    1092     for (int irow = 0; irow < nRow; irow++) {
    1093       if (sel[irow]) {
    1094         // Convert to feed-plane coordinates.
    1095         Double dist, pa;
    1096         distPA(ra[irow]*D2R, dec[irow]*D2R, srcRA[irow]*D2R, srcDec[irow]*D2R,
    1097                dist, pa);
    1098 
    1099         Double spin = (par[irow] + rot[irow])*D2R - pa + PI;
    1100         if (spin > 2.0*PI) spin -= 2.0*PI;
    1101         Double squint = PI/2.0 - dist;
    1102 
    1103         positions[isel++] = spin;
    1104         positions[isel++] = squint;
    1105       }
    1106     }
    1107 
    1108     delete [] srcRA;
    1109     delete [] srcDec;
    1110     delete [] par;
    1111     delete [] rot;
     1179  if (cCoordSys == 1) {
     1180    // Horizontal (Az,El).
     1181    if (cData[AZIMUTH].colnum  < 0 ||
     1182        cData[ELEVATIO].colnum < 0) {
     1183      log(LogOrigin( className, methodName, WHERE ), LogIO::WARN, "Azimuth/elevation information absent.");
     1184      cStatus = -1;
     1185
     1186    } else {
     1187      float *az = new float[cNRow];
     1188      float *el = new float[cNRow];
     1189      readCol(AZIMUTH,  az);
     1190      readCol(ELEVATIO, el);
     1191
     1192      if (!cStatus) {
     1193        for (int irow = 0; irow < cNRow; irow++) {
     1194          if (sel[irow]) {
     1195            positions[isel++] = az[irow] * D2R;
     1196            positions[isel++] = el[irow] * D2R;
     1197          }
     1198        }
     1199      }
     1200
     1201      delete [] az;
     1202      delete [] el;
     1203    }
     1204
     1205  } else if (cCoordSys == 3) {
     1206    // ZPA-EL.
     1207    if (cData[BEAM].colnum < 0 ||
     1208        cData[FOCUSROT].colnum < 0 ||
     1209        cData[ELEVATIO].colnum < 0) {
     1210      log(LogOrigin( className, methodName, WHERE ), LogIO::WARN, "ZPA/elevation information absent.");
     1211      cStatus = -1;
     1212
     1213    } else {
     1214      short *beam = new short[cNRow];
     1215      float *rot  = new float[cNRow];
     1216      float *el   = new float[cNRow];
     1217      readCol(BEAM,     beam);
     1218      readCol(FOCUSROT, rot);
     1219      readCol(ELEVATIO, el);
     1220
     1221      if (!cStatus) {
     1222        for (int irow = 0; irow < cNRow; irow++) {
     1223          if (sel[irow]) {
     1224            Int beamNo = beam[irow];
     1225            Double zpa = rot[irow];
     1226            if (beamNo > 1) {
     1227              // Beam geometry for the Parkes multibeam.
     1228              if (beamNo < 8) {
     1229                zpa += -60.0 + 60.0*(beamNo-2);
     1230              } else {
     1231                zpa += -90.0 + 60.0*(beamNo-8);
     1232              }
     1233
     1234              if (zpa < -180.0) {
     1235                zpa += 360.0;
     1236              } else if (zpa > 180.0) {
     1237                zpa -= 360.0;
     1238              }
     1239            }
     1240
     1241            positions[isel++] = zpa * D2R;
     1242            positions[isel++] = el[irow] * D2R;
     1243          }
     1244        }
     1245      }
     1246
     1247      delete [] beam;
     1248      delete [] rot;
     1249      delete [] el;
     1250    }
    11121251
    11131252  } else {
    1114     for (int irow = 0; irow < nRow; irow++) {
    1115       if (sel[irow]) {
    1116         positions[isel++] =  ra[irow] * D2R;
    1117         positions[isel++] = dec[irow] * D2R;
    1118       }
    1119     }
    1120   }
    1121 
     1253    double *ra  = new double[cNRow];
     1254    double *dec = new double[cNRow];
     1255    readCol(RA,  ra);
     1256    readCol(DEC, dec);
     1257
     1258    if (cStatus) {
     1259      delete [] ra;
     1260      delete [] dec;
     1261      goto cleanup;
     1262    }
     1263
     1264    if (cALFA_BD) {
     1265      for (int irow = 0; irow < cNRow; irow++) {
     1266        // Convert hours to degrees.
     1267        ra[irow] *= 15.0;
     1268      }
     1269    }
     1270
     1271    if (cCoordSys == 0) {
     1272      // Equatorial (RA,Dec).
     1273      for (int irow = 0; irow < cNRow; irow++) {
     1274        if (sel[irow]) {
     1275          positions[isel++] =  ra[irow] * D2R;
     1276          positions[isel++] = dec[irow] * D2R;
     1277        }
     1278      }
     1279
     1280    } else if (cCoordSys == 2) {
     1281      // Feed-plane.
     1282      if (cData[OBJ_RA].colnum   < 0 ||
     1283          cData[OBJ_DEC].colnum  < 0 ||
     1284          cData[PARANGLE].colnum < 0 ||
     1285          cData[FOCUSROT].colnum < 0) {
     1286        log( LogOrigin( className, methodName, WHERE ), LogIO::WARN,
     1287             "Insufficient information to compute feed-plane\n"
     1288             "         coordinates.");
     1289        cStatus = -1;
     1290
     1291      } else {
     1292        double *srcRA  = new double[cNRow];
     1293        double *srcDec = new double[cNRow];
     1294        float  *par = new float[cNRow];
     1295        float  *rot = new float[cNRow];
     1296
     1297        readCol(OBJ_RA,   srcRA);
     1298        readCol(OBJ_DEC,  srcDec);
     1299        readCol(PARANGLE, par);
     1300        readCol(FOCUSROT, rot);
     1301
     1302        if (!cStatus) {
     1303          for (int irow = 0; irow < cNRow; irow++) {
     1304            if (sel[irow]) {
     1305              // Convert to feed-plane coordinates.
     1306              Double dist, pa;
     1307              distPA(ra[irow]*D2R, dec[irow]*D2R, srcRA[irow]*D2R,
     1308                     srcDec[irow]*D2R, dist, pa);
     1309
     1310              Double spin = (par[irow] + rot[irow])*D2R - pa;
     1311              if (spin > 2.0*PI) spin -= 2.0*PI;
     1312              Double squint = PI/2.0 - dist;
     1313
     1314              positions[isel++] = spin;
     1315              positions[isel++] = squint;
     1316            }
     1317          }
     1318        }
     1319
     1320        delete [] srcRA;
     1321        delete [] srcDec;
     1322        delete [] par;
     1323        delete [] rot;
     1324      }
     1325    }
     1326
     1327    delete [] ra;
     1328    delete [] dec;
     1329  }
     1330
     1331cleanup:
    11221332  delete [] sel;
    1123   delete [] ra;
    1124   delete [] dec;
    1125 
    1126   return cStatus;
     1333
     1334  if (cStatus) {
     1335    nSel = 0;
     1336    delete [] positions;
     1337    log(LogOrigin( className, methodName, WHERE ), LogIO::SEVERE);
     1338    cStatus = 0;
     1339    return 1;
     1340  }
     1341
     1342  return 0;
    11271343}
    11281344
     
    11331349
    11341350int SDFITSreader::read(
    1135         PKSMBrecord &mbrec)
     1351        MBrecord &mbrec)
    11361352{
     1353  const string methodName = "read()" ;
     1354
    11371355  // Has the file been opened?
    11381356  if (!cSDptr) {
    11391357    return 1;
    11401358  }
    1141 
    11421359  // Find the next selected beam and IF.
    11431360  short iBeam = 0, iIF = 0;
    1144   while (++cRow <= cNRow) {
     1361  int iPol = -1 ;
     1362  while (1) {
     1363    if (++cTimeIdx > cNAxisTime) {
     1364      if (++cRow > cNRow) break;
     1365      cTimeIdx = 1;
     1366    }
     1367
    11451368    if (cData[BEAM].colnum > 0) {
    11461369      readData(BEAM, cRow, &iBeam);
     
    11641387          char chars[32];
    11651388          readData(OBSMODE, cRow, chars);
    1166           if (strcmp(chars, "CAL") == 0) {
    1167             // iIF is really the polarization in ALFA data.
    1168             alfaCal(iBeam, iIF);
     1389          if (strcmp(chars, "DROP") == 0) {
     1390            // Completely flagged integration.
    11691391            continue;
     1392
     1393          } else if (strcmp(chars, "CAL") == 0) {
     1394            sReset = 1;
     1395            if (cALFA_CIMA > 1) {
     1396              for (short iPol = 0; iPol < cNPol[iIF]; iPol++) {
     1397                alfaCal(iBeam, iIF, iPol);
     1398              }
     1399              continue;
     1400            } else {
     1401              // iIF is really the polarization in older ALFA data.
     1402              alfaCal(iBeam, 0, iIF);
     1403              continue;
     1404            }
     1405
     1406          } else {
     1407            // Reset for the next CAL record.
     1408            if (sReset) {
     1409              for (short iPol = 0; iPol < cNPol[iIF]; iPol++) {
     1410                sALFAcalNon[iBeam][iPol]  = 0;
     1411                sALFAcalNoff[iBeam][iPol] = 0;
     1412                sALFAcalOn[iBeam][iPol]   = 0.0f;
     1413                sALFAcalOff[iBeam][iPol]  = 0.0f;
     1414              }
     1415              sReset = 0;
     1416
     1417              sprintf(cMsg, "ALFA cal factors for beam %d: %.3e, %.3e",
     1418                iBeam+1, sALFAcal[iBeam][0], sALFAcal[iBeam][1]);
     1419              log(LogOrigin( className, methodName, WHERE ), LogIO::NORMAL, cMsg);
     1420              //logMsg(cMsg);
     1421            }
    11701422          }
    11711423        }
    11721424
     1425        // for GBT SDFITS
     1426        if (cData[STOKES].colnum > 0 ) {
     1427          readData(STOKES, cRow, &iPol ) ;
     1428          for ( int i = 0 ; i < cNPol[iIF] ; i++ ) {
     1429            if ( cPols[i] == iPol ) {
     1430              iPol = i ;
     1431              break ;
     1432            }
     1433          }
     1434        }
    11731435        break;
    11741436      }
     
    12001462  // Times.
    12011463  char datobs[32];
    1202   readData(DATE_OBS, cRow,  datobs);
    1203   readData(TIME,     cRow, &mbrec.utc);
    1204   if (cALFA_BD) mbrec.utc *= 3600.0;
    1205 
    1206   if (datobs[2] == '/') {
    1207     // Translate an old-format DATE-OBS.
    1208     datobs[9] = datobs[1];
    1209     datobs[8] = datobs[0];
    1210     datobs[2] = datobs[6];
    1211     datobs[5] = datobs[3];
    1212     datobs[3] = datobs[7];
    1213     datobs[6] = datobs[4];
    1214     datobs[7] = '-';
    1215     datobs[4] = '-';
    1216     datobs[1] = '9';
    1217     datobs[0] = '1';
    1218 
    1219   } else if (datobs[10] == 'T' && cData[TIME].colnum < 0) {
    1220     // Dig UTC out of a new-format DATE-OBS.
    1221     int   hh, mm;
    1222     float ss;
    1223     sscanf(datobs+11, "%d:%d:%f", &hh, &mm, &ss);
    1224     mbrec.utc = (hh*60 + mm)*60 + ss;
    1225   }
    1226 
    1227   datobs[10] = '\0';
     1464  readTime(cRow, cTimeIdx, datobs, mbrec.utc);
    12281465  strcpy(mbrec.datobs, datobs);
    12291466
    12301467  if (cData[CYCLE].colnum > 0) {
    12311468    readData(CYCLE, cRow, &mbrec.cycleNo);
     1469    mbrec.cycleNo += cTimeIdx - 1;
    12321470    if (cALFA_BD) mbrec.cycleNo++;
    12331471  } else {
     
    12391477  }
    12401478
     1479  if ( iPol != -1 ) {
     1480    if ( mbrec.scanNo != cGLastScan[iPol] ) {
     1481      cGLastScan[iPol] = mbrec.scanNo ;
     1482      cGCycleNo[iPol] = 0 ;
     1483      mbrec.cycleNo = ++cGCycleNo[iPol] ;
     1484    }
     1485    else {
     1486      mbrec.cycleNo = ++cGCycleNo[iPol] ;
     1487    }
     1488  }
     1489
    12411490  readData(EXPOSURE, cRow, &mbrec.exposure);
    12421491
    12431492  // Source identification.
    1244   readData(OBJECT,  cRow,  mbrec.srcName);
     1493  readData(OBJECT, cRow, mbrec.srcName);
     1494
     1495  if ( iPol != -1 ) {
     1496    char obsmode[32] ;
     1497    readData( OBSMODE, cRow, obsmode ) ;
     1498    char sig[1] ;
     1499    char cal[1] ;
     1500    readData( SIG, cRow, sig ) ;
     1501    readData( CAL, cRow, cal ) ;
     1502    if ( strstr( obsmode, "PSWITCH" ) != NULL ) {
     1503      // position switch
     1504      strcat( mbrec.srcName, "_p" ) ;
     1505      if ( strstr( obsmode, "PSWITCHON" ) != NULL ) {
     1506        strcat( mbrec.srcName, "s" ) ;
     1507      }
     1508      else if ( strstr( obsmode, "PSWITCHOFF" ) != NULL ) {
     1509        strcat( mbrec.srcName, "r" ) ;
     1510      }
     1511    }
     1512    else if ( strstr( obsmode, "Nod" ) != NULL ) {
     1513      // nod
     1514      strcat( mbrec.srcName, "_n" ) ;
     1515      if ( sig[0] == 'T' ) {
     1516        strcat( mbrec.srcName, "s" ) ;
     1517      }
     1518      else {
     1519        strcat( mbrec.srcName, "r" ) ;
     1520      }
     1521    }
     1522    else if ( strstr( obsmode, "FSWITCH" ) != NULL ) {
     1523      // frequency switch
     1524      strcat( mbrec.srcName, "_f" ) ;
     1525      if ( sig[0] == 'T' ) {
     1526        strcat( mbrec.srcName, "s" ) ;
     1527      }
     1528      else {
     1529        strcat( mbrec.srcName, "r" ) ;
     1530      }
     1531    }
     1532    if ( cal[0] == 'T' ) {
     1533      strcat( mbrec.srcName, "c" ) ;
     1534    }
     1535    else {
     1536      strcat( mbrec.srcName, "o" ) ;
     1537    }
     1538  }
    12451539
    12461540  readData(OBJ_RA,  cRow, &mbrec.srcRA);
     
    12791573    mbrec.decRate = scanrate[1] * D2R;
    12801574  }
     1575  mbrec.paRate = 0.0f;
    12811576
    12821577  // IF-dependent parameters.
     
    12891584  int nPol = cNPol[iIF];
    12901585
     1586  if ( cData[STOKES].colnum > 0 )
     1587    nPol = 1 ;
     1588
    12911589  if (cGetSpectra || cGetXPol) {
    12921590    int nxpol = cGetXPol ? 2*nChan : 0;
     
    12981596  mbrec.nChan[0] = nChan;
    12991597  mbrec.nPol[0]  = nPol;
     1598  mbrec.polNo = iPol ;
    13001599
    13011600  readData(FqRefPix, cRow, mbrec.fqRefPix);
     
    13161615
    13171616  if (cStatus) {
    1318     reportError();
     1617    log(LogOrigin( className, methodName, WHERE ), LogIO::SEVERE);
    13191618    return 1;
    13201619  }
     
    13531652
    13541653  if (cStatus) {
    1355     reportError();
     1654    log(LogOrigin( className, methodName, WHERE ), LogIO::SEVERE);
    13561655    return 1;
    13571656  }
    13581657
    13591658  // Read data, sectioning and transposing it in the process.
    1360   long *blc = new long[cNAxis+1];
    1361   long *trc = new long[cNAxis+1];
    1362   long *inc = new long[cNAxis+1];
    1363   for (int iaxis = 0; iaxis <= cNAxis; iaxis++) {
     1659  long *blc = new long[cNAxes+1];
     1660  long *trc = new long[cNAxes+1];
     1661  long *inc = new long[cNAxes+1];
     1662  for (int iaxis = 0; iaxis <= cNAxes; iaxis++) {
    13641663    blc[iaxis] = 1;
    13651664    trc[iaxis] = 1;
     
    13671666  }
    13681667
    1369   blc[cReqax[0]] = std::min(startChan, endChan);
    1370   trc[cReqax[0]] = std::max(startChan, endChan);
    1371   blc[cNAxis] = cRow;
    1372   trc[cNAxis] = cRow;
     1668  blc[cFreqAxis] = std::min(startChan, endChan);
     1669  trc[cFreqAxis] = std::max(startChan, endChan);
     1670  if (cTimeAxis >= 0) {
     1671    blc[cTimeAxis] = cTimeIdx;
     1672    trc[cTimeAxis] = cTimeIdx;
     1673  }
     1674  blc[cNAxes] = cRow;
     1675  trc[cNAxes] = cRow;
    13731676
    13741677  mbrec.haveSpectra = cGetSpectra;
     
    13761679    int  anynul;
    13771680
    1378     for (int ipol = 0; ipol < nPol; ipol++) {
    1379       blc[cReqax[1]] = ipol+1;
    1380       trc[cReqax[1]] = ipol+1;
    1381 
    1382       if (cALFA) {
     1681    for (int iPol = 0; iPol < nPol; iPol++) {
     1682      blc[cStokesAxis] = iPol+1;
     1683      trc[cStokesAxis] = iPol+1;
     1684
     1685      if (cALFA && cALFA_CIMA < 2) {
    13831686        // ALFA data: polarizations are stored in successive rows.
    1384         blc[cReqax[1]] = 1;
    1385         trc[cReqax[1]] = 1;
    1386 
    1387         if (ipol) {
     1687        blc[cStokesAxis] = 1;
     1688        trc[cStokesAxis] = 1;
     1689
     1690        if (iPol) {
    13881691          if (++cRow > cNRow) {
    13891692            return -1;
    13901693          }
    13911694
    1392           blc[cNAxis] = cRow;
    1393           trc[cNAxis] = cRow;
     1695          blc[cNAxes] = cRow;
     1696          trc[cNAxes] = cRow;
    13941697        }
    13951698
    13961699      } else if (cData[DATA].nelem < 0) {
    13971700        // Variable dimension array; get axis lengths.
    1398         int  naxis = 5, status;
    1399 
    1400         if ((status = readDim(DATA, cRow, &naxis, cNAxes))) {
    1401           reportError();
    1402 
    1403         } else if ((status = (naxis != cNAxis))) {
    1404           cerr << "DATA array dimensions changed." << endl;
     1701        int naxes = 5, status;
     1702
     1703        if ((status = readDim(DATA, cRow, &naxes, cNAxis))) {
     1704          log(LogOrigin( className, methodName, WHERE ), LogIO::SEVERE);
     1705
     1706        } else if ((status = (naxes != cNAxes))) {
     1707          log(LogOrigin( className, methodName, WHERE ), LogIO::SEVERE, "DATA array dimensions changed.");
    14051708        }
    14061709
     
    14131716      }
    14141717
    1415       if (fits_read_subset_flt(cSDptr, cData[DATA].colnum, cNAxis, cNAxes,
    1416           blc, trc, inc, 0, mbrec.spectra[0] + ipol*nChan, &anynul,
     1718      if (fits_read_subset_flt(cSDptr, cData[DATA].colnum, cNAxes, cNAxis,
     1719          blc, trc, inc, 0, mbrec.spectra[0] + iPol*nChan, &anynul,
    14171720          &cStatus)) {
    1418         reportError();
     1721        log(LogOrigin( className, methodName, WHERE ), LogIO::SEVERE);
    14191722        delete [] blc;
    14201723        delete [] trc;
     
    14251728      if (endChan < startChan) {
    14261729        // Reverse the spectrum.
    1427         float *iptr = mbrec.spectra[0] + ipol*nChan;
     1730        float *iptr = mbrec.spectra[0] + iPol*nChan;
    14281731        float *jptr = iptr + nChan - 1;
    14291732        float *mid  = iptr + nChan/2;
     
    14371740      if (cALFA) {
    14381741        // ALFA data, rescale the spectrum.
    1439         float *chan  = mbrec.spectra[0] + ipol*nChan;
     1742        float el, zd;
     1743        readData(ELEVATIO, cRow, &el);
     1744        zd = 90.0f - el;
     1745
     1746        float factor = sALFAcal[iBeam][iPol] / alfaGain(zd);
     1747
     1748        if (cALFA_CIMA > 1) {
     1749          // Rescale according to the number of unblanked accumulations.
     1750          int colnum, naccum;
     1751          findCol("STAT", &colnum);
     1752          fits_read_col(cSDptr, TINT, colnum, cRow, 10*(cTimeIdx-1)+2, 1, 0,
     1753                        &naccum, &anynul, &cStatus);
     1754          factor *= cALFAacc / naccum;
     1755        }
     1756
     1757        float *chan  = mbrec.spectra[0] + iPol*nChan;
    14401758        float *chanN = chan + nChan;
    14411759        while (chan < chanN) {
    14421760          // Approximate conversion to Jy.
    1443           *(chan++) *= cALFAcal[iBeam][iIF];
     1761          *(chan++) *= factor;
    14441762        }
    14451763      }
    14461764
    1447       if (mbrec.tsys[0][ipol] == 0.0) {
     1765      if (mbrec.tsys[0][iPol] == 0.0) {
    14481766        // Compute Tsys as the average across the spectrum.
    1449         float *chan  = mbrec.spectra[0] + ipol*nChan;
     1767        float *chan  = mbrec.spectra[0] + iPol*nChan;
    14501768        float *chanN = chan + nChan;
    1451         float *tsys = mbrec.tsys[0] + ipol;
     1769        float *tsys = mbrec.tsys[0] + iPol;
    14521770        while (chan < chanN) {
    14531771          *tsys += *(chan++);
     
    14591777      // Read data flags.
    14601778      if (cData[FLAGGED].colnum > 0) {
    1461         if (fits_read_subset_byt(cSDptr, cData[FLAGGED].colnum, cNAxis,
    1462             cNAxes, blc, trc, inc, 0, mbrec.flagged[0] + ipol*nChan, &anynul,
     1779        if (fits_read_subset_byt(cSDptr, cData[FLAGGED].colnum, cNAxes,
     1780            cNAxis, blc, trc, inc, 0, mbrec.flagged[0] + iPol*nChan, &anynul,
    14631781            &cStatus)) {
    1464           reportError();
     1782          log(LogOrigin( className, methodName, WHERE ), LogIO::SEVERE);
    14651783          delete [] blc;
    14661784          delete [] trc;
     
    14711789        if (endChan < startChan) {
    14721790          // Reverse the flag vector.
    1473           unsigned char *iptr = mbrec.flagged[0] + ipol*nChan;
     1791          unsigned char *iptr = mbrec.flagged[0] + iPol*nChan;
    14741792          unsigned char *jptr = iptr + nChan - 1;
    14751793          for (int ichan = 0; ichan < nChan/2; ichan++) {
     
    14821800      } else {
    14831801        // All channels are unflagged by default.
    1484         unsigned char *iptr = mbrec.flagged[0] + ipol*nChan;
     1802        unsigned char *iptr = mbrec.flagged[0] + iPol*nChan;
    14851803        for (int ichan = 0; ichan < nChan; ichan++) {
    14861804          *(iptr++) = 0;
     
    15131831    if (fits_read_subset_flt(cSDptr, cData[XPOLDATA].colnum, nAxis, nAxes,
    15141832        blc, trc, inc, 0, mbrec.xpol[0], &anynul, &cStatus)) {
    1515       reportError();
     1833      log(LogOrigin( className, methodName, WHERE ), LogIO::SEVERE);
    15161834      delete [] blc;
    15171835      delete [] trc;
     
    15441862
    15451863  if (cStatus) {
    1546     reportError();
     1864    log(LogOrigin( className, methodName, WHERE ), LogIO::SEVERE);
    15471865    return 1;
    15481866  }
     
    15521870  readData(TCAL,     cRow, &mbrec.tcal[0]);
    15531871  readData(TCALTIME, cRow,  mbrec.tcalTime);
     1872
    15541873  readData(AZIMUTH,  cRow, &mbrec.azimuth);
    15551874  readData(ELEVATIO, cRow, &mbrec.elevation);
    15561875  readData(PARANGLE, cRow, &mbrec.parAngle);
     1876
    15571877  readData(FOCUSAXI, cRow, &mbrec.focusAxi);
    15581878  readData(FOCUSTAN, cRow, &mbrec.focusTan);
    15591879  readData(FOCUSROT, cRow, &mbrec.focusRot);
     1880
    15601881  readData(TAMBIENT, cRow, &mbrec.temp);
    15611882  readData(PRESSURE, cRow, &mbrec.pressure);
     
    15751896  mbrec.windAz    *= D2R;
    15761897
     1898  // For GBT data, source velocity can be evaluated
     1899  if ( cData[RVSYS].colnum > 0 && cData[VFRAME].colnum > 0 ) {
     1900    float vframe;
     1901    readData(VFRAME, cRow, &vframe);
     1902    float rvsys;
     1903    readData(RVSYS,  cRow, &rvsys);
     1904    //mbrec.srcVelocity = rvsys - vframe ;
     1905    mbrec.srcVelocity = rvsys ;
     1906  }
     1907
    15771908  if (cStatus) {
    1578     reportError();
     1909    log(LogOrigin( className, methodName, WHERE ), LogIO::SEVERE);
    15791910    return 1;
    15801911  }
    15811912
    15821913  return 0;
    1583 }
    1584 
    1585 
    1586 //------------------------------------------------------ SDFITSreader::alfaCal
    1587 
    1588 // Process ALFA calibration data.
    1589 
    1590 int SDFITSreader::alfaCal(
    1591         short iBeam,
    1592         short iPol)
    1593 {
    1594   int  calOn;
    1595   char chars[32];
    1596   if (cALFA_BD) {
    1597     readData("OBS_NAME", TSTRING, cRow, chars);
    1598   } else {
    1599     readData("SCANTYPE", TSTRING, cRow, chars);
    1600   }
    1601 
    1602   if (strcmp(chars, "ON") == 0) {
    1603     calOn = 1;
    1604   } else if (strcmp(chars, "OFF") == 0) {
    1605     calOn = 0;
    1606   } else {
    1607     return 1;
    1608   }
    1609 
    1610   // Read cal data.
    1611   long *blc = new long[cNAxis+1];
    1612   long *trc = new long[cNAxis+1];
    1613   long *inc = new long[cNAxis+1];
    1614   for (int iaxis = 0; iaxis <= cNAxis; iaxis++) {
    1615     blc[iaxis] = 1;
    1616     trc[iaxis] = 1;
    1617     inc[iaxis] = 1;
    1618   }
    1619 
    1620   // User channel selection.
    1621   int startChan = cStartChan[0];
    1622   int endChan   = cEndChan[0];
    1623 
    1624   blc[cNAxis] = cRow;
    1625   trc[cNAxis] = cRow;
    1626   blc[cReqax[0]] = std::min(startChan, endChan);
    1627   trc[cReqax[0]] = std::max(startChan, endChan);
    1628   blc[cReqax[1]] = 1;
    1629   trc[cReqax[1]] = 1;
    1630 
    1631   float spectrum[endChan];
    1632   int anynul;
    1633   if (fits_read_subset_flt(cSDptr, cData[DATA].colnum, cNAxis, cNAxes,
    1634       blc, trc, inc, 0, spectrum, &anynul, &cStatus)) {
    1635     reportError();
    1636     delete [] blc;
    1637     delete [] trc;
    1638     delete [] inc;
    1639     return 1;
    1640   }
    1641 
    1642   // Average the spectrum.
    1643   float mean = 1e9f;
    1644   for (int k = 0; k < 2; k++) {
    1645     float discrim = 2.0f * mean;
    1646 
    1647     int nChan = 0;
    1648     float sum = 0.0f;
    1649 
    1650     float *chanN = spectrum + abs(endChan - startChan) + 1;
    1651     for (float *chan = spectrum; chan < chanN; chan++) {
    1652       // Simple discriminant that eliminates strong radar interference.
    1653       if (*chan < discrim) {
    1654         nChan++;
    1655         sum += *chan;
    1656       }
    1657     }
    1658 
    1659     mean = sum / nChan;
    1660   }
    1661 
    1662   if (calOn) {
    1663     cALFAcalOn[iBeam][iPol]  += mean;
    1664   } else {
    1665     cALFAcalOff[iBeam][iPol] += mean;
    1666   }
    1667 
    1668   if (cALFAcalOn[iBeam][iPol] != 0.0f &&
    1669       cALFAcalOff[iBeam][iPol] != 0.0f) {
    1670     // Tcal should come from the TCAL table, it varies weakly with beam,
    1671     // polarization, and frequency.  However, TCAL is not written properly.
    1672     float Tcal = 12.0f;
    1673     cALFAcal[iBeam][iPol] = Tcal / (cALFAcalOn[iBeam][iPol] -
    1674                                     cALFAcalOff[iBeam][iPol]);
    1675 
    1676     // Scale from K to Jy; the gain also varies weakly with beam,
    1677     // polarization, frequency, and zenith angle.
    1678     float fluxCal = 10.0f;
    1679     cALFAcal[iBeam][iPol] /= fluxCal;
    1680 
    1681     cALFAcalOn[iBeam][iPol]  = 0.0f;
    1682     cALFAcalOff[iBeam][iPol] = 0.0f;
    1683   }
    1684 
    1685   return 0;
    1686 }
    1687 
    1688 
    1689 //-------------------------------------------------- SDFITSreader::reportError
    1690 
    1691 // Print the error message corresponding to the input status value and all the
    1692 // messages on the CFITSIO error stack to stderr.
    1693 
    1694 void SDFITSreader::reportError()
    1695 {
    1696   fits_report_error(stderr, cStatus);
    16971914}
    16981915
     
    17061923    int status = 0;
    17071924    fits_close_file(cSDptr, &status);
    1708     cSDptr = 0;
     1925    cSDptr = 0x0;
    17091926
    17101927    if (cBeams)     delete [] cBeams;
     
    17141931    if (cRefChan)   delete [] cRefChan;
    17151932  }
     1933}
     1934
     1935//------------------------------------------------------- SDFITSreader::log
     1936
     1937// Log a message.  If the current CFITSIO status value is non-zero, also log
     1938// the corresponding error message and the CFITSIO message stack.
     1939
     1940void SDFITSreader::log(LogOrigin origin, LogIO::Command cmd, const char *msg)
     1941{
     1942  LogIO os( origin ) ;
     1943
     1944  os << msg << endl ;
     1945
     1946  if (cStatus > 0) {
     1947    fits_get_errstatus(cStatus, cMsg);
     1948    os << cMsg << endl ;
     1949
     1950    while (fits_read_errmsg(cMsg)) {
     1951      os << cMsg << endl ;
     1952    }
     1953  }
     1954  os << LogIO::POST ;
    17161955}
    17171956
     
    17371976    long nelem, width;
    17381977    fits_get_coltype(cSDptr, colnum, &coltype, &nelem, &width, &cStatus);
     1978    fits_get_bcolparms(cSDptr, colnum, 0x0, cData[iData].units, 0x0, 0x0, 0x0,
     1979      0x0, 0x0, 0x0, &cStatus);
    17391980
    17401981    // Look for a TDIMnnn keyword or column.
     
    17682009}
    17692010
     2011//------------------------------------------------------ SDFITSreader::findCol
     2012
     2013// Locate a parameter in the SDFITS file.
     2014
     2015void SDFITSreader::findCol(
     2016        char *name,
     2017        int *colnum)
     2018{
     2019  *colnum = 0;
     2020  int status = 0;
     2021  fits_get_colnum(cSDptr, CASESEN, name, colnum, &status);
     2022
     2023  if (status) {
     2024    // Not a real column - maybe it's virtual.
     2025    char card[81];
     2026
     2027    status = 0;
     2028    fits_read_card(cSDptr, name, card, &status);
     2029    if (status) {
     2030      // Not virtual either.
     2031      *colnum = -1;
     2032    }
     2033
     2034    // Clear error messages.
     2035    fits_clear_errmsg();
     2036  }
     2037}
     2038
    17702039//------------------------------------------------------ SDFITSreader::readDim
    17712040
     
    17752044        int  iData,
    17762045        long iRow,
    1777         int *naxis,
    1778         long naxes[])
     2046        int *naxes,
     2047        long naxis[])
    17792048{
    17802049  int colnum = cData[iData].colnum;
     
    17832052  }
    17842053
    1785   int maxdim = *naxis;
     2054  int maxdim = *naxes;
    17862055  if (cData[iData].tdimcol < 0) {
    17872056    // No TDIMnnn column for this array.
    17882057    if (cData[iData].nelem < 0) {
    17892058      // Variable length array; read the array descriptor.
    1790       *naxis = 1;
     2059      *naxes = 1;
    17912060      long dummy;
    1792       if (fits_read_descript(cSDptr, colnum, iRow, naxes, &dummy, &cStatus)) {
     2061      if (fits_read_descript(cSDptr, colnum, iRow, naxis, &dummy, &cStatus)) {
    17932062        return 1;
    17942063      }
     
    17962065    } else {
    17972066      // Read the repeat count from TFORMnnn.
    1798       if (fits_read_tdim(cSDptr, colnum, maxdim, naxis, naxes, &cStatus)) {
     2067      if (fits_read_tdim(cSDptr, colnum, maxdim, naxes, naxis, &cStatus)) {
    17992068        return 1;
    18002069      }
     
    18142083
    18152084    tp++;
    1816     *naxis = 0;
     2085    *naxes = 0;
    18172086    for (size_t j = 1; j < strlen(tdimval); j++) {
    18182087      if (tdimval[j] == ',' || tdimval[j] == ')') {
    1819         sscanf(tp, "%ld", naxes + (*naxis)++);
     2088        sscanf(tp, "%ld", naxis + (*naxes)++);
    18202089        if (tdimval[j] == ')') break;
    18212090        tp = tdimval + j + 1;
     
    18522121  findCol(name, &colnum);
    18532122
    1854   if (colnum > 0) {
     2123  if (colnum > 0 && iRow > 0) {
    18552124    // Read the first value from the specified row of the table.
    18562125    int  coltype;
     
    19152184        void *value)
    19162185{
    1917   char *name  = cData[iData].name;
    19182186  int  type   = cData[iData].type;
    19192187  int  colnum = cData[iData].colnum;
    1920   long nelem  = cData[iData].nelem;
    1921 
    1922   if (colnum > 0) {
     2188
     2189  if (colnum > 0 && iRow > 0) {
    19232190    // Read the required number of values from the specified row of the table.
     2191    long nelem = cData[iData].nelem;
    19242192    int anynul;
    19252193    if (type == TSTRING) {
     
    19502218  } else if (colnum == 0) {
    19512219    // Read keyword value.
     2220    char *name  = cData[iData].name;
    19522221    fits_read_key(cSDptr, type, name, value, 0, &cStatus);
    19532222
     
    19702239}
    19712240
    1972 //------------------------------------------------------ SDFITSreader::findCol
    1973 
    1974 // Locate a parameter in the SDFITS file.
    1975 
    1976 void SDFITSreader::findCol(
    1977         char *name,
    1978         int *colnum)
     2241//------------------------------------------------------ SDFITSreader::readCol
     2242
     2243// Read a scalar column from the SDFITS file.
     2244
     2245int SDFITSreader::readCol(
     2246        int  iData,
     2247        void *value)
    19792248{
    1980   *colnum = 0;
    1981   int status = 0;
    1982   fits_get_colnum(cSDptr, CASESEN, name, colnum, &status);
    1983 
    1984   if (status) {
    1985     // Not a real column - maybe it's virtual.
    1986     char card[81];
    1987 
    1988     status = 0;
    1989     fits_read_card(cSDptr, name, card, &status);
    1990     if (status) {
    1991       // Not virtual either.
    1992       *colnum = -1;
    1993     }
    1994 
    1995     // Clear error messages.
    1996     fits_clear_errmsg();
    1997   }
     2249  int type = cData[iData].type;
     2250
     2251  if (cData[iData].colnum > 0) {
     2252    // Table column.
     2253    int anynul;
     2254    fits_read_col(cSDptr, type, cData[iData].colnum, 1, 1, cNRow, 0,
     2255                  value, &anynul, &cStatus);
     2256
     2257  } else {
     2258    // Header keyword.
     2259    readData(iData, 0, value);
     2260    for (int irow = 1; irow < cNRow; irow++) {
     2261      if (type == TSHORT) {
     2262        ((short *)value)[irow] = *((short *)value);
     2263      } else if (type == TINT) {
     2264        ((int *)value)[irow] = *((int *)value);
     2265      } else if (type == TFLOAT) {
     2266        ((float *)value)[irow] = *((float *)value);
     2267      } else if (type == TDOUBLE) {
     2268        ((double *)value)[irow] = *((double *)value);
     2269      }
     2270    }
     2271  }
     2272
     2273  return cData[iData].colnum < 0;
    19982274}
     2275
     2276//----------------------------------------------------- SDFITSreader::readTime
     2277
     2278// Read the time from the SDFITS file.
     2279
     2280int SDFITSreader::readTime(
     2281        long iRow,
     2282        int  iPix,
     2283        char   *datobs,
     2284        double &utc)
     2285{
     2286  readData(DATE_OBS, iRow, datobs);
     2287  if (cData[TIME].colnum >= 0) {
     2288    readData(TIME, iRow, &utc);
     2289  } else if (cGBT) {
     2290    Int yy, mm ;
     2291    Double dd, hour, min, sec ;
     2292    sscanf( datobs, "%d-%d-%lfT%lf:%lf:%lf", &yy, &mm, &dd, &hour, &min, &sec ) ;
     2293    dd = dd + ( hour * 3600.0 + min * 60.0 + sec ) / 86400.0 ;
     2294    MVTime mvt( yy, mm, dd ) ;
     2295    dd = mvt.day() ;
     2296    utc = fmod( dd, 1.0 ) * 86400.0 ;
     2297  } else if (cNAxisTime > 1) {
     2298    double timeDelt, timeRefPix, timeRefVal;
     2299    readData(TimeRefVal, iRow, &timeRefVal);
     2300    readData(TimeDelt,   iRow, &timeDelt);
     2301    readData(TimeRefPix, iRow, &timeRefPix);
     2302    utc = timeRefVal + (iPix - timeRefPix) * timeDelt;
     2303  }
     2304
     2305  if (cALFA_BD) utc *= 3600.0;
     2306
     2307  // Check DATE-OBS format.
     2308  if (datobs[2] == '/') {
     2309    // Translate an old-format DATE-OBS.
     2310    datobs[9] = datobs[1];
     2311    datobs[8] = datobs[0];
     2312    datobs[2] = datobs[6];
     2313    datobs[5] = datobs[3];
     2314    datobs[3] = datobs[7];
     2315    datobs[6] = datobs[4];
     2316    datobs[7] = '-';
     2317    datobs[4] = '-';
     2318    datobs[1] = '9';
     2319    datobs[0] = '1';
     2320
     2321  } else if (datobs[10] == 'T' && cData[TIME].colnum < 0) {
     2322    // Dig UTC out of a new-format DATE-OBS.
     2323    int   hh, mm;
     2324    float ss;
     2325    sscanf(datobs+11, "%d:%d:%f", &hh, &mm, &ss);
     2326    utc = (hh*60 + mm)*60 + ss;
     2327  }
     2328
     2329  datobs[10] = '\0';
     2330
     2331  return 0;
     2332}
     2333
     2334//------------------------------------------------------ SDFITSreader::alfaCal
     2335
     2336// Process ALFA calibration data.
     2337
     2338int SDFITSreader::alfaCal(
     2339        short iBeam,
     2340        short iIF,
     2341        short iPol)
     2342{
     2343  const string methodName = "alfaCal()" ;
     2344
     2345  int  calOn;
     2346  char chars[32];
     2347  if (cALFA_BD) {
     2348    readData("OBS_NAME", TSTRING, cRow, chars);
     2349  } else {
     2350    readData("SCANTYPE", TSTRING, cRow, chars);
     2351  }
     2352
     2353  if (strcmp(chars, "ON") == 0) {
     2354    calOn = 1;
     2355  } else if (strcmp(chars, "OFF") == 0) {
     2356    calOn = 0;
     2357  } else {
     2358    return 1;
     2359  }
     2360
     2361  // Read cal data.
     2362  long *blc = new long[cNAxes+1];
     2363  long *trc = new long[cNAxes+1];
     2364  long *inc = new long[cNAxes+1];
     2365  for (int iaxis = 0; iaxis <= cNAxes; iaxis++) {
     2366    blc[iaxis] = 1;
     2367    trc[iaxis] = 1;
     2368    inc[iaxis] = 1;
     2369  }
     2370
     2371  // User channel selection.
     2372  int startChan = cStartChan[iIF];
     2373  int endChan   = cEndChan[iIF];
     2374
     2375  blc[cFreqAxis] = std::min(startChan, endChan);
     2376  trc[cFreqAxis] = std::max(startChan, endChan);
     2377  if (cALFA_CIMA > 1) {
     2378    // CIMAFITS 2.x has a legitimate STOKES axis...
     2379    blc[cStokesAxis] = iPol+1;
     2380    trc[cStokesAxis] = iPol+1;
     2381  } else {
     2382    // ...older ALFA data does not.
     2383    blc[cStokesAxis] = 1;
     2384    trc[cStokesAxis] = 1;
     2385  }
     2386  if (cTimeAxis >= 0) {
     2387    blc[cTimeAxis] = cTimeIdx;
     2388    trc[cTimeAxis] = cTimeIdx;
     2389  }
     2390  blc[cNAxes] = cRow;
     2391  trc[cNAxes] = cRow;
     2392
     2393  float spectrum[endChan];
     2394  int anynul;
     2395  if (fits_read_subset_flt(cSDptr, cData[DATA].colnum, cNAxes, cNAxis,
     2396      blc, trc, inc, 0, spectrum, &anynul, &cStatus)) {
     2397    log(LogOrigin( className, methodName, WHERE ), LogIO::SEVERE);
     2398    delete [] blc;
     2399    delete [] trc;
     2400    delete [] inc;
     2401    return 1;
     2402  }
     2403
     2404  // Factor to rescale according to the number of unblanked accumulations.
     2405  float factor = 1.0f;
     2406  if (cALFA_CIMA > 1) {
     2407    int   colnum, naccum;
     2408    findCol("STAT", &colnum);
     2409    fits_read_col(cSDptr, TINT, colnum, cRow, 2, 1, 0, &naccum, &anynul,
     2410                  &cStatus);
     2411    factor = cALFAacc / naccum;
     2412  }
     2413
     2414  // Average the spectrum.
     2415  float mean = 1e9f;
     2416  for (int k = 0; k < 2; k++) {
     2417    float discrim = 2.0f * mean;
     2418
     2419    int nChan = 0;
     2420    float sum = 0.0f;
     2421
     2422    float *chanN = spectrum + abs(endChan - startChan) + 1;
     2423    for (float *chan = spectrum; chan < chanN; chan++) {
     2424      // Simple discriminant that eliminates strong radar interference.
     2425      if (*chan < discrim) {
     2426        nChan++;
     2427        sum += *chan * factor;
     2428      }
     2429    }
     2430
     2431    mean = sum / nChan;
     2432  }
     2433
     2434  if (calOn) {
     2435    sALFAcalOn[iBeam][iPol]  *= sALFAcalNon[iBeam][iPol];
     2436    sALFAcalOn[iBeam][iPol]  += mean;
     2437    sALFAcalOn[iBeam][iPol]  /= ++sALFAcalNon[iBeam][iPol];
     2438  } else {
     2439    sALFAcalOff[iBeam][iPol] *= sALFAcalNoff[iBeam][iPol];
     2440    sALFAcalOff[iBeam][iPol] += mean;
     2441    sALFAcalOff[iBeam][iPol] /= ++sALFAcalNoff[iBeam][iPol];
     2442  }
     2443
     2444  if (sALFAcalNon[iBeam][iPol] && sALFAcalNoff[iBeam][iPol]) {
     2445    // Tcal should come from the TCAL table, it varies weakly with beam,
     2446    // polarization, and frequency.  However, TCAL is not written properly.
     2447    float Tcal = 12.0f;
     2448    sALFAcal[iBeam][iPol] = Tcal / (sALFAcalOn[iBeam][iPol] -
     2449                                    sALFAcalOff[iBeam][iPol]);
     2450
     2451    // Scale from K to Jy; the gain also varies weakly with beam,
     2452    // polarization, frequency, and zenith angle.
     2453    float fluxCal = 10.0f;
     2454    sALFAcal[iBeam][iPol] /= fluxCal;
     2455  }
     2456
     2457  return 0;
     2458}
     2459
     2460//----------------------------------------------------- SDFITSreader::alfaGain
     2461
     2462// ALFA gain factor.
     2463
     2464float SDFITSreader::alfaGain(
     2465        float zd)
     2466{
     2467  // Gain vs zenith distance table from Robert Minchin, 2008/12/08.
     2468  const int nZD = 37;
     2469  const float zdLim[] = {1.5f, 19.5f};
     2470  const float zdInc = (nZD - 1) / (zdLim[1] - zdLim[0]);
     2471  float zdGain[] = {                                       1.00723708,
     2472                    1.16644573,  1.15003645,  1.07117307,  1.02532673,
     2473                    1.01788402,  1.01369524,  1.00000000,  0.989855111,
     2474                    0.990888834, 0.993996620, 0.989964068, 0.982213855,
     2475                    0.978662670, 0.979349494, 0.978478372, 0.974631131,
     2476                    0.972126007, 0.972835243, 0.972742677, 0.968671739,
     2477                    0.963891327, 0.963452935, 0.966831207, 0.969585896,
     2478                    0.970700860, 0.972644389, 0.973754644, 0.967344403,
     2479                    0.952168941, 0.937160134, 0.927843094, 0.914048433,
     2480                    0.886700928, 0.864701211, 0.869126320, 0.854309499};
     2481
     2482  float gain;
     2483  // Do table lookup by linear interpolation.
     2484  float lambda = zdInc * (zd - zdLim[0]);
     2485  int j = int(lambda);
     2486  if (j < 0) {
     2487    gain = zdGain[0];
     2488  } else if (j >= nZD-1) {
     2489    gain = zdGain[nZD-1];
     2490  } else {
     2491    gain = zdGain[j] + (lambda - j) * (zdGain[j+1] - zdGain[j]);
     2492  }
     2493
     2494  return gain;
     2495}
     2496
  • branches/alma/external/atnf/PKSIO/SDFITSreader.h

    r1453 r1757  
    22//# SDFITSreader.h: ATNF CFITSIO interface class for SDFITS input.
    33//#---------------------------------------------------------------------------
    4 //# Copyright (C) 2000-2006
    5 //# Associated Universities, Inc. Washington DC, USA.
     4//# livedata - processing pipeline for single-dish, multibeam spectral data.
     5//# Copyright (C) 2000-2009, Australia Telescope National Facility, CSIRO
    66//#
    7 //# This library is free software; you can redistribute it and/or modify it
    8 //# under the terms of the GNU Library General Public License as published by
    9 //# the Free Software Foundation; either version 2 of the License, or (at your
    10 //# option) any later version.
     7//# This file is part of livedata.
    118//#
    12 //# This library is distributed in the hope that it will be useful, but WITHOUT
     9//# livedata is free software: you can redistribute it and/or modify it under
     10//# the terms of the GNU General Public License as published by the Free
     11//# Software Foundation, either version 3 of the License, or (at your option)
     12//# any later version.
     13//#
     14//# livedata is distributed in the hope that it will be useful, but WITHOUT
    1315//# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    14 //# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Library General Public
    15 //# License for more details.
     16//# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
     17//# more details.
    1618//#
    17 //# You should have received a copy of the GNU Library General Public License
    18 //# along with this library; if not, write to the Free Software Foundation,
    19 //# Inc., 675 Massachusetts Ave, Cambridge, MA 02139, USA.
     19//# You should have received a copy of the GNU General Public License along
     20//# with livedata.  If not, see <http://www.gnu.org/licenses/>.
    2021//#
    21 //# Correspondence concerning this software should be addressed as follows:
    22 //#        Internet email: aips2-request@nrao.edu.
    23 //#        Postal address: AIPS++ Project Office
    24 //#                        National Radio Astronomy Observatory
    25 //#                        520 Edgemont Road
    26 //#                        Charlottesville, VA 22903-2475 USA
     22//# Correspondence concerning livedata may be directed to:
     23//#        Internet email: mcalabre@atnf.csiro.au
     24//#        Postal address: Dr. Mark Calabretta
     25//#                        Australia Telescope National Facility, CSIRO
     26//#                        PO Box 76
     27//#                        Epping NSW 1710
     28//#                        AUSTRALIA
    2729//#
    28 //# $Id$
     30//# http://www.atnf.csiro.au/computing/software/livedata.html
     31//# $Id: SDFITSreader.h,v 19.22 2009-09-29 07:33:39 cal103 Exp $
    2932//#---------------------------------------------------------------------------
    3033//# The SDFITSreader class reads single dish FITS files such as those written
     
    3841
    3942#include <atnf/PKSIO/FITSreader.h>
    40 #include <atnf/PKSIO/PKSMBrecord.h>
     43#include <atnf/PKSIO/MBrecord.h>
     44
     45#include <casa/Logging/LogIO.h>
    4146
    4247#include <fitsio.h>
     48
     49using namespace std;
     50using namespace casa;
    4351
    4452// <summary>
     
    7684        double antPos[3],
    7785        char   obsMode[32],
     86        char   bunit[32],
    7887        float  &equinox,
    7988        char   radecsys[32],
     
    99108
    100109    // Read the next data record.
    101     virtual int read(PKSMBrecord &record);
    102 
    103     // Print out CFITSIO error messages.
    104     void reportError(void);
     110    virtual int read(MBrecord &record);
    105111
    106112    // Close the SDFITS file.
     
    108114
    109115  private:
    110     int      cCycleNo, cExtraSysCal, cNAxis, cStatus;
    111     long     cNAxes[5], cNRow, cReqax[4], cRow;
     116    int      cCycleNo, cExtraSysCal, cNAxes, cStatus;
     117    long     cBeamAxis, cDecAxis, cFreqAxis, cNAxis[5], cNAxisTime, cNRow,
     118             cRaAxis, cRow, cStokesAxis, cTimeAxis, cTimeIdx;
    112119    double   cLastUTC;
    113120    fitsfile *cSDptr;
     
    117124    int  cBeam_1rel, cIF_1rel;
    118125
     126    // for GBT
     127    int *cPols ;
     128
    119129    enum {SCAN, CYCLE, DATE_OBS, TIME, EXPOSURE, OBJECT, OBJ_RA, OBJ_DEC,
    120           RESTFRQ, OBSMODE, BEAM, IF, FqRefPix, FqRefVal, FqDelt, RA, DEC,
    121           SCANRATE, TSYS, CALFCTR, XCALFCTR, BASELIN, BASESUB, DATA, FLAGGED,
    122           DATAXED, XPOLDATA, REFBEAM, TCAL, TCALTIME, AZIMUTH, ELEVATIO,
    123           PARANGLE, FOCUSAXI, FOCUSTAN, FOCUSROT, TAMBIENT, PRESSURE,
    124           HUMIDITY, WINDSPEE, WINDDIRE, NDATA};
     130          RESTFRQ, OBSMODE, BEAM, IF, FqRefVal, FqDelt, FqRefPix, RA, DEC,
     131          TimeRefVal, TimeDelt, TimeRefPix, SCANRATE, TSYS, CALFCTR, XCALFCTR,
     132          BASELIN, BASESUB, DATA, FLAGGED, DATAXED, XPOLDATA, REFBEAM, TCAL,
     133          TCALTIME, AZIMUTH, ELEVATIO, PARANGLE, FOCUSAXI, FOCUSTAN, FOCUSROT,
     134          TAMBIENT, PRESSURE, HUMIDITY, WINDSPEE, WINDDIRE, STOKES, SIG, CAL,
     135          VFRAME, RVSYS, VELDEF, NDATA};
     136
     137    // Message handling.
     138    void log(LogOrigin origin, LogIO::Command cmd, const char *msg = 0x0);
    125139
    126140    void findData(int iData, char *name, int type);
     141    void  findCol(char *name, int *colnum);
    127142    int   readDim(int iData, long iRow, int *naxis, long naxes[]);
    128143    int  readParm(char *name, int type, void *value);
    129144    int  readData(char *name, int type, long iRow, void *value);
    130145    int  readData(int iData, long iRow, void *value);
    131     void  findCol(char *name, int *colnum);
     146    int  readCol(int iData, void *value);
     147    int  readTime(long iRow, int iPix, char *datobs, double &utc);
    132148
    133     // These are for ALFA data, "BDFITS" or "CIMAFITS".
     149    // These are for ALFA data: "BDFITS" or "CIMAFITS".  Statics are required
     150    // for CIMAFITS v2.0 because CAL ON/OFF data is split into separate files.
     151    static int  sInit, sReset;
     152    static int  (*sALFAcalNon)[2], (*sALFAcalNoff)[2];
     153    static float (*sALFAcal)[2], (*sALFAcalOn)[2], (*sALFAcalOff)[2];
     154
    134155    int   cALFA, cALFA_BD, cALFA_CIMA, cALFAscan, cScanNo;
    135     float cALFAcal[8][2], cALFAcalOn[8][2], cALFAcalOff[8][2];
    136     int   alfaCal(short iBeam, short iIF);
     156    float cALFAacc;
     157    int   alfaCal(short iBeam, short iIF, short iPol);
     158    float alfaGain(float zd);
    137159
    138160    // These are for GBT data.
    139161    int   cGBT, cFirstScanNo;
     162    double cGLastUTC[4] ;
     163    int cGLastScan[4] ;
     164    int cGCycleNo[4] ;
    140165};
    141166
  • branches/alma/external/atnf/PKSIO/SDFITSwriter.cc

    r1453 r1757  
    22//# SDFITSwriter.cc: ATNF CFITSIO interface class for SDFITS output.
    33//#---------------------------------------------------------------------------
    4 //# Copyright (C) 2000-2006
    5 //# Mark Calabretta, ATNF
     4//# livedata - processing pipeline for single-dish, multibeam spectral data.
     5//# Copyright (C) 2000-2009, Australia Telescope National Facility, CSIRO
    66//#
    7 //# This library is free software; you can redistribute it and/or modify it
    8 //# under the terms of the GNU Library General Public License as published by
    9 //# the Free Software Foundation; either version 2 of the License, or (at your
    10 //# option) any later version.
     7//# This file is part of livedata.
    118//#
    12 //# This library is distributed in the hope that it will be useful, but WITHOUT
     9//# livedata is free software: you can redistribute it and/or modify it under
     10//# the terms of the GNU General Public License as published by the Free
     11//# Software Foundation, either version 3 of the License, or (at your option)
     12//# any later version.
     13//#
     14//# livedata is distributed in the hope that it will be useful, but WITHOUT
    1315//# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    14 //# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Library General Public
    15 //# License for more details.
     16//# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
     17//# more details.
    1618//#
    17 //# You should have received a copy of the GNU Library General Public License
    18 //# along with this library; if not, write to the Free Software Foundation,
    19 //# Inc., 675 Massachusetts Ave, Cambridge, MA 02139, USA.
     19//# You should have received a copy of the GNU General Public License along
     20//# with livedata.  If not, see <http://www.gnu.org/licenses/>.
    2021//#
    21 //# Correspondence concerning this software should be addressed as follows:
    22 //#        Internet email: mcalabre@atnf.csiro.au.
    23 //#        Postal address: Dr. Mark Calabretta,
    24 //#                        Australia Telescope National Facility,
    25 //#                        P.O. Box 76,
    26 //#                        Epping, NSW, 2121,
     22//# Correspondence concerning livedata may be directed to:
     23//#        Internet email: mcalabre@atnf.csiro.au
     24//#        Postal address: Dr. Mark Calabretta
     25//#                        Australia Telescope National Facility, CSIRO
     26//#                        PO Box 76
     27//#                        Epping NSW 1710
    2728//#                        AUSTRALIA
    2829//#
    29 //# $Id$
     30//# http://www.atnf.csiro.au/computing/software/livedata.html
     31//# $Id: SDFITSwriter.cc,v 19.18 2009-09-29 07:33:39 cal103 Exp $
    3032//#---------------------------------------------------------------------------
    3133//# Original: 2000/07/24, Mark Calabretta, ATNF
    3234//#---------------------------------------------------------------------------
    3335
     36#include <atnf/PKSIO/MBrecord.h>
     37#include <atnf/PKSIO/SDFITSwriter.h>
     38
     39#include <casa/Logging/LogIO.h>
     40
     41#include <casa/iostream.h>
     42
    3443#include <algorithm>
    3544#include <math.h>
    36 
    37 // AIPS++ includes.
    38 #include <casa/iostream.h>
    39 
    40 // ATNF includes.
    41 #include <atnf/PKSIO/PKSMBrecord.h>
    42 #include <atnf/PKSIO/SDFITSwriter.h>
     45#include <cstring>
    4346
    4447using namespace std;
     
    4952// Factor to convert radians to degrees.
    5053const double R2D = 180.0 / PI;
     54
     55// Class name
     56const string className = "SDFITSwriter" ;
    5157
    5258//------------------------------------------------- SDFITSwriter::SDFITSwriter
     
    5561{
    5662  // Default constructor.
    57   cSDptr = 0;
     63  cSDptr = 0x0;
    5864}
    5965
     
    7682        double antPos[3],
    7783        char*  obsMode,
     84        char*  bunit,
    7885        float  equinox,
    7986        char*  dopplerFrame,
     
    8592        int    extraSysCal)
    8693{
     94  const string methodName = "create()" ;
     95
     96  if (cSDptr) {
     97    log(LogOrigin( className, methodName, WHERE ), LogIO::SEVERE, "Output file already open, close it first.");
     98    return 1;
     99  }
     100
    87101  // Prepend an '!' to the output name to force it to be overwritten.
    88102  char sdname[80];
     
    93107  cStatus = 0;
    94108  if (fits_create_file(&cSDptr, sdname, &cStatus)) {
     109    sprintf(cMsg, "Failed to create SDFITS file\n       %s", sdName);
     110    log(LogOrigin( className, methodName, WHERE ), LogIO::SEVERE, cMsg);
    95111    return cStatus;
    96112  }
     
    113129      break;
    114130    }
    115    
     131
    116132    if (cNChan[iIF] != cNChan[0] || cNPol[iIF] != cNPol[0]) {
    117133      // Varying channels and/or polarizations, need a TDIM column at least.
     
    140156  // Write required primary header keywords.
    141157  if (fits_write_imghdr(cSDptr, 8, 0, 0, &cStatus)) {
     158    log(LogOrigin( className, methodName, WHERE ), LogIO::SEVERE, "Failed to write required primary header keywords.");
    142159    return cStatus;
    143160  }
     
    159176  char version[7];
    160177  char date[11];
    161   sscanf("$Revision: 19.10 $", "%*s%s", version);
    162   sscanf("$Date: 2006/07/05 05:44:52 $", "%*s%s", date);
     178  sscanf("$Revision: 19.18 $", "%*s%s", version);
     179  sscanf("$Date: 2009-09-29 07:33:39 $", "%*s%s", date);
    163180  sprintf(text, "SDFITSwriter (v%s, %s)", version, date);
    164181  fits_write_key_str(cSDptr, "ORIGIN", text, "output class", &cStatus);
     
    170187  fits_write_comment(cSDptr, text, &cStatus);
    171188
     189  if (cStatus) {
     190    log(LogOrigin( className, methodName, WHERE ), LogIO::SEVERE, "Failed in writing primary header.");
     191    return cStatus;
     192  }
     193
     194
    172195  // Create an SDFITS extension.
    173196  long nrow = 0;
     
    175198  if (fits_create_tbl(cSDptr, BINARY_TBL, nrow, ncol, NULL, NULL, NULL,
    176199      "SINGLE DISH", &cStatus)) {
     200    log(LogOrigin( className, methodName, WHERE ), LogIO::SEVERE, "Failed to create a binary table extension.");
    177201    return 1;
    178202  }
     
    209233
    210234  // CYCLE (additional, real).
    211   fits_insert_col(cSDptr, ++ncol, "CYCLE", "1I", &cStatus);
     235  fits_insert_col(cSDptr, ++ncol, "CYCLE", "1J", &cStatus);
    212236
    213237  // DATE-OBS (core, real).
     
    355379  fits_insert_col(cSDptr, ++ncol, "TSYS", tform, &cStatus);
    356380  sprintf(tunit, "TUNIT%d", ncol);
    357   fits_write_key_str(cSDptr, tunit, "Jy", "units of field", &cStatus);
     381  fits_write_key_str(cSDptr, tunit, bunit, "units of field", &cStatus);
    358382
    359383  // CALFCTR (additional, real).
     
    369393
    370394    // BASESUB (additional, real).
    371     sprintf(tform, "%dE", 9*maxNPol);
     395    sprintf(tform, "%dE", 24*maxNPol);
    372396    fits_insert_col(cSDptr, ++ncol, "BASESUB", tform, &cStatus);
    373     tdim[0] = 9;
     397    tdim[0] = 24;
    374398    fits_write_tdim(cSDptr, ncol, 2, tdim, &cStatus);
    375399  }
     
    396420
    397421  sprintf(tunit, "TUNIT%d", ncol);
    398   fits_write_key_str(cSDptr, tunit, "Jy", "units of field", &cStatus);
     422  fits_write_key_str(cSDptr, tunit, bunit, "units of field", &cStatus);
    399423
    400424  // FLAGGED (additional, logical).
     
    444468
    445469    sprintf(tunit, "TUNIT%d", ncol);
    446     fits_write_key_str(cSDptr, tunit, "Jy", "units of field", &cStatus);
     470    fits_write_key_str(cSDptr, tunit, bunit, "units of field", &cStatus);
    447471  }
    448472
     
    523547  }
    524548
     549  if (cStatus) {
     550    log(LogOrigin( className, methodName, WHERE ), LogIO::SEVERE, "Failed in writing binary table header.");
     551  }
     552
    525553  return cStatus;
    526554}
     
    530558// Write a record to the SDFITS file.
    531559
    532 int SDFITSwriter::write(PKSMBrecord &mbrec)
     560int SDFITSwriter::write(MBrecord &mbrec)
    533561{
     562  const string methodName = "write()" ;
     563  LogIO os( LogOrigin( className, methodName, WHERE ) ) ;
     564
    534565  char *cptr;
    535566
     
    537568  int IFno = mbrec.IFno[0];
    538569  if (IFno < 1 || cNIF < IFno) {
    539     cerr << "SDFITSwriter::write: "
    540          << "Invalid IF number " << IFno
    541          << " (maximum " << cNIF << ")." << endl;
     570    os << LogIO::WARN
     571       << "SDFITSwriter::write: "
     572       << "Invalid IF number " << IFno
     573       << " (maximum " << cNIF << ")." << LogIO::POST ;
    542574    return 1;
    543575  }
     
    546578  int nChan = cNChan[iIF];
    547579  if (mbrec.nChan[0] != nChan) {
    548     cerr << "SDFITSriter::write: "
    549          << "Wrong number of channels for IF " << IFno << "," << endl
    550          << "                    "
    551          << "got " << nChan << " should be " << mbrec.nChan[0] << "." << endl;
     580    os << LogIO::WARN
     581       << "SDFITSriter::write: "
     582       << "Wrong number of channels for IF " << IFno << "," << endl
     583       << "                    "
     584       << "got " << nChan << " should be " << mbrec.nChan[0] << "." << endl;
     585    os << LogIO::POST ;
    552586    return 1;
    553587  }
     
    555589  int nPol = cNPol[iIF];
    556590  if (mbrec.nPol[0] != nPol) {
    557     cerr << "SDFITSriter::write: "
    558          << "Wrong number of polarizations for IF " << IFno << "," << endl
    559          << "                    "
    560          << "got " << nPol << " should be " << mbrec.nPol[0] << "." << endl;
     591    os << LogIO::WARN
     592       << "SDFITSriter::write: "
     593       << "Wrong number of polarizations for IF " << IFno << "," << endl
     594       << "                    "
     595       << "got " << nPol << " should be " << mbrec.nPol[0] << "." << endl;
     596    os << LogIO::POST ;
    561597    return 1;
    562598  }
     
    655691
    656692    // BASESUB.
    657     fits_write_col_flt(cSDptr, ++icol, cRow, 1, 9*nPol, mbrec.baseSub[0][0],
     693    fits_write_col_flt(cSDptr, ++icol, cRow, 1, 24*nPol, mbrec.baseSub[0][0],
    658694                       &cStatus);
    659695  }
     
    739775  }
    740776
     777  if (cStatus) {
     778    log(LogOrigin( className, methodName, WHERE ), LogIO::SEVERE, "Failed in writing binary table entry.");
     779  }
     780
    741781  return cStatus;
    742782}
    743783
    744784
    745 //-------------------------------------------------- SDFITSwriter::reportError
    746 
    747 // Print the error message corresponding to the input status value and all the
    748 // messages on the CFITSIO error stack to stderr.
    749 
    750 void SDFITSwriter::reportError()
     785//------------------------------------------------------ SDFITSwriter::history
     786
     787// Write a history record.
     788
     789int SDFITSwriter::history(char *text)
     790
    751791{
    752   fits_report_error(stderr, cStatus);
     792  const string methodName = "history()" ;
     793
     794  if (!cSDptr) {
     795    return 1;
     796  }
     797
     798  if (fits_write_history(cSDptr, text, &cStatus)) {
     799    log(LogOrigin( className, methodName, WHERE ), LogIO::SEVERE, "Failed in writing HISTORY records.");
     800  }
     801
     802  return cStatus;
    753803}
    754804
     
    759809void SDFITSwriter::close()
    760810{
     811  const string methodName = "close()" ;
     812
    761813  if (cSDptr) {
    762814    cStatus = 0;
    763     fits_close_file(cSDptr, &cStatus);
     815    if (fits_close_file(cSDptr, &cStatus)) {
     816      log(LogOrigin( className, methodName, WHERE ), LogIO::SEVERE, "Failed to close file.");
     817    }
     818
    764819    cSDptr = 0;
    765820  }
     
    772827void SDFITSwriter::deleteFile()
    773828{
     829  const string methodName = "deleteFile()" ;
     830
    774831  if (cSDptr) {
    775832    cStatus = 0;
    776     fits_delete_file(cSDptr, &cStatus);
     833    if (fits_delete_file(cSDptr, &cStatus)) {
     834      log(LogOrigin( className, methodName, WHERE ), LogIO::SEVERE, "Failed to close and delete file.");
     835    }
     836
    777837    cSDptr = 0;
    778838  }
    779839}
     840
     841//------------------------------------------------------- SDFITSwriter::log
     842
     843// Log a message.  If the current CFITSIO status value is non-zero, also log
     844// the corresponding error message and dump the CFITSIO message stack.
     845
     846void SDFITSwriter::log(LogOrigin origin, LogIO::Command cmd, const char *msg)
     847{
     848  LogIO os( origin ) ;
     849
     850  os << cmd << msg << endl ;
     851
     852  if (cStatus) {
     853    fits_get_errstatus(cStatus, cMsg);
     854    os << cMsg << endl ;
     855
     856    while (fits_read_errmsg(cMsg)) {
     857      os << cMsg << endl ;
     858    }
     859  }
     860
     861  os << LogIO::POST ;
     862}
  • branches/alma/external/atnf/PKSIO/SDFITSwriter.h

    r1453 r1757  
    22//# SDFITSwriter.h: ATNF CFITSIO interface class for SDFITS output.
    33//#---------------------------------------------------------------------------
    4 //# Copyright (C) 2000-2006
    5 //# Mark Calabretta, ATNF
     4//# livedata - processing pipeline for single-dish, multibeam spectral data.
     5//# Copyright (C) 2000-2009, Australia Telescope National Facility, CSIRO
    66//#
    7 //# This library is free software; you can redistribute it and/or modify it
    8 //# under the terms of the GNU Library General Public License as published by
    9 //# the Free Software Foundation; either version 2 of the License, or (at your
    10 //# option) any later version.
     7//# This file is part of livedata.
    118//#
    12 //# This library is distributed in the hope that it will be useful, but WITHOUT
     9//# livedata is free software: you can redistribute it and/or modify it under
     10//# the terms of the GNU General Public License as published by the Free
     11//# Software Foundation, either version 3 of the License, or (at your option)
     12//# any later version.
     13//#
     14//# livedata is distributed in the hope that it will be useful, but WITHOUT
    1315//# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    14 //# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Library General Public
    15 //# License for more details.
     16//# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
     17//# more details.
    1618//#
    17 //# You should have received a copy of the GNU Library General Public License
    18 //# along with this library; if not, write to the Free Software Foundation,
    19 //# Inc., 675 Massachusetts Ave, Cambridge, MA 02139, USA.
     19//# You should have received a copy of the GNU General Public License along
     20//# with livedata.  If not, see <http://www.gnu.org/licenses/>.
    2021//#
    21 //# Correspondence concerning this software should be addressed as follows:
    22 //#        Internet email: mcalabre@atnf.csiro.au.
    23 //#        Postal address: Dr. Mark Calabretta,
    24 //#                        Australia Telescope National Facility,
    25 //#                        P.O. Box 76,
    26 //#                        Epping, NSW, 2121,
     22//# Correspondence concerning livedata may be directed to:
     23//#        Internet email: mcalabre@atnf.csiro.au
     24//#        Postal address: Dr. Mark Calabretta
     25//#                        Australia Telescope National Facility, CSIRO
     26//#                        PO Box 76
     27//#                        Epping NSW 1710
    2728//#                        AUSTRALIA
    2829//#
    29 //# $Id$
     30//# http://www.atnf.csiro.au/computing/software/livedata.html
     31//# $Id: SDFITSwriter.h,v 19.10 2009-09-29 07:33:39 cal103 Exp $
    3032//#---------------------------------------------------------------------------
    3133//# Original: 2000/07/24, Mark Calabretta, ATNF
     
    3537#define ATNF_SDFITSWRITER_H
    3638
    37 #include <atnf/PKSIO/PKSMBrecord.h>
     39#include <atnf/PKSIO/MBrecord.h>
     40#include <casa/Logging/LogIO.h>
    3841
    3942#include <fitsio.h>
     43
     44using namespace std;
     45using namespace casa;
    4046
    4147// <summary>
     
    5056
    5157    // Destructor.
    52     ~SDFITSwriter();
     58    virtual ~SDFITSwriter();
    5359
    5460    // Create a new SDFITSwriter and store static data.
     
    6066        double antPos[3],
    6167        char*  obsMode,
     68        char*  bunit,
    6269        float  equinox,
    6370        char*  dopplerFrame,
     
    7077
    7178    // Store time-variable data.
    72     int write(PKSMBrecord &record);
     79    int write(MBrecord &record);
    7380
    74     // Print out CFITSIO error messages.
    75     void reportError();
     81    // Write a history record.
     82    int history(char* text);
    7683
    7784    // Close the SDFITS file.
     
    8693         *cNChan, cNIF, *cNPol, cStatus;
    8794    long cRow;
     95
     96    // Message handling.
     97    char cMsg[256];
     98    void log(LogOrigin origin, LogIO::Command cmd, const char *msg = 0x0);
    8899};
    89100
  • branches/alma/external/atnf/PKSIO/makefile

    r1325 r1757  
    1 # $Id: makefile,v 19.0 2003/07/16 03:34:05 aips2adm Exp $
     1# $Id$
    22
    33XLIBLIST := CFITSIO RPFITS
     
    55# Use the generic AIPS++ class implementation makefile.
    66#------------------------------------------------------
    7 include $(word 1, $(AIPSPATH))/code/install/makefile.imp
     7include $(word 1, $(CASAPATH))/code/install/makefile.imp
  • branches/alma/external/atnf/pks/makefile

    r1325 r1757  
    1 # $Id: makefile,v 19.0 2003/07/16 03:33:47 aips2adm Exp $
     1# $Id$
    22
    33# Use the generic AIPS++ class implementation makefile.
    44#------------------------------------------------------
    5 include $(word 1, $(AIPSPATH))/code/install/makefile.imp
     5include $(word 1, $(CASAPATH))/code/install/makefile.imp
  • branches/alma/external/atnf/pks/pks_maths.cc

    r1325 r1757  
    22//# pks_maths.cc: Mathematical functions for Parkes single-dish data reduction
    33//#---------------------------------------------------------------------------
    4 //# Copyright (C) 1994-2006
    5 //# Associated Universities, Inc. Washington DC, USA.
    6 //#
    7 //# This library is free software; you can redistribute it and/or modify it
    8 //# under the terms of the GNU Library General Public License as published by
    9 //# the Free Software Foundation; either version 2 of the License, or (at your
    10 //# option) any later version.
    11 //#
    12 //# This library is distributed in the hope that it will be useful, but WITHOUT
     4//# livedata - processing pipeline for single-dish, multibeam spectral data.
     5//# Copyright (C) 2004-2009, Australia Telescope National Facility, CSIRO
     6//#
     7//# This file is part of livedata.
     8//#
     9//# livedata is free software: you can redistribute it and/or modify it under
     10//# the terms of the GNU General Public License as published by the Free
     11//# Software Foundation, either version 3 of the License, or (at your option)
     12//# any later version.
     13//#
     14//# livedata is distributed in the hope that it will be useful, but WITHOUT
    1315//# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    14 //# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Library General Public
    15 //# License for more details.
    16 //#
    17 //# You should have received a copy of the GNU Library General Public License
    18 //# along with this library; if not, write to the Free Software Foundation,
    19 //# Inc., 675 Massachusetts Ave, Cambridge, MA 02139, USA.
    20 //#
    21 //# Correspondence concerning AIPS++ should be addressed as follows:
    22 //#        Internet email: aips2-request@nrao.edu.
    23 //#        Postal address: AIPS++ Project Office
    24 //#                        National Radio Astronomy Observatory
    25 //#                        520 Edgemont Road
    26 //#                        Charlottesville, VA 22903-2475 USA
    27 //#
    28 //# Original: Mark Calabretta
    29 //# $Id: pks_maths.cc,v 1.5 2006/05/19 00:12:35 mcalabre Exp $
    30 //----------------------------------------------------------------------------
     16//# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
     17//# more details.
     18//#
     19//# You should have received a copy of the GNU General Public License along
     20//# with livedata.  If not, see <http://www.gnu.org/licenses/>.
     21//#
     22//# Correspondence concerning livedata may be directed to:
     23//#        Internet email: mcalabre@atnf.csiro.au
     24//#        Postal address: Dr. Mark Calabretta
     25//#                        Australia Telescope National Facility, CSIRO
     26//#                        PO Box 76
     27//#                        Epping NSW 1710
     28//#                        AUSTRALIA
     29//#
     30//# http://www.atnf.csiro.au/computing/software/livedata.html
     31//# $Id: pks_maths.cc,v 1.7 2009-09-29 07:45:02 cal103 Exp $
     32//#---------------------------------------------------------------------------
     33//# Original: 2004/07/16 Mark Calabretta
     34//#---------------------------------------------------------------------------
    3135
    3236// AIPS++ includes.
     
    295299//----------------------------------------------------------------------- azel
    296300
    297 // Convert (ra,dec) to (az,el), from
    298 // http://aa.usno.navy.mil/faq/docs/Alt_Az.html.  Position as a Cartesian
    299 // triplet in m, UT1 in MJD form, and all angles in radian.
     301// Convert (ra,dec) to (az,el).  Position as a Cartesian triplet in m, UT1 in
     302// MJD form, and all angles in radian.
    300303
    301304void azel(const Vector<Double> position, Double ut1, Double ra, Double dec,
    302305          Double &az, Double &el)
    303306{
    304   // Get gocentric longitude and latitude (rad).
     307  // Get geocentric longitude and latitude (rad).
    305308  Double x = position(0);
    306309  Double y = position(1);
     
    318321
    319322  // Azimuth and elevation (rad).
    320   az = atan2(cos(dec)*sin(ha), cos(dec)*sin(lat)*cos(ha) - sin(dec)*cos(lat));
     323  az = atan2(cos(dec)*sin(ha),
     324             cos(dec)*sin(lat)*cos(ha) - sin(dec)*cos(lat));
    321325  if (az < 0.0) az += C::_2pi;
    322   el = asin(cos(dec)*cos(lat)*cos(ha) + sin(dec)*sin(lat));
     326  el = asin(sin(dec)*sin(lat) + cos(dec)*cos(lat)*cos(ha));
     327
    323328}
    324329
  • branches/alma/external/atnf/pks/pks_maths.h

    r1325 r1757  
    1 //----------------------------------------------------------------------------
     1//#---------------------------------------------------------------------------
    22//# pks_maths.h: Mathematical functions for Parkes single dish data reduction
    3 //----------------------------------------------------------------------------
    4 //# Copyright (C) 1994-2006
    5 //# Associated Universities, Inc. Washington DC, USA.
     3//#---------------------------------------------------------------------------
     4//# livedata - processing pipeline for single-dish, multibeam spectral data.
     5//# Copyright (C) 2000-2009, Australia Telescope National Facility, CSIRO
    66//#
    7 //# This library is free software; you can redistribute it and/or modify it
    8 //# under the terms of the GNU Library General Public License as published by
    9 //# the Free Software Foundation; either version 2 of the License, or (at your
    10 //# option) any later version.
     7//# This file is part of livedata.
    118//#
    12 //# This library is distributed in the hope that it will be useful, but WITHOUT
     9//# livedata is free software: you can redistribute it and/or modify it under
     10//# the terms of the GNU General Public License as published by the Free
     11//# Software Foundation, either version 3 of the License, or (at your option)
     12//# any later version.
     13//#
     14//# livedata is distributed in the hope that it will be useful, but WITHOUT
    1315//# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    14 //# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Library General Public
    15 //# License for more details.
     16//# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
     17//# more details.
    1618//#
    17 //# You should have received a copy of the GNU Library General Public License
    18 //# along with this library; if not, write to the Free Software Foundation,
    19 //# Inc., 675 Massachusetts Ave, Cambridge, MA 02139, USA.
     19//# You should have received a copy of the GNU General Public License along
     20//# with livedata.  If not, see <http://www.gnu.org/licenses/>.
    2021//#
    21 //# Correspondence concerning AIPS++ should be addressed as follows:
    22 //#        Internet email: aips2-request@nrao.edu.
    23 //#        Postal address: AIPS++ Project Office
    24 //#                        National Radio Astronomy Observatory
    25 //#                        520 Edgemont Road
    26 //#                        Charlottesville, VA 22903-2475 USA
     22//# Correspondence concerning livedata may be directed to:
     23//#        Internet email: mcalabre@atnf.csiro.au
     24//#        Postal address: Dr. Mark Calabretta
     25//#                        Australia Telescope National Facility, CSIRO
     26//#                        PO Box 76
     27//#                        Epping NSW 1710
     28//#                        AUSTRALIA
    2729//#
    28 //# Original: Mark Calabretta
    29 //# $Id: pks_maths.h,v 1.6 2006/05/19 00:12:06 mcalabre Exp $
    30 //----------------------------------------------------------------------------
     30//# http://www.atnf.csiro.au/computing/software/livedata.html
     31//# $Id: pks_maths.h,v 1.7 2009-09-29 07:45:02 cal103 Exp $
     32//#---------------------------------------------------------------------------
     33//# Original: 2004/07/16 Mark Calabretta
     34//#---------------------------------------------------------------------------
    3135#ifndef ATNF_PKS_MATHS_H
    3236#define ATNF_PKS_MATHS_H
Note: See TracChangeset for help on using the changeset viewer.