Changeset 1757 for branches/alma


Ignore:
Timestamp:
06/09/10 19:03:06 (15 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:
35 added
4 deleted
81 edited
29 copied

Legend:

Unmodified
Added
Removed
  • branches/alma

  • branches/alma/COPYING

    r1042 r1757  
    1 Copyright (C) 2004,2005,2006
    2 ATNF
     1Copyright (C) 2004-2009
     2CSIRO
    33
    44This program is free software; you can redistribute it and/or modify it
  • branches/alma/INSTALL

    r1194 r1757  
    22============
    33
    4 * scons
     4* scons >= 1.1
     5* rpfits >= 2.19
     6* cfitso >= 2
     7* python >= 2.4
     8* boost >= 1.37
     9* casacore >= 1.0
    510
    611Installation
     
    813
    914scons has several targets. It is recommended to execute them sequentially.
    10 The normal install procedure is as follows:
    11    . <path_to_casa_asap>/aipsinit.sh
     15The normal install procedure is as follows
     16.. code::
     17
    1218   scons
    13    # Do this if you haven't got a data directory already
     19   # Do this if you haven't got a measures data directory already
    1420   export ASAPDATA=.
    1521   ./bin/asap_update_data
     
    2026Obtaining the data directory
    2127============================
    22 The data repository can be obtained seperately after installing ASAP.
    23 Before you run asap for the first time simply run
     28
     29The data repository can be obtained separately after installing ASAP.
     30Before you run asap for the first time simply run::
     31
    2432    asap_update_data
     33
    2534This will install the data repository into the correct location.
    2635
    2736There are several ways to do this.
    28 a) If you already hae the 'data' directory, copy it to the root directory and run the normal install procedure.
     37a) If you already have the 'data' directory, copy it to the root directory and run the normal install procedure::
     38
    2939   scons
    3040   scons install
    3141
    3242b) You can obtain the data repository from the ftp site.
    33    Simply run
     43   Simply run::
     44
    3445        export ASAPDATA=.
    3546        ./bin/asap_update_data
     47
    3648   This will retrieve and unpack the data directory.
    37    After this run:
     49   After this run::
     50
    3851        scons install
    3952
     
    4154==============================
    4255
    43 after building using 'scons', you can create a compressed tarball of the binaries. This is done via the target 'makedist='. The argument should be an obvious identifier for the system you want to support, e.g. 'sarge' or 'fc5-x86_64'
     56after building using 'scons', you can create a compressed tarball of the binaries. This is done via the target 'makedist='. The argument should be an obvious identifier for the system you want to support, e.g. 'sarge' or 'fc5-x86_64'::
    4457
    4558    scons makedist=sarge
  • branches/alma/SConstruct

    r1377 r1757  
    66
    77moduledir = distutils.sysconfig.get_python_lib()
    8 if  platform.architecture()[0] == '64bit':
     8
     9if sys.platform.startswith('linux') and platform.architecture()[0] == '64bit':
    910    # hack to install into /usr/lib64 if scons is in the 32bit /usr/lib/
    1011    if moduledir.startswith("/usr/lib/"):
    1112        moduledir = moduledir.replace("lib", "lib64")
    1213
    13 opts = Options("options.cfg")
    14 opts.AddOptions(
     14EnsureSConsVersion(1,1,0)
     15
     16opts = Variables("options.cfg")
     17opts.AddVariables(
    1518                ("FORTRAN", "The fortran compiler", None),
    1619                ("f2clib", "The fortran to c library", None),
    17                 PathOption("prefix",
     20                PathVariable("prefix",
    1821                "The root installation path",
    1922                           distutils.sysconfig.PREFIX),
    20                 PathOption("moduledir",
     23                PathVariable("moduledir",
    2124                            "The python module path (site-packages))",
    2225                            moduledir),
    23                 PathOption("casacoreroot", "The location of casacore",
    24                                     "/usr/local"),
     26                PathVariable("casacoreroot", "The location of casacore",
     27                             "/usr/local"),
    2528                ("boostroot", "The root dir where boost is installed", None),
    2629                ("boostlib", "The name of the boost python library",
     
    4548                ("cfitsiolib", "The cfitsio library name", "cfitsio"),
    4649                ("cfitsioincdir", "The cfitsio include location", None),
     50                ("wcslib", "The wcs library name", "wcs"),
    4751                ("wcsroot",
    4852                 "The root directory where wcs is installed", None),
     
    5256                 "The root directory where rpfits is installed", None),
    5357                ("rpfitslibdir", "The rpfits library location", None),
    54 #               ("rpfitsincdir", "The rpfits include location", None),
    55                 EnumOption("mode", "The type of build.", "debug",
     58                ("pyraproot", "The root directory where libpyrap is installed",
     59                 None),
     60                ("pyraplib", "The name of the pyrap library", "pyrap"),
     61                ("pyraplibdir", "The directory where libpyrap is installed",
     62                 None),
     63                ("pyrapincdir", "The pyrap include location",
     64                 None),
     65                BoolVariable("enable_pyrap", "Use pyrap conversion library",
     66                             False),
     67
     68                EnumVariable("mode", "The type of build.", "release",
    5669                           ["release","debug"], ignorecase=1),
    5770                ("makedist",
    5871                 "Make a binary archive giving a suffix, e.g. sarge or fc5",
    5972                 ""),
    60                 EnumOption("makedoc", "Build the userguide in specified format",
     73                EnumVariable("makedoc", "Build the userguide in specified format",
    6174                           "none",
    62                            ["none", "pdf", "html"], ignorecase=1)
     75                           ["none", "pdf", "html"], ignorecase=1),
     76                BoolVariable("apps", "Build cpp apps", True),
     77                BoolVariable("alma", "Enable alma specific functionality",
     78                             False),
    6379                )
    6480
     
    7389env.SConsignFile()
    7490
    75 if env["PLATFORM"] == "darwin":
    76     env.EnsureSConsVersion(0,96,95)
    77 
    7891casacoretooldir = os.path.join(env["casacoreroot"],"share",
    7992                                   "casacore")
     
    8396
    8497# load casacore specific build flags
     98env.Tool('casaoptions', [casacoretooldir])
     99opts.Update(env)
    85100env.Tool('casa', [casacoretooldir])
    86101
     
    93108                                               "include", "casacore"))
    94109    if not conf.CheckLib("casa_casa", language='c++'): Exit(1)
    95     conf.env.PrependUnique(LIBS=["casa_ms", "casa_components",
     110    conf.env.PrependUnique(LIBS=["casa_images", "casa_ms", "casa_components",
    96111                                 "casa_coordinates", "casa_lattices",
    97112                                 "casa_fits", "casa_measures", "casa_scimath",
     
    108123
    109124    conf.env.AddCustomPackage('boost')
    110     if not conf.CheckLibWithHeader(env["boostlib"],
     125    if not conf.CheckLibWithHeader(conf.env["boostlib"],
    111126                                   'boost/python.hpp', language='c++'):
    112127        Exit(1)
     128
     129    conf.env.AddCustomPackage('pyrap')
     130    if  conf.env.get("enable_pyrap") and conf.CheckLib(conf.env["pyraplib"],
     131                                                       language='c++',
     132                                                       autoadd=0):
     133        conf.env.Append(CPPFLAGS=['-DHAVE_PYRAP'])
     134        conf.env.PrependUnique(LIBS=env['pyraplib'])
     135   
    113136    # test for cfitsio
    114137    if not conf.CheckLib("m"): Exit(1)
     
    118141        Exit(1)
    119142    conf.env.AddCustomPackage('wcs')
    120     if not conf.CheckLibWithHeader('wcs', 'wcslib/wcs.h', language='c'):
     143    if not conf.CheckLibWithHeader(conf.env["wcslib"],
     144                                   'wcslib/wcs.h', language='c'):
    121145        Exit(1)
    122146    conf.env.AddCustomPackage('rpfits')
     
    125149
    126150    # test for blas/lapack
     151    lapackname = conf.env.get("lapacklib", "lapack")
    127152    conf.env.AddCustomPackage("lapack")
    128     if not conf.CheckLib(conf.env["lapacklib"]): Exit(1)
     153    if not conf.CheckLib(lapackname): Exit(1)
    129154    blasname = conf.env.get("blaslib", "blas")
    130155    conf.env.AddCustomPackage("blas")
    131     if not conf.CheckLib(conf.env["blaslib"]): Exit(1)
     156    if not conf.CheckLib(blasname): Exit(1)
    132157    conf.env.CheckFortran(conf)
    133158    if not conf.CheckLib('stdc++', language='c++'): Exit(1)
     159    if conf.env["alma"]:
     160        conf.env.Append(CPPFLAGS=['-DUSE_ALMA'])
    134161    env = conf.Finish()
    135162
    136 env["version"] = "2.2.x"
     163env["version"] = "3.0.0"
    137164
    138165if env['mode'] == 'release':
     
    141168    env.Append(CCFLAGS=["-O2"])
    142169else:
    143     env.Append(CCFLAGS=["-g"])
     170    env.Append(CCFLAGS=["-g", "-Wall"])
    144171
    145172# Export for SConscript files
     
    165192
    166193# install targets
    167 somod = env.Install("$moduledir/asap", so )
    168 pymods = env.Install("$moduledir/asap", env.SGlob("python/*.py"))
    169 bins = env.Install("$prefix/bin", ["bin/asap", "bin/asap_update_data"])
    170 shares = env.Install("$moduledir/asap/data", "share/ipythonrc-asap")
    171 env.Alias('install', [somod, pymods, bins, shares])
     194installs = []
     195installs.append(env.Install("$moduledir/asap", so))
     196installs.append(env.Install("$moduledir/asap", env.SGlob("python/*.py")))
     197installs.append(env.Install("$prefix/bin",
     198                            ["bin/asap", "bin/asap_update_data"]))
     199installs.append(env.Install("$moduledir/asap/data", "share/ipythonrc-asap"))
     200installs.append(env.Install("$moduledir/asap/data", "share/ipy_user_conf.py"))
     201env.Alias('install', installs)
    172202
    173203# install aips++ data repos
    174 rootdir=None
     204rootdir = None
    175205outdir =  os.path.join(env["moduledir"],'asap','data')
    176206sources = ['ephemerides','geodetic']
     
    193223    env.QInstall("$stagedir", ["bin/install"])
    194224    env.QInstall("$stagedir/asap/data", "share/ipythonrc-asap")
     225    env.QInstall("$stagedir/asap/data", "share/ipy_user_conf.py")
    195226    if rootdir is not None:
    196227        # This creates a directory Using data table... - disabled
     
    209240    env.SConscript("doc/SConscript")
    210241
     242if env["apps"]:
     243    env.SConscript("apps/SConscript")
     244
    211245if env.GetOption("clean"):
    212246    Execute(Delete(".sconf_temp"))
  • branches/alma/bin/asap

    r1210 r1757  
    5151    fi
    5252    # now execute ipython using the profile
    53     $ip -ipythondir "${HOME}/.asap" -p 'asap' $*
     53    $ip -ipythondir "${HOME}/.asap" $*
    5454fi
  • branches/alma/bin/install

    r1232 r1757  
    1818    lddopts = ""
    1919    if (sys.platform == "darwin"):
    20         lddcommand = "otool"
     20        lddcommand = "/usr/bin/otool"
    2121        lddopts = "-L"
    2222    if not os.path.isfile(lddcommand):
     
    2727    resolved = []
    2828    unresolved = []
    29     for l in p.readlines():
    30         lsp = l.split()
    31         # test this to avoid fails on linux_gate, which has no library
    32         if len(lsp) >= 3:
    33             if lsp[2] == "not":
    34                 unresolved.append(lsp[0])
     29    if sys.platform == "linux2":
     30        for l in p.readlines():
     31            lsp = l.split()
     32            # test this to avoid fails on linux_gate, which has no library
     33            if len(lsp) >= 3:
     34                if lsp[2] == "not":
     35                    unresolved.append(lsp[0])
     36                else:
     37                    resolved.append(lsp[2])
     38    elif sys.platform == "darwin":
     39        for l in p.readlines():
     40            l = l.strip()
     41            if l.endswith(":"):
     42                continue
     43            l = l.split()[0]
     44            if not os.path.exists(l):
     45                unresolved.append(l)
    3546            else:
    36                 resolved.append(lsp[2])
     47                resolved.append(l)
    3748    return resolved, unresolved
     49
    3850
    3951try:
     
    122134    print "Installing asap  scripts in %s" % bindir
    123135    if moduledir != sysmoduledir:
    124         import sre
     136        import re
    125137        print "Changing asap startup script to use custom PYTHONPATH"
    126138        inf = file("bin/asap")
     
    137149        shutil.copy2("bin/asap", bindir)
    138150    shutil.copy2("bin/asap_update_data", bindir)
     151    shutil.copy2("bin/asap2to3", bindir)
    139152    if not os.path.exists("asap/data/ephemerides"):
    140153        print "Warning - no data directory present"
  • branches/alma/doc/CHANGELOG

    r1381 r1757  
    22=========
    33
    4 Release 2.2.1 [2007-??-??]
     4Release 3.0.0 [2010-05-06]
    55
    6 * source direction for Hobart data - Ticket #109
    7 * added running median to scantable.(smooth(kernel='rmedian')
     6* BEWARE: added asap2to3 which converts '.asap' files from version 2 to
     7          version 3
     8* Ticket #183 Added scantable.get_weather
     9* Ticket #181 Added work-around for casacore bug in saving tables with
     10              selection
     11* Ticket #178 Added opacity_model based on  miriad's atmospheric model
     12* Ticket #177 Added function skydip to determine opacities.
     13* Ticket #172 Fixed non-working scantable.resample
     14* Ticket #155 Better output filenames. Ignore non-existsing
     15              beams/pols/ifs/scans
     16* Ticket #157 numpy >= 1.1 support
     17* Ticket #158 fixed plotter.set_font
     18* Ticket #160 Aspect ratio of plotter is customisable now
     19* Ticket #163 fixed for scantable.set_sourcetype
     20* Ticket #164 Upgrade note in wiki FAQ
     21* Ticket #165 Handle non-parallactified polarimtery data (if supported in
     22              rpfits)
     23* Ticket #167 Added running polynomial filter to scantable.smooth
     24* Ticket #168 Data exported via scantable.save now contains correct frequency
     25              or velocity information
     26* Ticket #169 Simplified selection of data
     27* Ticket #46  Interactive lag flagging
     28* Ticket #170 Provided access to frequency coordinate information via
     29              scantable.get_coordinate
     30* Added OS X 10.5 Disk image installer
     31* Added support for OS X 10.6
     32* Interactive plotting annotations via optional argument interactive=True
     33* Interactive creation of masks on the plotter - plotter.create_mask
     34* Tidy up date range in asapplotter.plotazel/plotpointings
     35* support for gcc-4.4
     36
     37Release 2.3.1 [2009-03-25]
     38
     39* Ticket #154 Flagged data wasn't hnoured in fitting
     40* Ticket #153 plotter.plot_lines fixed for matplotlib >= 0.98
     41* Ticket #90  Support integer values for frequencies/errors/intensities
     42
     43Release 2.3.0 [2009-03-13]
     44
     45* Ticket #150 fix in casacore for frequency frame conversions
     46* Ticket #151 added rc parameter and function set_sourcetype to identify
     47              on/off scans
     48* Ticket #78/#112 Resolved the issue with random errors occuring under linux
     49                  for large
     50   data files, which corrupted the identifaction of off scans
     51* Ticket #149 Fixed the bug causing spectral line search to go into an
     52              infinite loop in some rare circumstances
     53* Ticket #110 Added export to CLASS readable FITS files
     54   scantable.save("myfile.fits", "CLASS")
     55* Ticket #142 Fix of the frequency alignment for long observations
     56* Ticket #133 allow supression of history in the scantable via rc parameters
     57* Ticket #109 source direction for Hobart data
     58* Ticket #115 added running median to scantable.(smooth(kernel='rmedian')
     59* Ticket #148 opacity correction wasn't applied to TSYS
     60* Ticket #135 quotient detection failure for specific source names
     61* Ticket #140 NaN values not handled - added scantable.flag_nans to ensure
     62              that the NaN are flagged
     63* added python iterator access to scantable rows
     64* made functions available to directly manipulate spectra
     65  scantable.get/set_spectrum
     66* upgrade to support ipython >= 0.8.1
     67* support gcc-4.3
     68* use scons >= 1.1.0
     69* update to latest livedata I/O functions
     70* add WCS info to the exported text files
     71
    872
    973Release 2.2.0 [2007-05-02]
     
    2892* fix for Ticket #88 - numpy masks
    2993* better TAB completion for ipython (handles quotes, don't list private members)
    30 * Fix for Ticket #81 = scanatble.stats output as list 
     94* Fix for Ticket #81 = scanatble.stats output as list
    3195* ticket #64 - speed up of auto_poly_baseline
    3296* fix for ticket #89 - export of IF sub-selections
  • branches/alma/doc/userguide.tex

    r1347 r1757  
    1313\setlength{\parskip}{1ex}
    1414
    15 \title{ATNF Spectral Analysis Package\\User Guide v2.1\\DRAFT }
     15\title{ATNF Spectral Analysis Package\\User Guide v2.3 }
    1616\author{Chris Phillips}
    1717
     
    4848package.
    4949
    50 This userguide has been updated for the ASAP 2.1. Please report any
     50This userguide has been updated for the ASAP 2.3. Please report any
    5151mistakes you find.
    5252
     
    5858\item Epping - use hosts {\tt draco} or {\tt hydra}
    5959\item Narrabri - use host {\tt kaputar}
    60 \item Parkes - use host {\tt bourbon}
    61 \item Mopra - use host {\tt minos}
     60\item Parkes - use host {\tt ?}
     61\item Mopra - use host {\tt minos} or {\tt kaputar} if at Narrabri
    6262\end{itemize}
    6363
    6464Or use your own Linux desktop.
    6565
    66 {\em Note. ASAP2.1 only runs on ATNF Linux machines which have been
     66{\em Note. ASAP2.2 only runs on ATNF Linux machines which have been
    6767updated to Debian Sarge and are using the ``DEBIANSarge''
    6868/usr/local. If your favourite machine has not been upgraded, send a
    69 request to your friendly IT support. At the time of writing asap 2.1
    70 does not run on hydra, bourbon or kaputar.}
     69request to your friendly IT support.}
    7170
    7271\index{Running}To start asap log onto one of these Linux hosts and enter
     
    166165is un-ambiguous, or a list of possibilities will be
    167166given. Auto-completion works for the user object names as well as
    168 function names. It does not work for filenames, nor for function
     167function names and even file names It does not work for for function
    169168arguments.
    170169
     
    210209  ASAP>ls
    211210  ASAP>cd /my/data/directory
    212   ASAP>! mozilla&
     211  ASAP>! firefox&
    213212\end{verbatim}
    214213
     
    352351
    353352  # Equivalent to brief summary function call
    354   ASAP>print scan
     353  ASAP>print scans
    355354\end{verbatim}
    356355
     
    422421  ASAP>selection.reset()              # Turn off selection
    423422  ASAP>scans.set_selection(selection) # Apply the reset selection
     423  ASAP>scans.set_selection() # alternative to reset selection
    424424
    425425\end{verbatim}
     
    460460\begin{verbatim}
    461461  ASAP>scans = scantable('2004-11-23_1841-P484.rpf') # Read in the data
    462   ASAP>scans.set_freqframe('LSRK')  # Use the LSR velocity frame
     462  ASAP>scans.set_freqframe('LSRK')   # Use the LSR velocity frame
    463463  ASAP>scans.set_unit('km/s')        # Use velocity for plots etc from now on
    464464  ASAP>scans.set_doppler('OPTICAL')  # Use the optical velocity convention
     
    528528
    529529  # Select channel range for baselining
    530   ASAP>scans.set_unit('channels')
     530  ASAP>scans.set_unit('channel')
    531531  ASAP>msk = scans.create_mask([100,400],[600,800])
    532532
     
    542542Example :
    543543\begin{verbatim}
    544   ASAP>scans.set_unit('channels')
     544  ASAP>scans.set_unit('channel')
    545545  ASAP>msk = scans.create_mask([0,100],[900-1023], invert=True)
    546546\end{verbatim}
     
    562562
    563563\begin{verbatim}
    564   ASAP>scans.set_unit('channels')
     564  ASAP>scans.set_unit('channel')
    565565  ASAP>msk1 = q.create_mask([0,100],[511,511],[900,1023],invert=True)
    566566  ASAP>scans.set_unit('km/s')
     
    614614
    615615
    616 \subsection{Reader object}
    617 
    618 \index{Reader object}\index{Scantable!reader object}For more control
    619 when reading data into ASAP, the reader object should be used.  This
    620 has the option of only reading in a range of integrations, only a
    621 specified beam or IF and does not perform any scan averaging of the
    622 data, allowing analysis of the individual integrations.  Note that due
    623 to limitation of the RPFITS library, only one reader object can be
    624 open at one time reading RPFITS files.  To read multiple RPFITS files,
    625 the old reader must be destroyed before the new file is opened.
    626 However, multiple readers can be created and attached to SDFITS files.
    627 
    628 
    629 Example usage:
    630 
    631 \begin{verbatim}
    632   ASAP>r = reader('2003-03-16_082048_t0002.rpf')
    633   ASAP>r.summary()
    634   ASAP>scan = r.read()
    635   ASAP>del r
    636 \end{verbatim}
     616%\subsection{Reader object}
     617
     618%\index{Reader object}\index{Scantable!reader object}For more control
     619%when reading data into ASAP, the reader object should be used.  This
     620%has the option of only reading in a range of integrations, only a
     621%specified beam or IF and does not perform any scan averaging of the
     622%data, allowing analysis of the individual integrations.  Note that due
     623%to limitation of the RPFITS library, only one reader object can be
     624%open at one time reading RPFITS files.  To read multiple RPFITS files,
     625%the old reader must be destroyed before the new file is opened.
     626%However, multiple readers can be created and attached to SDFITS files.
     627%
     628%
     629%Example usage:
     630%
     631%\begin{verbatim}
     632%  ASAP>r = reader('2003-03-16_082048_t0002.rpf')
     633%  ASAP>r.summary()
     634%  ASAP>scan = r.read()
     635%  ASAP>del r
     636%\end{verbatim}
    637637
    638638\section{Basic Processing}
     
    649649have a trailing ``\_R'' in the source name for data from Parkes and
    650650Mopra, and a trailing ``e'' or ``w'' for data from Tidbinbilla.
    651 This functions has two \cmd{mode}s. \cmd{paired} (the deafault), which assumes
     651This functions has two \cmd{mode}s. \cmd{paired} (the default), which assumes
    652652matching adjacent pairs of source/reference scans and \cmd{time}, which finds
    653653the closest reference scan in time.
     
    835835telescope is wrong due to an incorrect noise diode calibration. This
    836836can easily be corrected for with the scale function. By default,
    837 \cmd{scale} only scans the spectra and not the corresponding Tsys.
     837\cmd{scale} only scaless the spectra and not the corresponding Tsys.
    838838
    839839\begin{verbatim}
     
    871871\begin{verbatim}
    872872  ASAP>scans.recalc_azel()                # recalculate az/el
    873                                                                   # based on pointing
     873                                          # based on pointing
    874874\end{verbatim}
    875875
     
    962962\end{verbatim}
    963963
     964One can also apply the inverse of \cmd{get\_scan} \cmd{drop\_scan}
     965
    964966To copy a scantable the following does not work:
    965967
     
    994996  it.
    995997
    996 %\item[FITS] This uses simple ``image'' fits to save the data, each row
    997 %  being written to a separate fits file. This format is suitable for
    998 %  importing the data into CLASS.
     998\item[FITS] This uses simple ``image'' fits to save the data, each row
     999  being written to a separate fits file.
     1000
     1001\item[CLASS] This uses simple ``image'' fits to save the data, each row
     1002  being written to a separate fits file. This format has modification so it
     1003  is suitable for importing the data into CLASS.
    9991004
    10001005\item[ASCII] A simple text based format suitable for the user to
     
    14021407\end{verbatim}
    14031408
    1404 For data with many IFs, such as from MOPS, the user it is recommended
    1405 that the user creates their own line cstalog for the data and use this
     1409For data with many IFs, such as from MOPS, it is recommended
     1410that users creates their own line catalog table for the data and use this
    14061411to set the rest frequency for each IF.
    14071412
     
    16581663size of the dataset which can be loaded. ASAP can use ``disk based''
    16591664scan tables which cache the bulk of the scantable on disk and require
    1660 significantly less memory usage.
     1665significantly less memory usage. This should be used for all MOPS data!
    16611666
    16621667To use disk based tables you either need to change the default in your
     
    16791684{\bf NOTE: } Currently a bug in ipython means temporary files are not
    16801685cleaned up properly when you exit ASAP. If you use disk based scan
    1681 tables your directory will be left with 'tabXXXXX\_X' directories. These can
     1686tables your directory will be left with 'tmpXXXXX\_X' directories. These can
    16821687be safely removed if ASAP is not running.
    16831688
     
    16921697{\em Currently mathematics between two scantables is not available }
    16931698
    1694 %  ASAP>sum = scan1+scan2
    16951699\begin{verbatim}
    16961700  ASAP>scan2 = scan1+2.0
    16971701  ASAP>scan *= 1.05
     1702  ASAP>sum = scan1+scan2
    16981703\end{verbatim}
    16991704
     
    17131718
    17141719\hspace{1cm} http://www.python.org/doc/Introduction.html
     1720
     1721\hspace{1cm} http:/ipython.scipy.org
    17151722
    17161723\subsection{Running scripts}
  • 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
  • branches/alma/monitor/cgi-bin/asapconfig.py

    r712 r1757  
    55               'lines' : {} }
    66
     7asapmonhome = "/var/www/htdocs"
     8asapmonrel = "/asapmon/"
    79import os,sys
    8 # This is where asap lives
    9 sys.path.insert(2,'/opt/lib/python2.3/site-packages')
    10 os.environ["AIPSPATH"]="/opt/share/asap linux_gnu somewhere localhost"
    11 
    12 #overwrite /usr/local/... as default
    13 sys.path.insert(2,'/usr/lib/python2.3/site-packages')
    14 
    15 # This is needed for plotting with matplotlib
    16 # where matplotlib data is located
    17 os.environ["MATPLOTLIBDATA"]="/opt/share/matplotlib"
    1810# where matplotlib puts it temporary font files
    1911# this location can also have a custom .matplotlibrc
    20 os.environ["HOME"]="/var/www/asapmon/tmp"
     12os.environ["HOME"]="/var/www/htdocs/asapmon/tmp"
  • branches/alma/monitor/cgi-bin/asapmon.py

    r1295 r1757  
    77from simpletal import simpleTAL, simpleTALES
    88
    9 #absolute home
    10 abspath= "/var/www/asapmon/"
    11 cgiloc = "/cgi-bin/asapmon/"
    12 tmppath = os.path.join(abspath,"tmp/")
    13 htmlloc = "/asapmon/"
    14 tmploc = "/asapmon/tmp/"
    15 
    169from obsconfig import *
     10
     11tmppath = os.path.join(asapmonhome,"tmp/")
     12tmppath = os.path.join(asapmonrel,"tmp/")
    1713
    1814# a redirection object for stdout/stderr
     
    2824sys.stderr = logsink2
    2925import asap
     26asap.rc('scantable', storage="memory")
    3027sys.stdout = sys.__stdout__
    3128sys.stderr = sys.__stderr__
     
    5855    def decodeWindow(self,window):
    5956        if not len(window.strip()): return None,None
    60         x = window.split(", ")
     57        x = window.split(",")
    6158        return [float(x[0].strip()), float(x[1].strip())]
    6259
     
    167164            else:
    168165                # get only the last source in the table if not averaging
    169                 s = s.get_scan(self.fields['sourcenames'][-1])
    170                 #self.fields['debug'] = "DEBUG"
     166                # This doesn't work anymore, but works on the command-line??
     167                # Use explict selection
     168                #s = s.get_scan(str(self.fields['sourcenames'][-1]))
     169                sel = asap.selector()
     170                sel.set_name(str(self.fields['sourcenames'][-1]))
     171                s.set_selection(sel)
     172                s = s.copy()
    171173                self.fields['csource'] = s.get_sourcename()[-1]
    172174            if self.fields['cunit'] == 1:
    173                 srest = s._getrestfreqs()
    174                 if isinstance(srest, tuple) and len(srest) != s.nif():
    175                     s.set_restfreqs(restfs, unit="GHz")
     175                s.set_restfreqs(restfs, unit="GHz")
    176176            s.set_unit(self.fields['units'][self.fields['cunit']])
    177177            s.set_freqframe(self.form.getfirst("frame", "LSRK"))
     
    213213            rcp['figure.subplot.wspace'] = 0.3
    214214            rcp['figure.subplot.hspace'] = 0.3
    215             del asap.plotter
     215            #del asap.plotter
    216216            # plotter without GUI
    217217            asap.plotter = asap.asapplotter(False)
     
    259259        self.setDefaultFields()
    260260        title = "ASAP %s Online Monitor" % (observatory['name'])
    261         tmplname = abspath+"asapmon.html.template"
     261        tmplname = asapmonhome+"asapmon.html.template"
    262262        if ( self.form.has_key("plot")):
    263263            self.plotForm()
  • branches/alma/monitor/cgi-bin/obsconfig.py

    r712 r1757  
    55
    66# Append observing directories
    7 observatory['rpfpath'].append("/u/mar637/brage/singledish/data")
    8 observatory['rpfpath'].append("/u/mar637/brage/singledish/data/mopra200505")
    9 observatory['rpfpath'].append("/u/mar637/brage/singledish/data/mopra/phoenix")
     7observatory['rpfpath'].append("/DATA/MPCCC1_1/corr/dat/")
    108
    119# Restfrequencies in GHz
  • branches/alma/monitor/htdocs/asapmon.html.template

    r711 r1757  
    44    <head>
    55        <title tal:content="title">ASAP Online Monitor</title>
    6         <link rel="stylesheet" href="/asaptest/fields.css" type="text/css">
     6        <link rel="stylesheet" href="/asapmon/asapmon.css" type="text/css">
    77        <script type="text/javascript" src="/asapmon/prototype.js"></script>
    88        <script type="text/javascript" src="/asapmon/asapmon.js"></script>
  • branches/alma/python/__init__.py

    r1729 r1757  
    44"""
    55import os,sys,shutil, platform
     6try:
     7    from functools import wraps as wraps_dec
     8except ImportError:
     9    from asap.compatibility import wraps as wraps_dec
    610
    711# Set up CASAPATH and first time use of asap i.e. ~/.asap/*
     
    3337    #shutil.copyfile(asapdata+"/data/ipythonrc-asap", userdir+"/ipythonrc-asap")
    3438    # commented out by TT on 2009.06.23 for casapy use
    35     ##shutil.copyfile(asapdata+"/data/ipy_user_conf.py", 
     39    ##shutil.copyfile(asapdata+"/data/ipy_user_conf.py",
    3640    ##                userdir+"/ipy_user_conf.py")
    3741    f = file(userdir+"/asapuserfuncs.py", "w")
     
    4347    # upgrade to support later ipython versions
    4448    ##if not os.path.exists(userdir+"/ipy_user_conf.py"):
    45     ##    shutil.copyfile(asapdata+"/data/ipy_user_conf.py", 
     49    ##    shutil.copyfile(asapdata+"/data/ipy_user_conf.py",
    4650    ##                    userdir+"/ipy_user_conf.py")
    4751
     
    7478
    7579    """
    76 
    7780    fname = os.path.join( os.getcwd(), '.asaprc')
    7881    if os.path.exists(fname): return fname
     
    109112    'plotter.histogram'  : [False, _validate_bool],
    110113    'plotter.papertype'  : ['A4', str],
    111     'plotter.xaxisformatting' : ['asap', str],
     114    ## for older Matplotlib version
     115    #'plotter.axesformatting' : ['mpl', str],
     116    'plotter.axesformatting' : ['asap', str],
    112117
    113118    # scantable
     
    118123    'scantable.storage'   : ['memory', str],
    119124    'scantable.history'   : [True, _validate_bool],
    120     'scantable.reference'      : ['.*(e|w|_R)$', str]
     125    'scantable.reference'      : ['.*(e|w|_R)$', str],
     126    'scantable.parallactify'   : [False, _validate_bool]
    121127    # fitter
    122128    }
     
    146152plotter.panelling          : scan
    147153
    148 # push panels together, to share axislabels
     154# push panels together, to share axis labels
    149155plotter.ganged             : True
    150156
     
    164170
    165171# The formatting style of the xaxis
    166 plotter.xaxisformatting    : 'asap' or 'mpl'
     172plotter.axesformatting    : 'mpl' (default) or 'asap' (for old versions of matplotlib)
    167173
    168174# scantable
     
    189195# Control the identification of reference (off) scans
    190196# This is has to be a regular expression
    191 scantable.reference         : .*(e|w|_R)$
     197scantable.reference        : .*(e|w|_R)$
     198
     199# Indicate whether the data was parallactified (total phase offest == 0.0)
     200scantable.parallactify     : False
     201
    192202# Fitter
    193203"""
     
    290300
    291301def _n_bools(n, val):
    292     return [ val for i in xrange(n) ] 
     302    return [ val for i in xrange(n) ]
    293303
    294304def _is_sequence_or_number(param, ptype=int):
     
    357367    asaplog.disable()
    358368
     369
     370def print_log_dec(f):
     371    @wraps_dec(f)
     372    def wrap_it(*args, **kw):
     373        val = f(*args, **kw)
     374        print_log()
     375        return val
     376    return wrap_it
     377
    359378def print_log(level='INFO'):
    360379    from taskinit import casalog
     
    382401from scantable import scantable
    383402from asaplinefind import linefinder
     403from simplelinefinder import simplelinefinder
    384404from linecatalog import linecatalog
    385405from interactivemask import interactivemask
     406from opacity import skydip
     407from opacity import model as opacity_model
    386408
    387409if rcParams['useplotter']:
     
    392414            import matplotlib
    393415            if not matplotlib.sys.modules['matplotlib.backends']: matplotlib.use("TkAgg")
    394         import pylab
     416        from matplotlib import pylab
    395417        xyplotter = pylab
    396418        plotter = asapplotter(gui)
     
    402424
    403425__date__ = '$Date$'.split()[1]
    404 __version__  = '2.3.1 alma'
     426__version__  = '3.0.0 alma'
    405427# nrao casapy specific, get revision number
    406428#__revision__ = ' unknown '
     
    427449
    428450def is_ipython():
    429     return '__IP' in dir(sys.modules["__main__"])
     451    return 'IPython' in sys.modules.keys()
    430452if is_ipython():
    431453    def version(): print  "ASAP %s(%s)"% (__version__, __date__)
     454
    432455    def list_scans(t = scantable):
    433         import types
    434         globs = sys.modules['__main__'].__dict__.iteritems()
    435         print "The user created scantables are:"
    436         sts = map(lambda x: x[0], filter(lambda x: isinstance(x[1], t), globs))
    437         print filter(lambda x: not x.startswith('_'), sts)
    438         return
     456        import inspect
     457        print "The user created scantables are: ",
     458        globs=inspect.currentframe().f_back.f_locals.copy()
     459        out = [ k for k,v in globs.iteritems() \
     460                     if isinstance(v, scantable) and not k.startswith("_") ]
     461        print out
     462        return out
    439463
    440464    def commands():
     
    462486            get_elevation   - get the elevation of the scans
    463487            get_parangle    - get the parallactic angle of the scans
     488            get_coordinate  - get the spectral coordinate for the given row,
     489                              which can be used for coordinate conversions
     490            get_weather     - get the weather condition parameters
    464491            get_unit        - get the current unit
    465492            set_unit        - set the abcissa unit to be used from this
     
    506533            mx_quotient     - Form a quotient using MX data (off beams)
    507534            scale, *, /     - return a scan scaled by a given factor
    508             add, +, -       - return a scan with given value added
     535            add, +          - return a scan with given value added
     536            sub, -          - return a scan with given value subtracted
    509537            bin             - return a scan with binned channels
    510538            resample        - return a scan with resampled channels
     
    529557            stddev          - Determine the standard deviation of the current
    530558                              beam/if/pol
     559            get_row_selector - get the selection object for a specified row
     560                               number
    531561     [Selection]
    532562         selector              - a selection object to set a subset of a scantable
     
    590620            plot            - plot a scantable
    591621            plot_lines      - plot a linecatalog overlay
     622            plotazel        - plot azimuth and elevation versus time
     623            plotpointing    - plot telescope pointings
    592624            save            - save the plot to a file ('png' ,'ps' or 'eps')
    593625            set_mode        - set the state of the plotter, i.e.
     
    613645            axhline,axvline - draw horizontal/vertical lines
    614646            axhspan,axvspan - draw horizontal/vertical regions
     647            annotate        - draw an arrow with label
     648            create_mask     - create a scnatble mask interactively
    615649
    616650        xyplotter           - matplotlib/pylab plotting functions
    617 
    618     [Reading files]
    619         reader              - access rpfits/sdfits files
    620             open            - attach reader to a file
    621             close           - detach reader from file
    622             read            - read in integrations
    623             summary         - list info about all integrations
    624651
    625652    [General]
    626653        commands            - this command
    627654        print               - print details about a variable
    628         list_scans          - list all scantables created bt the user
     655        list_scans          - list all scantables created by the user
    629656        list_files          - list all files readable by asap (default rpf)
    630657        del                 - delete the given variable from memory
     
    639666        mask_not            - boolean operations on masks created with
    640667                              scantable.create_mask
     668        skydip              - gain opacity values from a sky dip observation
     669        opacity_model       - compute opacities fro given frequencies based on
     670                              atmospheric model
    641671
    642672    Note:
  • branches/alma/python/asapfitter.py

    r1701 r1757  
    11import _asap
    22from asap import rcParams
    3 from asap import print_log
     3from asap import print_log, print_log_dec
    44from asap import _n_bools
    55from asap import mask_and
     
    7979        Set the function to be fit.
    8080        Parameters:
    81             poly:    use a polynomial of the order given with nonlinear least squares fit 
     81            poly:    use a polynomial of the order given with nonlinear least squares fit
    8282            lpoly:   use polynomial of the order given with linear least squares fit
    8383            gauss:   fit the number of gaussian specified
     
    9595            n = kwargs.get('poly')
    9696            self.components = [n]
    97             self.uselinear = False 
     97            self.uselinear = False
    9898        elif kwargs.has_key('lpoly'):
    9999            self.fitfunc = 'poly'
     
    106106            self.fitfuncs = [ 'gauss' for i in range(n) ]
    107107            self.components = [ 3 for i in range(n) ]
    108             self.uselinear = False 
     108            self.uselinear = False
    109109        elif kwargs.has_key('lorentz'):
    110110            n = kwargs.get('lorentz')
     
    112112            self.fitfuncs = [ 'lorentz' for i in range(n) ]
    113113            self.components = [ 3 for i in range(n) ]
    114             self.uselinear = False 
     114            self.uselinear = False
    115115        else:
    116116            msg = "Invalid function type."
     
    127127        return
    128128
     129    #@print_log_dec
    129130    def fit(self, row=0, estimate=False):
    130131        """
     
    164165                                                                      self.data.getbeam(i),
    165166                                                                      self.data.getif(i),
    166                                                                       self.data.getpol(i), 
     167                                                                      self.data.getpol(i),
    167168                                                                      self.data.getcycle(i))
    168169                asaplog.push(out,False)
     
    221222                self.data._addfit(fit,self._fittedrow)
    222223
    223     #def set_parameters(self, params, fixed=None, component=None):
     224    #@print_log_dec
    224225    def set_parameters(self,*args,**kwargs):
    225226        """
     
    543544        return self.fitter.getfit()
    544545
     546    #@print_log_dec
    545547    def commit(self):
    546548        """
     
    571573        return scan
    572574
    573     def plot(self, residual=False, components=None, plotparms=False, filename=None):
     575    #@print_log_dec
     576    def plot(self, residual=False, components=None, plotparms=False,
     577             filename=None):
    574578        """
    575579        Plot the last fit.
     
    598602        xlab = 'Abcissa'
    599603        ylab = 'Ordinate'
    600         from matplotlib.numerix import ma,logical_not,logical_and,array
     604        from numpy import ma,logical_not,logical_and,array
    601605        m = self.mask
    602606        if self.data:
     
    606610                             array(self.data._getmask(self._fittedrow),
    607611                                   copy=False))
    608                              
     612
    609613            ylab = self.data._get_ordinate_label()
    610614
     
    670674        print_log()
    671675
     676    #@print_log_dec
    672677    def auto_fit(self, insitu=None, plot=False):
    673678        """
     
    700705                                                                   scan.getbeam(r),
    701706                                                                   scan.getif(r),
    702                                                                    scan.getpol(r), 
     707                                                                   scan.getpol(r),
    703708                                                                   scan.getcycle(r))
    704709            asaplog.push(out, False)
     
    723728        print_log()
    724729        return scan
    725 
  • branches/alma/python/asaplinefind.py

    r929 r1757  
    4141
    4242    def set_options(self,threshold=1.7320508075688772,min_nchan=3,
    43         avg_limit=8,box_size=0.2):
     43        avg_limit=8,box_size=0.2,noise_box='all',noise_stat='mean80'):
    4444        """
    4545        Set the parameters of the algorithm
     
    5555                          this parameter can be averaged to search for
    5656                          broad lines. Default is 8.
    57              box_size     A running mean box size specified as a fraction
     57             box_size     A running mean/median box size specified as a fraction
    5858                          of the total spectrum length. Default is 1/5
     59             noise_box    Area of the spectrum used to estimate noise stats
     60                          Both string values and numbers are allowed
     61                          Allowed string values:
     62                             'all' use all the spectrum (default)
     63                             'box' noise box is the same as running mean/median
     64                                   box
     65                          Numeric values are defined as a fraction from the
     66                          spectrum size. Values should be positive.
     67                          (noise_box == box_size has the same effect as
     68                           noise_box = 'box')
     69             noise_stat   Statistics used to estimate noise, allowed values:
     70                              'mean80' use the 80% of the lowest deviations
     71                                       in the noise box (default)
     72                              'median' median of deviations in the noise box
     73                             
    5974        Note:  For bad baselines threshold should be increased,
    6075               and avg_limit decreased (or even switched off completely by
     
    6277               undulations instead of real lines.
    6378        """
    64         self.finder.setoptions(threshold,min_nchan,avg_limit,box_size)
     79        if noise_stat.lower() not in ["mean80",'median']:
     80           raise RuntimeError, "noise_stat argument in linefinder.set_options can only be mean80 or median"
     81        nStat = (noise_stat.lower() == "median")
     82        nBox = -1.
     83        if isinstance(noise_box,str):
     84           if noise_box.lower() not in ['all','box']:
     85              raise RuntimeError, "string-valued noise_box in linefinder.set_options can only be all or box"
     86           if noise_box.lower() == 'box':
     87              nBox = box_size
     88        else:
     89           nBox = float(noise_box)
     90        self.finder.setoptions(threshold,min_nchan,avg_limit,box_size,nBox,nStat)
    6591        return
    6692
  • branches/alma/python/asaplot.py

    r708 r1757  
    1111    ASAP plotting class based on matplotlib.
    1212    """
    13     def __init__(self, rows=1, cols=0, title='', size=(8,4), buffering=False):
     13    def __init__(self, rows=1, cols=0, title='', size=None, buffering=False):
    1414        """
    1515        Create a new instance of the ASAPlot plotting class.
  • branches/alma/python/asaplotbase.py

    r1723 r1757  
    1010from matplotlib.figure import Figure, Text
    1111from matplotlib.font_manager import FontProperties as FP
    12 from matplotlib.numerix import sqrt
     12from numpy import sqrt
    1313from matplotlib import rc, rcParams
    1414from asap import rcParams as asaprcParams
    1515from matplotlib.ticker import OldScalarFormatter
    16 from matplotlib.ticker import NullLocator
    1716
    1817# API change in mpl >= 0.98
     
    2019    from matplotlib.transforms import blended_transform_factory
    2120except ImportError:
    22     from matplotlib.transforms import blend_xy_sep_transform  as blended_transform_factory
     21    from matplotlib.transforms import blend_xy_sep_transform as blended_transform_factory
    2322
    2423from asap import asaplog
     
    2928    print_log( 'WARN' )
    3029
    31 #class MyFormatter(OldScalarFormatter):
    32 #    def __call__(self, x, pos=None):
    33 #        last = len(self.locs)-2
    34 #        if pos==0:
    35 #            return ''
    36 #        else: return OldScalarFormatter.__call__(self, x, pos)
    37 
    3830class asaplotbase:
    3931    """
     
    4133    """
    4234
    43     def __init__(self, rows=1, cols=0, title='', size=(8,6), buffering=False):
     35    def __init__(self, rows=1, cols=0, title='', size=None, buffering=False):
    4436        """
    4537        Create a new instance of the ASAPlot plotting class.
     
    157149        fmt is the line style as in plot().
    158150        """
    159         from matplotlib.numerix import array
    160         from matplotlib.numerix.ma import MaskedArray
     151        from numpy import array
     152        from numpy.ma import MaskedArray
    161153        if x is None:
    162154            if y is None: return
     
    289281        self.register('button_press', position_disable)
    290282
     283
     284#     def get_region(self):
     285#         pos = []
     286#         print "Please select the bottom/left point"
     287#         pos.append(self.figure.ginput(n=1, show_clicks=False)[0])
     288#         print "Please select the top/right point"
     289#         pos.append(self.figure.ginput(n=1, show_clicks=False)[0])
     290#         return pos
     291
     292#     def get_point(self):
     293#         print "Please select the point"
     294#         pt = self.figure.ginput(n=1, show_clicks=False)
     295#         if pt:
     296#             return pt[0]
     297#         else:
     298#             return None
    291299
    292300    def region(self):
     
    640648                    self.subplots[i]['axes'] = self.figure.add_subplot(rows,
    641649                                                cols, i+1)
    642                     if asaprcParams['plotter.xaxisformatting'] == 'mpl':
     650                    if asaprcParams['plotter.axesformatting'] != 'mpl':
    643651                        self.subplots[i]['axes'].xaxis.set_major_formatter(OldScalarFormatter())
    644652                else:
     
    646654                        self.subplots[i]['axes'] = self.figure.add_subplot(rows,
    647655                                                cols, i+1)
    648                         if asaprcParams['plotter.xaxisformatting'] != 'mpl':
     656                        if asaprcParams['plotter.axesformatting'] != 'mpl':
    649657                           
    650658                            self.subplots[i]['axes'].xaxis.set_major_formatter(OldScalarFormatter())
     
    730738
    731739            from matplotlib.artist import setp
    732             fp = FP(size=rcParams['xtick.labelsize'])
    733             xts = fp.get_size_in_points()- (self.cols)/2
    734             fp = FP(size=rcParams['ytick.labelsize'])
    735             yts = fp.get_size_in_points() - (self.rows)/2
     740            fpx = FP(size=rcParams['xtick.labelsize'])
     741            xts = fpx.get_size_in_points()- (self.cols)/2
     742            fpy = FP(size=rcParams['ytick.labelsize'])
     743            yts = fpy.get_size_in_points() - (self.rows)/2
     744            fpa = FP(size=rcParams['axes.labelsize'])
     745            fpat = FP(size=rcParams['axes.titlesize'])
     746            axsize =  fpa.get_size_in_points()
     747            tsize =  fpat.get_size_in_points()-(self.cols)/2
    736748            for sp in self.subplots:
    737749                ax = sp['axes']
    738                 #s = ax.title.get_size()
    739                 #tsize = s-(self.cols+self.rows)
    740                 s=FP(size=rcParams['axes.titlesize'])
    741                 tsize = s.get_size_in_points()-(self.cols)/2
    742750                ax.title.set_size(tsize)
    743                 fp = FP(size=rcParams['axes.labelsize'])
    744751                setp(ax.get_xticklabels(), fontsize=xts)
    745752                setp(ax.get_yticklabels(), fontsize=yts)
    746                 origx =  fp.get_size_in_points()
    747                 origy = origx
    748753                off = 0
    749754                if self.cols > 1: off = self.cols
    750                 xfsize = origx-off
    751                 ax.xaxis.label.set_size(xfsize)
     755                ax.xaxis.label.set_size(axsize-off)
    752756                off = 0
    753757                if self.rows > 1: off = self.rows
    754                 yfsize = origy-off
    755                 ax.yaxis.label.set_size(yfsize)
     758                ax.yaxis.label.set_size(axsize-off)
    756759
    757760    def subplot(self, i=None, inc=None):
  • branches/alma/python/asaplotgui.py

    r1699 r1757  
    1616    """
    1717
    18     def __init__(self, rows=1, cols=0, title='', size=(8,6), buffering=False):
     18    def __init__(self, rows=1, cols=0, title='', size=None, buffering=False):
    1919        """
    2020        Create a new instance of the ASAPlot plotting class.
  • branches/alma/python/asaplotgui_gtk.py

    r1619 r1757  
    1818    """
    1919
    20     def __init__(self, rows=1, cols=0, title='', size=(8,6), buffering=False):
     20    def __init__(self, rows=1, cols=0, title='', size=None, buffering=False):
    2121        """
    2222        Create a new instance of the ASAPlot plotting class.
  • branches/alma/python/asaplotgui_qt4.py

    r1640 r1757  
    1818    """
    1919
    20     def __init__(self, rows=1, cols=0, title='', size=(8,6), buffering=False):
     20    def __init__(self, rows=1, cols=0, title='', size=None, buffering=False):
    2121        """
    2222        Create a new instance of the ASAPlot plotting class.
  • branches/alma/python/asapmath.py

    r1693 r1757  
    11from asap.scantable import scantable
    22from asap import rcParams
    3 from asap import print_log
     3from asap import print_log, print_log_dec
    44from asap import selector
    55from asap import asaplog
    66from asap import asaplotgui
    77
     8#@print_log_dec
    89def average_time(*args, **kwargs):
    910    """
     
    2930        # without using a mask
    3031        scanav = average_time(scana,scanb)
    31         # or equivalent
    32         # scanav = average_time([scana, scanb])
     32        # or equivalent
     33        # scanav = average_time([scana, scanb])
    3334        # return the (time) averaged scan, i.e. the average of
    3435        # all correlator cycles
     
    122123    return s
    123124
     125#@print_log_dec
    124126def dototalpower(calon, caloff, tcalval=0.0):
    125127    """
     
    140142    return s
    141143
     144#@print_log_dec
    142145def dosigref(sig, ref, smooth, tsysval=0.0, tauval=0.0):
    143146    """
     
    160163    return s
    161164
     165#@print_log_dec
    162166def calps(scantab, scannos, smooth=1, tsysval=0.0, tauval=0.0, tcalval=0.0, verify=False):
    163167    """
     
    442446    return ress
    443447
     448#@print_log_dec
    444449def calnod(scantab, scannos=[], smooth=1, tsysval=0.0, tauval=0.0, tcalval=0.0, verify=False):
    445450    """
     
    682687    return resspec
    683688
     689#@print_log_dec
    684690def calfs(scantab, scannos=[], smooth=1, tsysval=0.0, tauval=0.0, tcalval=0.0, verify=False):
    685691    """
     
    889895    return resspec
    890896
    891 def simple_math(left, right, op='add', tsys=True):
    892     """
    893     Apply simple mathematical binary operations to two
    894     scan tables,  returning the result in a new scan table.
    895     The operation is applied to both the correlations and the TSys data
    896     The cursor of the output scan is set to 0
    897     Parameters:
    898         left:          the 'left' scan
    899         right:         the 'right' scan
    900         op:            the operation: 'add' (default), 'sub', 'mul', 'div'
    901         tsys:          if True (default) then apply the operation to Tsys
    902                        as well as the data
    903     """
    904     #print "simple_math is deprecated use +=/* instead."
    905     asaplog.push( "simple_math is deprecated use +=/* instead." )
    906     print_log('WARN')
    907 
     897#@print_log_dec
    908898def merge(*args):
    909899    """
     
    914904    Example:
    915905        myscans = [scan1, scan2]
    916         allscans = merge(myscans)
    917         # or equivalent
    918         sameallscans = merge(scan1, scan2)
     906        allscans = merge(myscans)
     907        # or equivalent
     908        sameallscans = merge(scan1, scan2)
    919909    """
    920910    varlist = vars()
  • branches/alma/python/asapplotter.py

    r1732 r1757  
    1 from asap import rcParams, print_log, selector
     1from asap import rcParams, print_log, print_log_dec
     2from asap import selector, scantable
    23from asap import asaplog
    34import matplotlib.axes
     5from matplotlib.font_manager import FontProperties
     6from matplotlib.text import Text
     7
    48import re
    59
     
    1317        other variables.
    1418    """
    15     def __init__(self, visible=None):
     19    def __init__(self, visible=None , **kwargs):
    1620        self._visible = rcParams['plotter.gui']
    1721        if visible is not None:
    1822            self._visible = visible
    19         self._plotter = self._newplotter()
     23        self._plotter = self._newplotter(**kwargs)
    2024        if self._visible and matplotlib.get_backend() == "TkAgg":
    2125            from asap.casatoolbar import CustomToolbarTkAgg
     
    4246        self._selection = selector()
    4347        self._hist = rcParams['plotter.histogram']
     48        self._fp = FontProperties()
    4449        self._panellayout = self.set_panellayout(refresh=False)
    4550
     
    5257        return None
    5358
    54     def _newplotter(self):
     59    def _newplotter(self, **kwargs):
    5560        backend=matplotlib.get_backend()
    5661        if not self._visible:
     
    6469        else:
    6570            from asap.asaplot import asaplot
    66         return asaplot()
    67 
    68 
     71        return asaplot(**kwargs)
     72
     73    #@print_log_dec
    6974    def plot(self, scan=None):
    7075        """
     
    101106        return
    102107
     108    def gca(self):
     109        return self._plotter.figure.gca()
     110
     111    def refresh(self):
     112        """Do a soft refresh"""
     113        self._plotter.figure.show()
     114
     115    def create_mask(self, nwin=1, panel=0, color=None):
     116        """
     117        Interactively define a mask.It retruns a mask that is equivalent to
     118        the one created manually with scantable.create_mask.
     119        Parameters:
     120            nwin:       The number of mask windows to create interactively
     121                        default is 1.
     122            panel:      Which panel to use for mask selection. This is useful
     123                        if different IFs are spread over panels (default 0)
     124        """
     125        if self._data is None:
     126            return []
     127        outmask = []
     128        self._plotter.subplot(panel)
     129        xmin, xmax = self._plotter.axes.get_xlim()
     130        marg = 0.05*(xmax-xmin)
     131        self._plotter.axes.set_xlim(xmin-marg, xmax+marg)
     132        self.refresh()
     133
     134        def cleanup(lines=False, texts=False, refresh=False):
     135            if lines:
     136                del self._plotter.axes.lines[-1]
     137            if texts:
     138                del self._plotter.axes.texts[-1]
     139            if refresh:
     140                self.refresh()
     141
     142        for w in xrange(nwin):
     143            wpos = []
     144            self.text(0.05,1.0, "Add start boundary",
     145                      coords="relative", fontsize=10)
     146            point = self._plotter.get_point()
     147            cleanup(texts=True)
     148            if point is None:
     149                continue
     150            wpos.append(point[0])
     151            self.axvline(wpos[0], color=color)
     152            self.text(0.05,1.0, "Add end boundary", coords="relative", fontsize=10)
     153            point = self._plotter.get_point()
     154            cleanup(texts=True, lines=True)
     155            if point is None:
     156                self.refresh()
     157                continue
     158            wpos.append(point[0])
     159            self.axvspan(wpos[0], wpos[1], alpha=0.1,
     160                         edgecolor=color, facecolor=color)
     161            ymin, ymax = self._plotter.axes.get_ylim()
     162            outmask.append(wpos)
     163
     164        self._plotter.axes.set_xlim(xmin, xmax)
     165        self.refresh()
     166        if len(outmask) > 0:
     167            return self._data.create_mask(*outmask)
     168        return []
    103169
    104170    # forwards to matplotlib axes
    105171    def text(self, *args, **kwargs):
     172        if kwargs.has_key("interactive"):
     173            #if kwargs.pop("interactive"):
     174            #    pos = self._plotter.get_point()
     175            #    args = tuple(pos)+args
     176            kwargs.pop("interactive")
    106177        self._axes_callback("text", *args, **kwargs)
     178
    107179    text.__doc__ = matplotlib.axes.Axes.text.__doc__
     180
    108181    def arrow(self, *args, **kwargs):
     182        if kwargs.has_key("interactive"):
     183            #if kwargs.pop("interactive"):
     184            #    pos = self._plotter.get_region()
     185            #    dpos = (pos[0][0], pos[0][1],
     186            #            pos[1][0]-pos[0][0],
     187            #            pos[1][1] - pos[0][1])
     188            #    args = dpos + args
     189            kwargs.pop("interactive")
    109190        self._axes_callback("arrow", *args, **kwargs)
     191
    110192    arrow.__doc__ = matplotlib.axes.Axes.arrow.__doc__
     193
     194    def annotate(self, text, xy=None, xytext=None, **kwargs):
     195        if kwargs.has_key("interactive"):
     196            #if kwargs.pop("interactive"):
     197            #    xy = self._plotter.get_point()
     198            #    xytext = self._plotter.get_point()
     199            kwargs.pop("interactive")
     200        if not kwargs.has_key("arrowprops"):
     201            kwargs["arrowprops"] = dict(arrowstyle="->")
     202        self._axes_callback("annotate", text, xy, xytext, **kwargs)
     203
     204    annotate.__doc__ = matplotlib.axes.Axes.annotate.__doc__
     205
    111206    def axvline(self, *args, **kwargs):
     207        if kwargs.has_key("interactive"):
     208            #if kwargs.pop("interactive"):
     209            #    pos = self._plotter.get_point()
     210            #    args = (pos[0],)+args
     211            kwargs.pop("interactive")
    112212        self._axes_callback("axvline", *args, **kwargs)
     213
    113214    axvline.__doc__ = matplotlib.axes.Axes.axvline.__doc__
     215
    114216    def axhline(self, *args, **kwargs):
     217        if kwargs.has_key("interactive"):
     218            #if kwargs.pop("interactive"):
     219            #    pos = self._plotter.get_point()
     220            #    args = (pos[1],)+args
     221            kwargs.pop("interactive")
    115222        self._axes_callback("axhline", *args, **kwargs)
     223
    116224    axhline.__doc__ = matplotlib.axes.Axes.axhline.__doc__
     225
    117226    def axvspan(self, *args, **kwargs):
     227        if kwargs.has_key("interactive"):
     228            #if kwargs.pop("interactive"):
     229            #    pos = self._plotter.get_region()
     230            #    dpos = (pos[0][0], pos[1][0])
     231            #    args = dpos + args
     232            kwargs.pop("interactive")
    118233        self._axes_callback("axvspan", *args, **kwargs)
    119234        # hack to preventy mpl from redrawing the patch
    120235        # it seem to convert the patch into lines on every draw.
    121236        # This doesn't happen in a test script???
    122         del self._plotter.axes.patches[-1]
     237        #del self._plotter.axes.patches[-1]
     238
    123239    axvspan.__doc__ = matplotlib.axes.Axes.axvspan.__doc__
    124240
    125241    def axhspan(self, *args, **kwargs):
     242        if kwargs.has_key("interactive"):
     243            #if kwargs.pop("interactive"):
     244            #    pos = self._plotter.get_region()
     245            #    dpos = (pos[0][1], pos[1][1])
     246            #    args = dpos + args
     247            kwargs.pop("interactive")
    126248        self._axes_callback("axhspan", *args, **kwargs)
    127249        # hack to preventy mpl from redrawing the patch
    128250        # it seem to convert the patch into lines on every draw.
    129251        # This doesn't happen in a test script???
    130         del self._plotter.axes.patches[-1]
     252        #del self._plotter.axes.patches[-1]
     253
    131254    axhspan.__doc__ = matplotlib.axes.Axes.axhspan.__doc__
    132255
     
    465588        if refresh and self._data: self.plot(self._data)
    466589
    467     def set_font(self, family=None, style=None, weight=None, size=None, refresh=True):
     590    def set_font(self, refresh=True,**kwargs):
    468591        """
    469592        Set font properties.
     
    479602        """
    480603        from matplotlib import rc as rcp
    481         if isinstance(family, str):
    482             rcp('font', family=family)
    483         if isinstance(style, str):
    484             rcp('font', style=style)
    485         if isinstance(weight, str):
    486             rcp('font', weight=weight)
    487         if isinstance(size, float) or isinstance(size, int):
    488             rcp('font', size=size)
     604        fdict = {}
     605        for k,v in kwargs.iteritems():
     606            if v:
     607                fdict[k] = v
     608        self._fp = FontProperties(**fdict)
    489609        if refresh and self._data: self.plot(self._data)
    490610
     
    540660        if not self._data.get_unit().endswith("Hz"):
    541661            raise RuntimeError("Can only overlay linecatalogs when data is in frequency.")
    542         from matplotlib.numerix import ma
     662        from numpy import ma
    543663        for j in range(len(self._plotter.subplots)):
    544664            self._plotter.subplot(j)
     
    716836        if isinstance(nstack0, int): nstack = nstack0
    717837        else: nstack = len(nstack0)
    718         maxpanel, maxstack = 16,8
     838        maxpanel, maxstack = 16,16
    719839        if n > maxpanel or nstack > maxstack:
    720840            maxn = 0
     
    761881                ylab = self._ordinate and self._ordinate[panelcount] \
    762882                       or scan._get_ordinate_label()
    763                 self._plotter.set_axes('xlabel',xlab)
    764                 self._plotter.set_axes('ylabel',ylab)
     883                self._plotter.set_axes('xlabel', xlab)
     884                self._plotter.set_axes('ylabel', ylab)
    765885                lbl = self._get_label(scan, r, self._panelling, self._title)
    766886                if isinstance(lbl, list) or isinstance(lbl, tuple):
     
    781901                    y = scan._getspectrum(r)
    782902                m = scan._getmask(r)
    783                 from matplotlib.numerix import logical_not, logical_and
     903                from numpy import logical_not, logical_and
    784904                if self._maskselection and len(self._usermask) == len(m):
    785905                    if d[self._stacking](r) in self._maskselection[self._stacking]:
    786906                        m = logical_and(m, self._usermask)
    787907                x = scan._getabcissa(r)
    788                 from matplotlib.numerix import ma, array
     908                from numpy import ma, array
    789909                y = ma.masked_array(y,mask=logical_not(array(m,copy=False)))
    790910                if self._minmaxx is not None:
     
    839959        #reset the selector to the scantable's original
    840960        scan.set_selection(savesel)
    841 
    842     def set_selection(self, selection=None, refresh=True):
     961       
     962        #temporary switch-off for older matplotlib
     963        #if self._fp is not None:
     964        if self._fp is not None and getattr(self._plotter.figure,'findobj',False):
     965            for o in self._plotter.figure.findobj(Text):
     966                o.set_fontproperties(self._fp)
     967
     968    def set_selection(self, selection=None, refresh=True, **kw):
    843969        """
    844970        Parameters:
     
    848974                        Otherwise,the parameter(s) are set without replotting.
    849975        """
    850         self._selection = isinstance(selection,selector) and selection or selector()
     976        if selection is None:
     977            # reset
     978            if len(kw) == 0:
     979                self._selection = selector()
     980            else:
     981                # try keywords
     982                for k in kw:
     983                    if k not in selector.fields:
     984                        raise KeyError("Invalid selection key '%s', valid keys are %s" % (k, selector.fields))
     985                self._selection = selector(**kw)
     986        elif isinstance(selection, selector):
     987            self._selection = selection
     988        else:
     989            raise TypeError("'selection' is not of type selector")
     990
    851991        d0 = {'s': 'SCANNO', 'b': 'BEAMNO', 'i':'IFNO',
    852992              'p': 'POLNO', 'c': 'CYCLENO', 't' : 'TIME' }
     
    8851025
    8861026    def plotazel(self, scan=None, outfile=None):
    887         """
    888         plot azimuth and elevation  versus time of a scantable
    889         """
    890         import pylab as PL
    891         from matplotlib.dates import DateFormatter, timezone, HourLocator, MinuteLocator, DayLocator
     1027    #def plotazel(self):
     1028        """
     1029        plot azimuth and elevation versus time of a scantable
     1030        """
     1031        from matplotlib import pylab as PL
     1032        from matplotlib.dates import DateFormatter, timezone
     1033        from matplotlib.dates import HourLocator, MinuteLocator,SecondLocator, DayLocator
    8921034        from matplotlib.ticker import MultipleLocator
    893         from matplotlib.numerix import array, pi
     1035        from numpy import array, pi
    8941036        self._data = scan
    8951037        self._outfile = outfile
     
    8981040        tz = timezone('UTC')
    8991041        PL.cla()
    900         #PL.ioff()
     1042        PL.ioff()
    9011043        PL.clf()
    9021044        # Adjust subplot layouts
     
    9171059            minloc = HourLocator(range(0,23,12))
    9181060            timefmt = DateFormatter("%b%d")
     1061        elif tdel > 24./60.:
     1062            timefmt = DateFormatter('%H:%M')
     1063            majloc = HourLocator()
     1064            minloc = MinuteLocator(30)
    9191065        else:
    920             timefmt = DateFormatter('%H')
    921             majloc = HourLocator()
    922             minloc = MinuteLocator(20)
     1066            timefmt = DateFormatter('%H:%M')
     1067            majloc = MinuteLocator(interval=5)
     1068            minloc = SecondLocator(30)
     1069
    9231070        PL.title(dstr)
    924 
    9251071        if tdel == 0.0:
    9261072            th = (t - PL.floor(t))*24.0
     
    9471093                if az[irow] < 0: az[irow] += 360.0
    9481094
    949         ax = PL.subplot(2,1,2)
     1095        ax2 = PL.subplot(2,1,2)
    9501096        #PL.xlabel('Time (UT [hour])')
    9511097        PL.ylabel('Az [deg.]')
     
    9541100        else:
    9551101            PL.plot_date(t,az,'o', markersize=2,markeredgecolor='b',markerfacecolor='b',tz=tz)
    956             ax.xaxis.set_major_formatter(timefmt)
    957             ax.xaxis.set_major_locator(majloc)
    958             ax.xaxis.set_minor_locator(minloc)
    959         #ax.grid(True)
    960         ax.set_ylim(0,360)
    961         ax.yaxis.grid(True)
     1102            ax2.xaxis.set_major_formatter(timefmt)
     1103            ax2.xaxis.set_major_locator(majloc)
     1104            ax2.xaxis.set_minor_locator(minloc)
     1105        #ax2.grid(True)
     1106        ax2.set_ylim(0,360)
     1107        ax2.yaxis.grid(True)
    9621108        #hfmt = DateFormatter('%H')
    9631109        #hloc = HourLocator()
    9641110        yloc = MultipleLocator(60)
    965         ax.yaxis.set_major_locator(yloc)
     1111        ax2.yaxis.set_major_locator(yloc)
    9661112        if tdel > 1.0:
    967             labels = ax.get_xticklabels()
     1113            labels = ax2.get_xticklabels()
    9681114            PL.setp(labels, fontsize=10)
    9691115            PL.xlabel('Time (UT [day])')
     
    9711117            PL.xlabel('Time (UT [hour])')
    9721118
    973         #PL.ion()
     1119        PL.ion()
    9741120        PL.draw()
    9751121        if (self._outfile is not None):
     
    9771123
    9781124    def plotpointing(self, scan=None, outfile=None):
     1125    #def plotpointing(self):
    9791126        """
    9801127        plot telescope pointings
    9811128        """
    982         import pylab as PL
    983         from matplotlib.dates import DateFormatter, timezone
    984         from matplotlib.ticker import MultipleLocator
    985         from matplotlib.numerix import array, pi, zeros
     1129        from matplotlib import pylab as PL
     1130        from numpy import array, pi
    9861131        self._data = scan
    9871132        self._outfile = outfile
     
    10011146        #ax = PL.axes([0.1,0.1,0.8,0.8])
    10021147        ax.set_aspect('equal')
    1003         PL.plot(ra,dec, 'b,')
     1148        PL.plot(ra, dec, 'b,')
    10041149        PL.xlabel('RA [deg.]')
    10051150        PL.ylabel('Declination [deg.]')
     
    11351280        # Print Observation header to the upper-left corner of plot
    11361281        if plot:
    1137             srest=ssum[ssum.find('Rest Freqs:'):ssum.find('Abcissa:')]
    1138             shead=ssum[ssum.find('Beams:'):ssum.find('Flux Unit:')]
    1139             headstr=shead.split('\n\n')
    1140             if extrastr != '': headstr[1]=extrastr+'\n'+headstr[1]
     1282            headstr=[ssum[ssum.find('Observer:'):ssum.find('Flux Unit:')]]
     1283            headstr.append(ssum[ssum.find('Beams:'):ssum.find('Observer:')]
     1284                         +ssum[ssum.find('Rest Freqs:'):ssum.find('Abcissa:')])
     1285            if extrastr != '': headstr[0]=extrastr+'\n'+headstr[0]
    11411286            #headstr[1]='Data File:     '+(filestr or 'unknown')+'\n'+headstr[1]
    1142             headstr[0]=headstr[0]+'\n'+srest
    1143             headstr.reverse()
    11441287            ssel='***Selections***\n'+(selstr+self._data.get_selection().__str__() or 'none')
    11451288            headstr.append(ssel)
     
    11591302                            verticalalignment='bottom',fontsize=8)
    11601303            self._plotter.release()
    1161             del srest, shead, headstr, ssel
     1304            del headstr, ssel
    11621305        if logger:
    11631306            asaplog.push("----------------\n  Plot Summary\n----------------")
  • branches/alma/python/asapreader.py

    r1059 r1757  
    11from asap._asap import stfiller
    2 from asap import print_log
     2from asap import print_log, print_log_dec
    33
    44class reader(stfiller):
     
    2525               rpfits ONLY.
    2626    """
    27 
     27    #@print_log_dec
    2828    def __init__(self, filename, unit=None, theif=None, thebeam=None):
    2929        self.unit = unit
     
    4848        print_log()
    4949
     50    #@print_log_dec
    5051    def read(self):
    5152        """
  • branches/alma/python/scantable.py

    r1701 r1757  
     1import os
     2try:
     3    from functools import wraps as wraps_dec
     4except ImportError:
     5    from asap.compatibility import wraps as wraps_dec
     6
    17from asap._asap import Scantable
    28from asap import rcParams
    3 from asap import print_log
     9from asap import print_log, print_log_dec
    410from asap import asaplog
    511from asap import selector
    612from asap import linecatalog
     13from asap.coordinate import coordinate
    714from asap import _n_bools, mask_not, mask_and, mask_or
     15
     16
     17def preserve_selection(func):
     18    @wraps_dec(func)
     19    def wrap(obj, *args, **kw):
     20        basesel = obj.get_selection()
     21        val = func(obj, *args, **kw)
     22        obj.set_selection(basesel)
     23        return val
     24    return wrap
     25
     26
     27def is_scantable(filename):
     28    return (os.path.isdir(filename)
     29            and not os.path.exists(filename+'/table.f1')
     30            and os.path.exists(filename+'/table.info'))
     31
    832
    933class scantable(Scantable):
     
    1236    """
    1337
    14     def __init__(self, filename, average=None, unit=None, getpt=None, antenna=None):
     38    #@print_log_dec
     39    def __init__(self, filename, average=None, unit=None, getpt=None, antenna=None, parallactify=None):
    1540        """
    1641        Create a scantable from a saved one or make a reference
     
    3661            antenna:     Antenna selection. integer (id) or string (name
    3762                         or id).
     63            parallactify: Indcicate that the data had been parallatified.
     64                          Default is taken form rc file.
    3865        """
    3966        if average is None:
     
    5784                    return
    5885            antenna = tmpstr.rstrip(',')
     86        parallactify = parallactify or rcParams['scantable.parallactify']
    5987        varlist = vars()
    6088        from asap._asap import stmath
     
    6391            Scantable.__init__(self, filename)
    6492        else:
    65             if isinstance(filename, str):# or \
    66 #                (isinstance(filename, list) or isinstance(filename, tuple)) \
    67 #                  and isinstance(filename[-1], str):
    68                 import os.path
     93            if isinstance(filename, str):
    6994                filename = os.path.expandvars(filename)
    7095                filename = os.path.expanduser(filename)
     
    7398                    if rcParams['verbose']:
    7499                        asaplog.push(s)
    75                         #print asaplog.pop().strip()
    76100                        print_log('ERROR')
    77101                        return
    78102                    raise IOError(s)
    79                 if os.path.isdir(filename) \
    80                     and not os.path.exists(filename+'/table.f1'):
    81                     # crude check if asap table
    82                     if os.path.exists(filename+'/table.info'):
    83                         ondisk = rcParams['scantable.storage'] == 'disk'
    84                         Scantable.__init__(self, filename, ondisk)
    85                         if unit is not None:
    86                             self.set_fluxunit(unit)
    87                         # do not reset to the default freqframe
    88                         #self.set_freqframe(rcParams['scantable.freqframe'])
     103                if is_scantable(filename):
     104                    ondisk = rcParams['scantable.storage'] == 'disk'
     105                    Scantable.__init__(self, filename, ondisk)
     106                    if unit is not None:
     107                        self.set_fluxunit(unit)
     108                    # do not reset to the default freqframe
     109                    #self.set_freqframe(rcParams['scantable.freqframe'])
     110                elif os.path.isdir(filename) \
     111                         and not os.path.exists(filename+'/table.f1'):
     112                    msg = "The given file '%s'is not a valid " \
     113                          "asap table." % (filename)
     114                    if rcParams['verbose']:
     115                        #print msg
     116                        asaplog.push( msg )
     117                        print_log( 'ERROR' )
     118                        return
    89119                    else:
    90                         msg = "The given file '%s'is not a valid " \
    91                               "asap table." % (filename)
    92                         if rcParams['verbose']:
    93                             #print msg
    94                             asaplog.push( msg )
    95                             print_log( 'ERROR' )
    96                             return
    97                         else:
    98                             raise IOError(msg)
     120                        raise IOError(msg)
    99121                else:
    100122                    self._fill([filename], unit, average, getpt, antenna)
     
    102124                  and isinstance(filename[-1], str):
    103125                self._fill(filename, unit, average, getpt, antenna)
     126        self.parallactify(parallactify)
    104127        self._add_history("scantable", varlist)
    105128        print_log()
    106129
     130    #@print_log_dec
    107131    def save(self, name=None, format=None, overwrite=False):
    108132        """
     
    119143                                       'MS2' (saves as an aips++
    120144                                              MeasurementSet V2)
    121                                        'FITS' (save as image FITS - not 
     145                                       'FITS' (save as image FITS - not
    122146                                               readable by class)
    123147                                       'CLASS' (save as FITS readable by CLASS)
     
    130154        """
    131155        from os import path
    132         if format is None: format = rcParams['scantable.save']
     156        format = format or rcParams['scantable.save']
    133157        suffix = '.'+format.lower()
    134158        if name is None or name == "":
     
    203227            else: raise
    204228        try:
    205             bsel = self.get_selection()
    206             sel = selector()
    207             sel.set_scans(allscans)
    208             self.set_selection(bsel+sel)
    209             scopy = self._copy()
    210             self.set_selection(bsel)
    211             return scantable(scopy)
     229            sel = selector(scans=allscans)
     230            return self._select_copy(sel)
    212231        except RuntimeError:
    213232            if rcParams['verbose']:
     
    219238                raise
    220239
     240    def _select_copy(self, selection):
     241        orig = self.get_selection()
     242        self.set_selection(orig+selection)
     243        cp = self.copy()
     244        self.set_selection(orig)
     245        return cp
    221246
    222247    def get_scan(self, scanid=None):
     
    253278            if type(scanid) is str:
    254279                sel.set_name(scanid)
    255                 self.set_selection(bsel+sel)
    256                 scopy = self._copy()
    257                 self.set_selection(bsel)
    258                 return scantable(scopy)
     280                return self._select_copy(sel)
    259281            elif type(scanid) is int:
    260282                sel.set_scans([scanid])
    261                 self.set_selection(bsel+sel)
    262                 scopy = self._copy()
    263                 self.set_selection(bsel)
    264                 return scantable(scopy)
     283                return self._select_copy(sel)
    265284            elif type(scanid) is list:
    266285                sel.set_scans(scanid)
    267                 self.set_selection(sel)
    268                 scopy = self._copy()
    269                 self.set_selection(bsel)
    270                 return scantable(scopy)
     286                return self._select_copy(sel)
    271287            else:
    272288                msg = "Illegal scanid type, use 'int' or 'list' if ints."
     
    294310            filename:    the name of a file to write the putput to
    295311                         Default - no file output
    296             verbose:     print extra info such as the frequency table
    297                          The default (False) is taken from .asaprc
    298312        """
    299313        info = Scantable._summary(self, True)
    300         #if verbose is None: verbose = rcParams['scantable.verbosesummary']
    301314        if filename is not None:
    302315            if filename is "":
     
    328341        """Return the spectrum for the current row in the scantable as a list.
    329342        Parameters:
    330              rowno:   the row number to retrieve the spectrum from       
     343             rowno:   the row number to retrieve the spectrum from
    331344        """
    332345        return self._getspectrum(rowno)
     
    335348        """Return the mask for the current row in the scantable as a list.
    336349        Parameters:
    337              rowno:   the row number to retrieve the mask from       
     350             rowno:   the row number to retrieve the mask from
    338351        """
    339352        return self._getmask(rowno)
     
    343356        Parameters:
    344357             spec:   the spectrum
    345              rowno:    the row number to set the spectrum for       
     358             rowno:    the row number to set the spectrum for
    346359        """
    347360        assert(len(spec) == self.nchan())
    348361        return self._setspectrum(spec, rowno)
     362
     363    def get_coordinate(self, rowno):
     364        """Return the (spectral) coordinate for a a given 'rowno'.
     365        NOTE:
     366            * This coordinate is only valid until a scantable method modifies
     367              the frequency axis.
     368            * This coordinate does contain the original frequency set-up
     369              NOT the new frame. The conversions however are done using the user
     370              specified frame (e.g. LSRK/TOPO). To get the 'real' coordinate,
     371              use scantable.freq_align first. Without it there is no closure,
     372              i.e.
     373              c = myscan.get_coordinate(0)
     374              c.to_frequency(c.get_reference_pixel()) != c.get_reference_value()
     375
     376        Parameters:
     377             rowno:    the row number for the spectral coordinate
     378
     379        """
     380        return coordinate(Scantable.get_coordinate(self, rowno))
    349381
    350382    def get_selection(self):
     
    360392        return selector(self._getselection())
    361393
    362     def set_selection(self, selection=selector()):
     394    def set_selection(self, selection=None, **kw):
    363395        """
    364396        Select a subset of the data. All following operations on this scantable
    365397        are only applied to thi selection.
    366398        Parameters:
    367             selection:    a selector object (default unset the selection)
     399            selection:    a selector object (default unset the selection),
     400
     401            or
     402
     403            any combination of
     404            "pols", "ifs", "beams", "scans", "cycles", "name", "query"
     405
    368406        Examples:
    369407            sel = selector()         # create a selection object
     
    372410            scan.summary()           # will only print summary of scanno 0 an 3
    373411            scan.set_selection()     # unset the selection
    374         """
     412            # or the equivalent
     413            scan.set_selection(scans=[0,3])
     414            scan.summary()           # will only print summary of scanno 0 an 3
     415            scan.set_selection()     # unset the selection
     416        """
     417        if selection is None:
     418            # reset
     419            if len(kw) == 0:
     420                selection = selector()
     421            else:
     422                # try keywords
     423                for k in kw:
     424                    if k not in selector.fields:
     425                        raise KeyError("Invalid selection key '%s', valid keys are %s" % (k, selector.fields))
     426                selection = selector(**kw)
    375427        self._setselection(selection)
    376428
     
    425477            scan.stats(stat='mean', mask=m)
    426478        """
    427         if mask == None:
    428             mask = []
    429         axes = ['Beam', 'IF', 'Pol', 'Time']
     479        mask = mask or []
    430480        if not self._check_ifs():
    431481            raise ValueError("Cannot apply mask as the IFs have different "
     
    441491        if not rtnabc: statvals = self._math._stats(self, mask, stat)
    442492
    443         out = ''
    444         axes = []
     493        #def cb(i):
     494        #    return statvals[i]
     495
     496        #return self._row_callback(cb, stat)
     497
     498        label=stat
     499        #callback=cb
     500        out = ""
     501        #outvec = []
     502        sep = '-'*50
    445503        for i in range(self.nrow()):
    446             axis = []
    447             axis.append(self.getscan(i))
    448             axis.append(self.getbeam(i))
    449             axis.append(self.getif(i))
    450             axis.append(self.getpol(i))
    451             axis.append(self.getcycle(i))
    452             axes.append(axis)
    453             tm = self._gettime(i)
    454             src = self._getsourcename(i)
    455504            refstr = ''
    456505            statunit= ''
     
    459508                if rtnabc:
    460509                    statvals.append(qx['value'])
    461                     #refstr = '(value: %3.3f' % (qy['value'])+' ['+qy['unit']+'])'
    462510                    refstr = ('(value: %'+form) % (qy['value'])+' ['+qy['unit']+'])'
    463511                    statunit= '['+qx['unit']+']'
    464512                else:
    465                     #refstr = '(@ %3.3f' % (qx['value'])+' ['+qx['unit']+'])'
    466513                    refstr = ('(@ %'+form) % (qx['value'])+' ['+qx['unit']+'])'
    467                     #statunit= ' ['+qy['unit']+']'
    468             out += 'Scan[%d] (%s) ' % (axis[0], src)
     514
     515            tm = self._gettime(i)
     516            src = self._getsourcename(i)
     517            out += 'Scan[%d] (%s) ' % (self.getscan(i), src)
    469518            out += 'Time[%s]:\n' % (tm)
    470             if self.nbeam(-1) > 1: out +=  ' Beam[%d] ' % (axis[1])
    471             if self.nif(-1) > 1: out +=  ' IF[%d] ' % (axis[2])
    472             if self.npol(-1) > 1: out +=  ' Pol[%d] ' % (axis[3])
    473             #out += '= %3.3f   ' % (statvals[i]) +refstr+'\n'
     519            if self.nbeam(-1) > 1:
     520                out +=  ' Beam[%d] ' % (self.getbeam(i))
     521            if self.nif(-1) > 1: out +=  ' IF[%d] ' % (self.getif(i))
     522            if self.npol(-1) > 1: out +=  ' Pol[%d] ' % (self.getpol(i))
     523            #outvec.append(callback(i))
     524            #out += ('= %'+form) % (outvec[i]) +'   '+refstr+'\n'
    474525            out += ('= %'+form) % (statvals[i]) +'   '+refstr+'\n'
    475             out +=  "--------------------------------------------------\n"
     526            out +=  sep+"\n"
    476527
    477528        if rcParams['verbose']:
     
    484535            tmpfile='/tmp/tmp_'+usr+'_casapy_asap_scantable_stats'
    485536            f=open(tmpfile,'w')
    486             print >> f, "--------------------------------------------------"
    487             print >> f, " ", stat, statunit
    488             print >> f, "--------------------------------------------------"
     537            print >> f, sep
     538            print >> f, ' %s %s' % (label, statunit)
     539            print >> f, sep
    489540            print >> f, out
    490541            f.close()
     
    492543            x=f.readlines()
    493544            f.close()
    494             for xx in x:
    495                 asaplog.push( xx, False )
     545            blanc=''
     546            asaplog.push(blanc.join(x), False)
     547            #for xx in x:
     548            #    asaplog.push( xx, False )
    496549            print_log()
    497         #else:
    498             #retval = { 'axesnames': ['scanno', 'beamno', 'ifno', 'polno', 'cycleno'],
    499             #           'axes' : axes,
    500             #           'data': statvals}
    501550        return statvals
    502551
     
    541590        return list(Scantable.get_column_names(self))
    542591
    543     def get_tsys(self):
     592    def get_tsys(self, row=-1):
    544593        """
    545594        Return the System temperatures.
     
    547596            a list of Tsys values for the current selection
    548597        """
    549 
     598        if row > -1:
     599            return self._get_column(self._gettsys, row)
    550600        return self._row_callback(self._gettsys, "Tsys")
    551601
     602
     603    def get_weather(self, row=-1):
     604        values = self._get_column(self._get_weather, row)
     605        if row > -1:
     606            return {'temperature': values[0],
     607                    'pressure': values[1], 'humidity' : values[2],
     608                    'windspeed' : values[3], 'windaz' : values[4]
     609                    }
     610        else:
     611            out = []
     612            for r in values:
     613
     614                out.append({'temperature': r[0],
     615                            'pressure': r[1], 'humidity' : r[2],
     616                            'windspeed' : r[3], 'windaz' : r[4]
     617                    })
     618            return out
     619
    552620    def _row_callback(self, callback, label):
    553         axes = []
    554         axesnames = ['scanno', 'beamno', 'ifno', 'polno', 'cycleno']
    555621        out = ""
    556622        outvec = []
     623        sep = '-'*50
    557624        for i in range(self.nrow()):
    558             axis = []
    559             axis.append(self.getscan(i))
    560             axis.append(self.getbeam(i))
    561             axis.append(self.getif(i))
    562             axis.append(self.getpol(i))
    563             axis.append(self.getcycle(i))
    564             axes.append(axis)
    565625            tm = self._gettime(i)
    566626            src = self._getsourcename(i)
    567             out += 'Scan[%d] (%s) ' % (axis[0], src)
     627            out += 'Scan[%d] (%s) ' % (self.getscan(i), src)
    568628            out += 'Time[%s]:\n' % (tm)
    569             if self.nbeam(-1) > 1: out +=  ' Beam[%d] ' % (axis[1])
    570             if self.nif(-1) > 1: out +=  ' IF[%d] ' % (axis[2])
    571             if self.npol(-1) > 1: out +=  ' Pol[%d] ' % (axis[3])
     629            if self.nbeam(-1) > 1:
     630                out +=  ' Beam[%d] ' % (self.getbeam(i))
     631            if self.nif(-1) > 1: out +=  ' IF[%d] ' % (self.getif(i))
     632            if self.npol(-1) > 1: out +=  ' Pol[%d] ' % (self.getpol(i))
    572633            outvec.append(callback(i))
    573634            out += '= %3.3f\n' % (outvec[i])
    574             out +=  "--------------------------------------------------\n"
     635            out +=  sep+'\n'
    575636        if rcParams['verbose']:
    576             asaplog.push("--------------------------------------------------")
     637            asaplog.push(sep)
    577638            asaplog.push(" %s" % (label))
    578             asaplog.push("--------------------------------------------------")
     639            asaplog.push(sep)
    579640            asaplog.push(out)
    580641            print_log()
    581         # disabled because the vector seems more useful
    582         #retval = {'axesnames': axesnames, 'axes': axes, 'data': outvec}
    583642        return outvec
    584643
     
    624683            none
    625684        """
    626         return self._get_column(self._getinttime, row)       
    627        
     685        return self._get_column(self._getinttime, row)
     686
    628687
    629688    def get_sourcename(self, row=-1):
     
    674733        """
    675734        Get a list of Positions on the sky (direction) for the observations.
    676         Return a float for each integration in the scantable.
     735        Return a string for each integration in the scantable.
    677736        Parameters:
    678737            row:    row no of integration. Default -1 return all rows
     
    693752        return self._get_column(self._getdirectionvec, row)
    694753
     754    #@print_log_dec
    695755    def set_unit(self, unit='channel'):
    696756        """
     
    708768        self._add_history("set_unit", varlist)
    709769
     770    #@print_log_dec
    710771    def set_instrument(self, instr):
    711772        """
     
    719780        print_log()
    720781
     782    #@print_log_dec
    721783    def set_feedtype(self, feedtype):
    722784        """
     
    729791        print_log()
    730792
     793    #@print_log_dec
    731794    def set_doppler(self, doppler='RADIO'):
    732795        """
     
    742805        print_log()
    743806
     807    #@print_log_dec
    744808    def set_freqframe(self, frame=None):
    745809        """
     
    747811        Parameters:
    748812            frame:   an optional frame type, default 'LSRK'. Valid frames are:
    749                      'REST', 'TOPO', 'LSRD', 'LSRK', 'BARY',
     813                     'TOPO', 'LSRD', 'LSRK', 'BARY',
    750814                     'GEO', 'GALACTO', 'LGROUP', 'CMB'
    751815        Examples:
    752816            scan.set_freqframe('BARY')
    753817        """
    754         if frame is None: frame = rcParams['scantable.freqframe']
    755         varlist = vars()
    756         valid = ['REST', 'TOPO', 'LSRD', 'LSRK', 'BARY', \
     818        frame = frame or rcParams['scantable.freqframe']
     819        varlist = vars()
     820        # "REST" is not implemented in casacore
     821        #valid = ['REST', 'TOPO', 'LSRD', 'LSRK', 'BARY', \
     822        #           'GEO', 'GALACTO', 'LGROUP', 'CMB']
     823        valid = ['TOPO', 'LSRD', 'LSRK', 'BARY', \
    757824                   'GEO', 'GALACTO', 'LGROUP', 'CMB']
    758825
     
    829896        """
    830897        varlist = vars()
    831         if mask is None:
    832             mask = []
     898        mask = mask or []
    833899        try:
    834900            self._flag(mask, unflag)
     
    883949            else: raise
    884950        self._add_history("clip", varlist)
    885        
    886     def lag_flag(self, frequency, width=0.0, unit="GHz", insitu=None):
     951
     952    #@print_log_dec
     953    def lag_flag(self, start, end, unit="MHz", insitu=None):
     954    #def lag_flag(self, frequency, width=0.0, unit="GHz", insitu=None):
    887955        """
    888956        Flag the data in 'lag' space by providing a frequency to remove.
    889         Flagged data in the scantable gets set to 0.0 before the fft.
     957        Flagged data in the scantable gets interpolated over the region.
    890958        No taper is applied.
    891959        Parameters:
    892             frequency:    the frequency (really a period within the bandwidth)
    893                           to remove
    894             width:        the width of the frequency to remove, to remove a
    895                           range of frequencies around the centre.
    896             unit:         the frequency unit (default "GHz")
     960            start:    the start frequency (really a period within the
     961                      bandwidth)  or period to remove
     962            end:      the end frequency or period to remove
     963            unit:     the frequency unit (default "MHz") or "" for
     964                      explicit lag channels
    897965        Notes:
    898             It is recommended to flag edges of the band or strong 
     966            It is recommended to flag edges of the band or strong
    899967            signals beforehand.
    900968        """
     
    902970        self._math._setinsitu(insitu)
    903971        varlist = vars()
    904         base = { "GHz": 1000000000., "MHz": 1000000., "kHz": 1000., "Hz": 1. }
    905         if not base.has_key(unit):
     972        base = { "GHz": 1000000000., "MHz": 1000000., "kHz": 1000., "Hz": 1.}
     973        if not (unit == "" or base.has_key(unit)):
    906974            raise ValueError("%s is not a valid unit." % unit)
    907975        try:
    908             s = scantable(self._math._lag_flag(self, frequency*base[unit],
    909                                                width*base[unit]))
     976            if unit == "":
     977                s = scantable(self._math._lag_flag(self, start, end, "lags"))
     978            else:
     979                s = scantable(self._math._lag_flag(self, start*base[unit],
     980                                                   end*base[unit], "frequency"))
    910981        except RuntimeError, msg:
    911982            if rcParams['verbose']:
     
    923994            return s
    924995
    925 
     996    #@print_log_dec
    926997    def create_mask(self, *args, **kwargs):
    927998        """
     
    9521023            c)
    9531024            mask only channel 400
    954             msk =  scan.create_mask([400, 400])
    955         """
    956         row = 0
    957         if kwargs.has_key("row"):
    958             row = kwargs.get("row")
     1025            msk =  scan.create_mask([400])
     1026        """
     1027        row = kwargs.get("row", 0)
    9591028        data = self._getabcissa(row)
    9601029        u = self._getcoordinfo()[0]
     
    9731042             and args or args[0]
    9741043        for window in ws:
    975             if (len(window) != 2 or window[0] > window[1] ):
    976                 raise TypeError("A window needs to be defined as [min, max]")
     1044            if len(window) == 1:
     1045                window = [window[0], window[0]]
     1046            if len(window) == 0 or  len(window) > 2:
     1047                raise ValueError("A window needs to be defined as [start(, end)]")
     1048            if window[0] > window[1]:
     1049                tmp = window[0]
     1050                window[0] = window[1]
     1051                window[1] = tmp
    9771052            for i in range(n):
    9781053                if data[i] >= window[0] and data[i] <= window[1]:
     
    11271202            source and IF basis, use scantable.set_selection() before using
    11281203            this function.
    1129             # provide your scantable is call scan
     1204            # provide your scantable is called scan
    11301205            selection = selector()
    11311206            selection.set_name("ORION*")
     
    11881263
    11891264    def shift_refpix(self, delta):
    1190         """
    1191         Shift the reference pixel of the Spectra Coordinate by an
    1192         integer amount.
    1193         Parameters:
    1194             delta:   the amount to shift by
     1265        """
     1266        Shift the reference pixel of the Spectra Coordinate by an
     1267        integer amount.
     1268        Parameters:
     1269            delta:   the amount to shift by
    11951270        Note:
    1196             Be careful using this with broadband data.
    1197         """
    1198         Scantable.shift(self, delta)
     1271            Be careful using this with broadband data.
     1272        """
     1273        Scantable.shift_refpix(self, delta)
    11991274
    12001275    def history(self, filename=None):
     
    12491324    # Maths business
    12501325    #
    1251 
     1326    #@print_log_dec
    12521327    def average_time(self, mask=None, scanav=False, weight='tint', align=False):
    12531328        """
     
    12751350        """
    12761351        varlist = vars()
    1277         if weight is None: weight = 'TINT'
    1278         if mask is None: mask = ()
    1279         if scanav: scanav = "SCAN"
    1280         else: scanav = "NONE"
     1352        weight = weight or 'TINT'
     1353        mask = mask or ()
     1354        scanav = (scanav and 'SCAN') or 'NONE'
    12811355        scan = (self, )
    12821356        try:
     
    13021376        return s
    13031377
     1378    #@print_log_dec
    13041379    def convert_flux(self, jyperk=None, eta=None, d=None, insitu=None):
    13051380        """
     
    13211396        self._math._setinsitu(insitu)
    13221397        varlist = vars()
    1323         if jyperk is None: jyperk = -1.0
    1324         if d is None: d = -1.0
    1325         if eta is None: eta = -1.0
     1398        jyperk = jyperk or -1.0
     1399        d = d or -1.0
     1400        eta = eta or -1.0
    13261401        s = scantable(self._math._convertflux(self, d, eta, jyperk))
    13271402        s._add_history("convert_flux", varlist)
     
    13301405        else: return s
    13311406
     1407    #@print_log_dec
    13321408    def gain_el(self, poly=None, filename="", method="linear", insitu=None):
    13331409        """
     
    13731449        self._math._setinsitu(insitu)
    13741450        varlist = vars()
    1375         if poly is None:
    1376             poly = ()
     1451        poly = poly or ()
    13771452        from os.path import expandvars
    13781453        filename = expandvars(filename)
     
    13801455        s._add_history("gain_el", varlist)
    13811456        print_log()
    1382         if insitu: self._assign(s)
    1383         else: return s
    1384 
     1457        if insitu:
     1458            self._assign(s)
     1459        else:
     1460            return s
     1461
     1462    #@print_log_dec
    13851463    def freq_align(self, reftime=None, method='cubic', insitu=None):
    13861464        """
     
    14011479        self._math._setinsitu(insitu)
    14021480        varlist = vars()
    1403         if reftime is None: reftime = ""
     1481        reftime = reftime or ""
    14041482        s = scantable(self._math._freq_align(self, reftime, method))
    14051483        s._add_history("freq_align", varlist)
     
    14081486        else: return s
    14091487
    1410     def opacity(self, tau, insitu=None):
     1488    #@print_log_dec
     1489    def opacity(self, tau=None, insitu=None):
    14111490        """
    14121491        Apply an opacity correction. The data
    14131492        and Tsys are multiplied by the correction factor.
    14141493        Parameters:
    1415             tau:         Opacity from which the correction factor is
     1494            tau:         (list of) opacity from which the correction factor is
    14161495                         exp(tau*ZD)
    1417                          where ZD is the zenith-distance
     1496                         where ZD is the zenith-distance.
     1497                         If a list is provided, it has to be of length nIF,
     1498                         nIF*nPol or 1 and in order of IF/POL, e.g.
     1499                         [opif0pol0, opif0pol1, opif1pol0 ...]
     1500                         if tau is `None` the opacities are determined from a
     1501                         model.
    14181502            insitu:      if False a new scantable is returned.
    14191503                         Otherwise, the scaling is done in-situ
     
    14231507        self._math._setinsitu(insitu)
    14241508        varlist = vars()
     1509        if not hasattr(tau, "__len__"):
     1510            tau = [tau]
    14251511        s = scantable(self._math._opacity(self, tau))
    14261512        s._add_history("opacity", varlist)
     
    14291515        else: return s
    14301516
     1517    #@print_log_dec
    14311518    def bin(self, width=5, insitu=None):
    14321519        """
     
    14441531        s._add_history("bin", varlist)
    14451532        print_log()
    1446         if insitu: self._assign(s)
    1447         else: return s
    1448 
    1449 
     1533        if insitu:
     1534            self._assign(s)
     1535        else:
     1536            return s
     1537
     1538    #@print_log_dec
    14501539    def resample(self, width=5, method='cubic', insitu=None):
    14511540        """
     
    14701559        else: return s
    14711560
    1472 
     1561    #@print_log_dec
    14731562    def average_pol(self, mask=None, weight='none'):
    14741563        """
     
    14821571        """
    14831572        varlist = vars()
    1484         if mask is None:
    1485             mask = ()
     1573        mask = mask or ()
    14861574        s = scantable(self._math._averagepol(self, mask, weight.upper()))
    14871575        s._add_history("average_pol", varlist)
     
    14891577        return s
    14901578
     1579    #@print_log_dec
    14911580    def average_beam(self, mask=None, weight='none'):
    14921581        """
     
    15001589        """
    15011590        varlist = vars()
    1502         if mask is None:
    1503             mask = ()
     1591        mask = mask or ()
    15041592        s = scantable(self._math._averagebeams(self, mask, weight.upper()))
    15051593        s._add_history("average_beam", varlist)
     
    15071595        return s
    15081596
     1597    def parallactify(self, pflag):
     1598        """
     1599        Set a flag to inidcate whether this data should be treated as having
     1600        been 'parallactified' (total phase == 0.0)
     1601        Parameters:
     1602            pflag:  Bool inidcating whether to turn this on (True) or
     1603                    off (False)
     1604        """
     1605        varlist = vars()
     1606        self._parallactify(pflag)
     1607        self._add_history("parallactify", varlist)
     1608
     1609    #@print_log_dec
    15091610    def convert_pol(self, poltype=None):
    15101611        """
    15111612        Convert the data to a different polarisation type.
     1613        Note that you will need cross-polarisation terms for most conversions.
    15121614        Parameters:
    15131615            poltype:    The new polarisation type. Valid types are:
    1514                         "linear", "stokes" and "circular"
     1616                        "linear", "circular", "stokes" and "linpol"
    15151617        """
    15161618        varlist = vars()
     
    15301632        return s
    15311633
    1532     #def smooth(self, kernel="hanning", width=5.0, insitu=None):
    1533     def smooth(self, kernel="hanning", width=5.0, plot=False, insitu=None):
     1634    #@print_log_dec
     1635    def smooth(self, kernel="hanning", width=5.0, order=2, plot=False, insitu=None):
    15341636        """
    15351637        Smooth the spectrum by the specified kernel (conserving flux).
    15361638        Parameters:
    15371639            kernel:     The type of smoothing kernel. Select from
    1538                         'hanning' (default), 'gaussian', 'boxcar' and
    1539                         'rmedian'
     1640                        'hanning' (default), 'gaussian', 'boxcar', 'rmedian'
     1641                        or 'poly'
    15401642            width:      The width of the kernel in pixels. For hanning this is
    15411643                        ignored otherwise it defauls to 5 pixels.
    15421644                        For 'gaussian' it is the Full Width Half
    15431645                        Maximum. For 'boxcar' it is the full width.
    1544                         For 'rmedian' it is the half width.
     1646                        For 'rmedian' and 'poly' it is the half width.
     1647            order:      Optional parameter for 'poly' kernel (default is 2), to
     1648                        specify the order of the polnomial. Ignored by all other
     1649                        kernels.
    15451650            plot:       plot the original and the smoothed spectra.
    15461651                        In this each indivual fit has to be approved, by
     
    15581663        if plot: orgscan = self.copy()
    15591664
    1560         s = scantable(self._math._smooth(self, kernel.lower(), width))
     1665        s = scantable(self._math._smooth(self, kernel.lower(), width, order))
    15611666        s._add_history("smooth", varlist)
    15621667
     
    16011706        else: return s
    16021707
    1603 
    1604     def poly_baseline(self, mask=None, order=0, plot=False, uselin=False, insitu=None):
     1708    #@print_log_dec
     1709    def poly_baseline(self, mask=None, order=0, plot=False, uselin=False,
     1710                      insitu=None):
    16051711        """
    16061712        Return a scan which has been baselined (all rows) by a polynomial.
     
    18331939            return workscan
    18341940
     1941    #@print_log_dec
    18351942    def rotate_linpolphase(self, angle):
    18361943        """
     
    18491956        return
    18501957
    1851 
     1958    #@print_log_dec
    18521959    def rotate_xyphase(self, angle):
    18531960        """
     
    18661973        return
    18671974
     1975    #@print_log_dec
    18681976    def swap_linears(self):
    18691977        """
    1870         Swap the linear polarisations XX and YY, or better the first two 
     1978        Swap the linear polarisations XX and YY, or better the first two
    18711979        polarisations as this also works for ciculars.
    18721980        """
     
    18771985        return
    18781986
     1987    #@print_log_dec
    18791988    def invert_phase(self):
    18801989        """
     
    18871996        return
    18881997
     1998    #@print_log_dec
    18891999    def add(self, offset, insitu=None):
    18902000        """
     
    19072017            return s
    19082018
     2019    #@print_log_dec
    19092020    def scale(self, factor, tsys=True, insitu=None):
    19102021        """
     
    19722083        self._setsourcetype(stype)
    19732084        self.set_selection(basesel)
    1974         s._add_history("set_sourcetype", varlist)
    1975 
     2085        self._add_history("set_sourcetype", varlist)
     2086
     2087    #@print_log_dec
    19762088    def auto_quotient(self, preserve=True, mode='paired', verify=False):
    19772089        """
     
    19842096                            preserve: Output = Toff * (on/off) - Toff
    19852097                            remove:   Output = Toff * (on/off) - Ton
    1986             mode:           the on/off detection mode 
     2098            mode:           the on/off detection mode
    19872099                            'paired' (default)
    19882100                            identifies 'off' scans by the
     
    20172129        return s
    20182130
     2131    #@print_log_dec
    20192132    def mx_quotient(self, mask = None, weight='median', preserve=True):
    20202133        """
     
    20282141                            remove:   Output = Toff * (on/off) - Ton
    20292142        """
    2030         if mask is None: mask = ()
     2143        mask = mask or ()
    20312144        varlist = vars()
    20322145        on = scantable(self._math._mx_extract(self, 'on'))
     
    20392152        return q
    20402153
     2154    #@print_log_dec
    20412155    def freq_switch(self, insitu=None):
    20422156        """
     
    20582172        else: return s
    20592173
     2174    #@print_log_dec
    20602175    def recalc_azel(self):
    20612176        """
     
    20712186        return
    20722187
     2188    #@print_log_dec
    20732189    def __add__(self, other):
    20742190        """
     
    20772193        return self._operation( other, "ADD" )
    20782194
     2195    #@print_log_dec
    20792196    def __sub__(self, other):
    20802197        """
     
    20832200        return self._operation( other, 'SUB' )
    20842201
     2202    #@print_log_dec
    20852203    def __mul__(self, other):
    20862204        """
     
    20892207        return self._operation( other, 'MUL' )
    20902208
     2209    #@print_log_dec
    20912210    def __div__(self, other):
    20922211        """
     
    21202239        basesel = self.get_selection()
    21212240        for i in range(self.nrow()):
    2122             sel = selector()+basesel
    2123             sel.set_scans(self.getscan(i))
    2124             sel.set_beams(self.getbeam(i))
    2125             sel.set_ifs(self.getif(i))
    2126             sel.set_polarisations(self.getpol(i))
    2127             self.set_selection(sel)
     2241            sel = self.get_row_selector(i)
     2242            self.set_selection(basesel+sel)
    21282243            nans = numpy.isnan(self._getspectrum(0))
    21292244        if numpy.any(nans):
     
    21312246            self.flag(bnans)
    21322247        self.set_selection(basesel)
    2133        
     2248
     2249    def get_row_selector(self, rowno):
     2250        return selector(beams=self.getbeam(rowno),
     2251                        ifs=self.getif(rowno),
     2252                        pols=self.getpol(rowno),
     2253                        scans=self.getscan(rowno),
     2254                        cycles=self.getcycle(rowno))
    21342255
    21352256    def _add_history(self, funcname, parameters):
  • branches/alma/python/selector.py

    r1693 r1757  
    77    scantables to specific rows.
    88    """
    9     def __init(self):
    10         _selector.__init__(self)
     9    fields = ["pols", "ifs", "beams", "scans", "cycles", "name", "query"]
     10
     11    def __init__(self, *args, **kw):
     12        if len(args) == 1:
     13            if isinstance(args[0], self.__class__) \
     14               or isinstance(args[0], _selector):
     15                _selector.__init__(self, args[0])
     16            else:
     17                raise TypeError("Argument can only be a selector object")
     18        else:
     19            _selector.__init__(self)
     20            for k,v  in kw.items():
     21                if k in self.fields:
     22                    func = getattr(self, "set_%s" % k)
     23                    func(v)
    1124
    1225    def reset(self):
     
    4558        else:
    4659            raise TypeError('Unknown pol type. Please use [0,1...] or ["XX","YY"...]')
    47    
     60
    4861    # for the americans
    4962    set_polarizations = set_polarisations
     
    220233        Merge two selections.
    221234        """
     235        if self.is_empty():
     236            return other
     237        elif other.is_empty():
     238            return self
    222239        union = selector()
    223240        gets = [[self._getscans(), other._getscans(), union._setscans],
  • branches/alma/scons/quietinstall.py

    r1184 r1757  
    11import SCons
     2
     3try:
     4    from SCons.Environment import installFunc
     5except ImportError:
     6    from SCons.Tool.install import installFunc
    27
    38def no_output(target, source, env):
     
    2732   
    2833    quietinstaller_builder = env.Builder(
    29         action = env.Action(SCons.Environment.installFunc, no_output),
     34        action = env.Action(installFunc, no_output),
    3035        multi=1
    3136    )
  • branches/alma/scons/utils.py

    r1332 r1757  
     1import sys
    12import os
    23import glob
     4import re
     5import platform
    36
    47def generate(env):
    5     def SGlob(pattern):
    6         path = env.GetBuildPath('SConscript').replace('SConscript', '')
    7         return [ i.replace(path, '') for i in glob.glob(path + pattern) ]
     8
     9    def SGlob(pattern, excludedirs=[], recursive=False):
     10        # always exclude .svn
     11        excludedirs.append(".svn")
     12        path = env.GetBuildPath('SConscript').replace('SConscript', '')
     13        if recursive:
     14            # remove '*' from pattern is accidentally specified
     15            pattern=pattern.replace("*", "")
     16            out = []
     17            for d, ld, fls in os.walk(path):
     18                # remove directorys to be excluded
     19                for exd in excludedirs:
     20                    if exd in ld:
     21                        ld.remove(exd)
     22                for f in fls:               
     23                    if f.endswith(pattern):
     24                        drel=d.replace(path,"")
     25                        out.append(os.path.join(drel,f))
     26            return out
     27        else:
     28            return [ i.replace(path, '') for i in  glob.glob(path + pattern) ]
    829    env.SGlob = SGlob
    930
    10     def AddCustomPath(path=""):
    11         if not len(path) or not os.path.exists(path):
    12             return
     31    def AddCustomPath(path=None):
     32        if path is None or not os.path.exists(path):
     33            env.Exit(1)
    1334        env.PrependUnique(CPPPATH = [os.path.join(path, "include")])
    1435        env.PrependUnique(LIBPATH = [os.path.join(path, "lib")])
     
    1738    def AddCustomPackage(pkgname=None):
    1839        if pkgname is None:
    19             return
    20         pkgroot = env.get("%sroot" % pkgname, None)
    21         pkgincd = env.get("%sincdir" % pkgname, None)
    22         pkglibd = env.get("%slibdir" % pkgname, None)
    23         incd = None
    24         libd = None
    25         if pkgroot is not None:
    26             incd = os.path.join(pkgroot, "include")
    27             libd = os.path.join(pkgroot, "lib")
    28         else:      
    29             if pkgincd is not None:
    30                 incd = pkgincd
    31             if pkglibd is not None:
    32                 libd = pkglibd
    33         if incd is not None:
    34             if not os.path.exists(incd):
    35                 print "Custom %s include dir '%s' not found" % (pkgname, incd)
    36                 env.Exit(1)
    37             env.PrependUnique(CPPPATH = [incd])
    38         if libd is not None:
    39             if not os.path.exists(libd):
    40                 print "Custom %s lib dir '%s' not found" % (pkgname, libd)
    41                 env.Exit(1)
    42             env.PrependUnique(LIBPATH = [libd])
     40            return
     41        pkgroot = env.get("%sroot" % pkgname, None)
     42        pkgincd = env.get("%sincdir" % pkgname, None)
     43        pkglibd = env.get("%slibdir" % pkgname, None)
     44        incd = None
     45        libd = None
     46        if pkgroot is not None:
     47            incd = os.path.join(pkgroot, "include")
     48            libd = os.path.join(pkgroot, "lib")
     49        else:      
     50            if pkgincd is not None:
     51                incd = pkgincd
     52            if pkglibd is not None:
     53                libd = pkglibd
     54        if incd is not None:
     55            if not os.path.exists(incd):
     56                print "Custom %s include dir '%s' not found" % (pkgname, incd)
     57                env.Exit(1)
     58            env.PrependUnique(CPPPATH = [incd])
     59        if libd is not None:
     60            if not os.path.exists(libd):
     61                print "Custom %s lib dir '%s' not found" % (pkgname, libd)
     62                env.Exit(1)
     63            env.PrependUnique(LIBPATH = [libd])
    4364
    4465    env.AddCustomPackage = AddCustomPackage
    4566
     67    def PlatformIdent():
     68        p = sys.platform
     69        # replace the trailing 2 in linux2
     70        p = re.sub(re.compile("2$"), "", p)
     71        return p + "_" + platform.machine()
     72    env.PlatformIdent = PlatformIdent
     73
     74    def MergeFlags():
     75        def _to_list(xf):
     76            if xf.count(","):
     77                return xf.split(",")
     78            return xf.split()
     79
     80        xf=env.get("extracppflags", None)
     81        if xf:
     82            env.AppendUnique(CPPFLAGS=_to_list(xf))
     83        xf=env.get("extralinkflags", None)
     84        if xf:
     85            env.AppendUnique(LINKFLAGS=_to_list(xf))
     86            env.AppendUnique(SHLINKFLAGS=_to_list(xf))
     87        xf=env.get("extracxxflags", None)
     88        if xf:
     89            env.AppendUnique(CXXFLAGS=_to_list(xf))
     90        xf=env.get("extrafflags", None)
     91        if xf:
     92            env.AppendUnique(FORTRANFLAGS=_to_list(xf))
     93            env.AppendUnique(SHFORTRANFLAGS=_to_list(xf))
     94        xf=env.get("extracflags", None)
     95        if xf:
     96            env.AppendUnique(CCFLAGS=_to_list(xf))
     97    # set the extra flags if available
     98    MergeFlags()
     99       
    46100    def CheckFortran(conf):
    47            
    48         if not conf.env.has_key("FORTRAN"):
    49             # auto-detect fortran
    50             detect_fortran = conf.env.Detect(['gfortran', 'g77', 'f77'])
    51             if not detect_fortran:
    52                 print "No fortran compiler found. Specify FORTRAN and f2clib."
    53                 conf.env.Exit(1)
    54             conf.env["FORTRAN"] = detect_fortran
     101       
     102        def getf2clib(fc):
    55103            fdict = {'gfortran': 'gfortran', 'g77': 'g2c', 'f77': 'f2c'}
    56             f2clib = conf.env.get("f2clib", fdict[detect_fortran])
    57             if not conf.CheckLib(f2clib):
    58                 env.Exit(1)
    59         else:
    60             if not conf.env.has_key("f2clib"):
    61                 print "A custom fortran compiler also needs f2clib defined"
    62                 env.Exit(1)
    63             else:
    64                 if not conf.CheckLib(env["f2clib"]):
    65                     env.Exit(1)
    66         if conf.env["FORTRAN"].startswith("g77"):
     104            return fdict[fc]
     105
     106       
     107        if not conf.env.has_key("FORTRAN"):
     108            # auto-detect fortran
     109            detect_fortran = conf.env.Detect(['gfortran', 'g77', 'f77'])
     110            conf.env["FORTRAN"] = detect_fortran
     111        f2clib = conf.env.get("f2clib", getf2clib(conf.env["FORTRAN"]))
     112        if not conf.CheckLib(f2clib):
     113            conf.env.Exit(1)
     114
     115        if conf.env["FORTRAN"].startswith("g77"):
    67116            fflags = ["-Wno-globals", "-fno-second-underscore"]
    68             conf.env.Append(SHFORTRANFLAGS=fflags)
    69             conf.env.Append(FORTRANFLAGS=fflags)
     117            conf.env.AppendUnique(SHFORTRANFLAGS=fflags)
     118            conf.env.AppendUnique(FORTRANFLAGS=fflags)
     119        conf.env.AppendUnique(SHFORTRANFLAGS=['-fPIC'])
     120
    70121    env.CheckFortran = CheckFortran
    71122
     
    84135    env.WalkDirTree = WalkDirTree
    85136
     137
    86138    def null_action(target, source, env): return 0
    87139
  • branches/alma/src/Makefile

    r1704 r1757  
    123123             STAsciiWriter.o \
    124124             STFITSImageWriter.o \
     125             STAtmosphere.o \
    125126             Scantable.o \
    126127             Templates.o
     
    136137             python_LineCatalog.o \
    137138             python_SrcType.o \
     139             python_STAtmosphere.o \
     140             python_STCoordinate.o \
    138141             python_asap.o
    139142
     
    172175             STWriter.h \
    173176             STAsciiWriter.h \
    174              STFITSImageWriter.h
     177             STFITSImageWriter.h \
     178             IndexedCompare.h \
     179             STAtmosphere.h \
     180             STCoordinate.h
    175181
    176182STATICCCLIB := libasap.a
  • branches/alma/src/MathUtils.cpp

    r1603 r1757  
    3939#include <scimath/Mathematics/MedianSlider.h>
    4040#include <casa/Exceptions/Error.h>
     41
     42#include <scimath/Fitting/LinearFit.h>
     43#include <scimath/Functionals/Polynomial.h>
     44#include <scimath/Mathematics/AutoDiff.h>
     45
    4146
    4247#include "MathUtils.h"
     
    183188  MedianSlider ms(hwidth);
    184189  Slice sl(0, fwidth-1);
    185   Float medval = ms.add(const_cast<Vector<Float>& >(in)(sl), 
     190  Float medval = ms.add(const_cast<Vector<Float>& >(in)(sl),
    186191                  const_cast<Vector<Bool>& >(flag)(sl));
    187192  uInt n = in.nelements();
    188193  for (uInt i=hwidth; i<(n-hwidth); ++i) {
    189194    // add data value
    190     out[i] = ms.add(in[i+hwidth], flag[i+hwidth]); 
    191     outflag[i] = (ms.nval() == 0);   
    192   }
    193   // replicate edge values from fisrt value with full width of values
     195    out[i] = ms.add(in[i+hwidth], flag[i+hwidth]);
     196    outflag[i] = (ms.nval() == 0);
     197  }
     198  // replicate edge values from first value with full width of values
    194199  for (uInt i=0;i<hwidth;++i) {
    195200    out[i] = out[hwidth];
    196     outflag[i] = outflag[hwidth];   
     201    outflag[i] = outflag[hwidth];
    197202    out[n-1-i] = out[n-1-hwidth];
    198     outflag[n-1-i] = outflag[n-1-hwidth];   
    199   }
    200 }
     203    outflag[n-1-i] = outflag[n-1-hwidth];
     204  }
     205}
     206
     207void mathutil::polyfit(Vector<Float>& out, Vector<Bool>& outmask,
     208                       const Vector<Float>& in, const Vector<Bool>& mask,
     209                       float width, int order)
     210{
     211  Int hwidth = Int(width+0.5);
     212  Int fwidth = hwidth*2+1;
     213  out.resize(in.nelements());
     214  outmask.resize(mask.nelements());
     215  LinearFit<Float> fitter;
     216  Polynomial<Float> poly(order);
     217  fitter.setFunction(poly);
     218  Vector<Float> sigma(fwidth);
     219  sigma = 1.0;
     220  Vector<Float> parms;
     221  Vector<Float> x(fwidth);
     222  indgen(x);
     223
     224  uInt n = in.nelements();
     225
     226  for (uInt i=hwidth; i<(n-hwidth); ++i) {
     227    // add data value
     228    if (mask[i]) {
     229      Slice sl(i-hwidth, fwidth);
     230      const Vector<Float> &y = const_cast<Vector<Float>& >(in)(sl);
     231      const Vector<Bool> &m = const_cast<Vector<Bool>& >(mask)(sl);
     232      parms = fitter.fit(x, y, sigma, &m);
     233
     234      poly.setCoefficients(parms);
     235      out[i] = poly(x[hwidth]);//cout << in[i] <<"->"<<out[i]<<endl;
     236    } else {
     237      out[i] = in[i];
     238    }
     239    outmask[i] = mask[i];
     240  }
     241  // replicate edge values from first value with full width of values
     242  for (uInt i=0;i<hwidth;++i) {
     243    out[i] = out[hwidth];
     244    outmask[i] = outmask[hwidth];
     245    out[n-1-i] = out[n-1-hwidth];
     246    outmask[n-1-i] = outmask[n-1-hwidth];
     247  }
     248}
  • branches/alma/src/MathUtils.h

    r1603 r1757  
    5151 * @param ignoreOther drop every second channel (NYI)
    5252 */
    53 void hanning(casa::Vector<casa::Float>& out, 
     53void hanning(casa::Vector<casa::Float>& out,
    5454             casa::Vector<casa::Bool>& outmask,
    55              const casa::Vector<casa::Float>& in, 
     55             const casa::Vector<casa::Float>& in,
    5656             const casa::Vector<casa::Bool>& mask,
    5757             casa::Bool relaxed=casa::False,
     
    6060/**
    6161 * Apply a running median to  a masked vector.
    62  * Edge solution:  The first and last hwidth channels will be replicated 
     62 * Edge solution:  The first and last hwidth channels will be replicated
    6363 * from the first/last value from a full window.
    6464 * @param out the smoothed vector
     
    6868 * @param hwidth half-width of the smoothing window
    6969 */
    70  void runningMedian(casa::Vector<casa::Float>& out,
     70 void runningMedian(casa::Vector<casa::Float>& out,
     71                   casa::Vector<casa::Bool>& outflag,
     72                   const casa::Vector<casa::Float>& in,
     73                   const casa::Vector<casa::Bool>& flag,
     74                   float hwidth);
     75
     76 void polyfit(casa::Vector<casa::Float>& out,
    7177                   casa::Vector<casa::Bool>& outmask,
    72                    const casa::Vector<casa::Float>& in, 
     78                   const casa::Vector<casa::Float>& in,
    7379                   const casa::Vector<casa::Bool>& mask,
    74                    float hwidth);
     80                   float hwidth, int order);
    7581
    7682// Generate specified statistic
  • branches/alma/src/RowAccumulator.cpp

    r1603 r1757  
    6767  Float totalweight = weight;
    6868  MaskedArray<Float> data(v,m);
    69   if ( weightType_ == asap::VAR ) {
     69  if ( weightType_ == asap::W_VAR ) {
    7070    if (m.nelements() == userMask_.nelements()) {
    7171      Float fac = 1.0/variance(data(userMask_));
     
    9090  Float w = 1.0;
    9191  tsysSum_ += v[0];
    92   if ( weightType_ == asap::TSYS  || weightType_ == asap::TINTSYS ) {
     92  if ( weightType_ == asap::W_TSYS  || weightType_ == asap::W_TINTSYS ) {
    9393    w /= (v[0]*v[0]);
    9494  }
     
    105105  Float w = 1.0;
    106106  intervalSum_ += inter;
    107   if ( weightType_ == asap::TINT || weightType_ == asap::TINTSYS ) {
     107  if ( weightType_ == asap::W_TINT || weightType_ == asap::W_TINTSYS ) {
    108108    w /= Float(inter);
    109109  }
  • branches/alma/src/RowAccumulator.h

    r1603 r1757  
    3333   * Constructor taking a weight type as defined in @ref STDefs
    3434   */
    35   explicit RowAccumulator(WeightType wt = asap::NONE);
     35  explicit RowAccumulator(WeightType wt = asap::W_NONE);
    3636
    3737 ~RowAccumulator();
  • branches/alma/src/STAsciiWriter.cpp

    r1657 r1757  
    8989
    9090   String rootName(fileName);
    91    if (rootName.length()==0) rootName = String("ascii");
    9291
    9392  Block<String> cols(4);
     
    104103    String dirtype = stable.getDirectionRefString();
    105104    ostringstream onstr;
    106     onstr << "SCAN" << rec.asuInt("SCANNO")
    107     << "_CYCLE" << rec.asuInt("CYCLENO")
    108     << "_BEAM" << rec.asuInt("BEAMNO")
    109     << "_IF" << rec.asuInt("IFNO");
     105
     106    if (rootName.length()==0) {
     107      rootName = String("ascii");
     108    }
     109    if (tab.nrow() > 1) {
     110      if (stable.nscan() > 1)
     111        onstr << "_SCAN" << rec.asuInt("SCANNO");
     112      if (stable.ncycle(rec.asuInt("SCANNO")) > 1)
     113        onstr << "_CYCLE" << rec.asuInt("CYCLENO");
     114      if (stable.nbeam(rec.asuInt("SCANNO")) > 1)
     115        onstr << "_BEAM" << rec.asuInt("BEAMNO");
     116      if (stable.nif(rec.asuInt("SCANNO")) > 1)
     117        onstr << "_IF" << rec.asuInt("IFNO");
     118    }
     119
    110120    String fName = rootName + String(onstr) + String(".txt");
    111121    ofstream of(fName.chars(), ios::trunc);
  • branches/alma/src/STAttr.cpp

    r1387 r1757  
    331331   TidGainElPoly_(2) = -3.219093e-4;
    332332   
     333   // 2009-09-15 - 13mm (22.2GHz) receiver
    333334   ParkesGainElPoly_.resize(3);
    334    ParkesGainElPoly_(0) = 0.296759e-1;
    335    ParkesGainElPoly_(1) = -0.293124e-3;
    336    ParkesGainElPoly_(2) = 0.264295e-6;
     335   ParkesGainElPoly_(0) = -0.194031;
     336   ParkesGainElPoly_(1) = 0.457724e-1;
     337   ParkesGainElPoly_(2) = -0.438659e-3;
    337338}
    338339
  • branches/alma/src/STDefs.h

    r1388 r1757  
    3434
    3535namespace asap {
    36   enum AxisNo { BeamAxis=0,
    37                 IFAxis,
    38                 PolAxis,
    39                 ChanAxis,
    40                 nAxes};
    4136
    4237  enum Instrument {UNKNOWNINST=0,
     
    5348  enum FeedPolType {UNKNOWNFEED, LINEAR, CIRCULAR, N_POL};
    5449
    55   enum WeightType {NONE=0, VAR, TSYS, TINT, TINTSYS, N_WEIGHTTYPES};
    56 
    57   enum TableType {MEMORY=0, PERSISTENT};
    58 
     50  enum WeightType {W_NONE=0, W_VAR, W_TSYS, W_TINT, W_TINTSYS, W_N_WEIGHTTYPES};
    5951
    6052
  • branches/alma/src/STFITSImageWriter.cpp

    r1604 r1757  
    121121  TableIterator iter(tab, cols);
    122122  // Open data file
     123
    123124  while ( !iter.pastEnd() ) {
    124125    Table t = iter.table();
     
    127128    String dirtype = stable.getDirectionRefString();
    128129    ostringstream onstr;
    129     onstr << "SCAN" << rec.asuInt("SCANNO")
    130     << "_CYCLE" << rec.asuInt("CYCLENO")
    131     << "_BEAM" << rec.asuInt("BEAMNO")
    132     << "_IF" << rec.asuInt("IFNO")
    133     << "_POL" << rec.asuInt("POLNO");
     130    if (rootName.length()==0) {
     131      rootName = "fits";
     132    }
     133    if (tab.nrow() > 1) {
     134      if (stable.nscan() > 1)
     135        onstr << "_SCAN" << rec.asuInt("SCANNO");
     136      if (stable.ncycle(rec.asuInt("SCANNO")) > 1)
     137        onstr << "_CYCLE" << rec.asuInt("CYCLENO");
     138      if (stable.nbeam(rec.asuInt("SCANNO")) > 1)
     139        onstr << "_BEAM" << rec.asuInt("BEAMNO");
     140      if (stable.nif(rec.asuInt("SCANNO")) > 1)
     141        onstr << "_IF" << rec.asuInt("IFNO");
     142      if (stable.npol(rec.asuInt("SCANNO")) > 1)
     143        onstr << "_POL" << rec.asuInt("POLNO");
     144    }
    134145    String fileName = rootName + String(onstr) + String(".fits");
    135146    int row0 = t.rowNumbers(tab)[0];
     
    260271    }
    261272    fits_close_file(fptr, &status);
    262  
     273    ostringstream oss;
     274    oss << "Wrote " << fileName;
     275    pushLog(String(oss)); 
    263276    //pushLog(String(oss));
    264277    ++iter;
  • branches/alma/src/STFiller.cpp

    r1684 r1757  
    264264    freqFrame = "REST";
    265265  }
    266   table_->frequencies().setFrame(freqFrame);
    267      
     266  // set both "FRAME" and "BASEFRAME"
     267  table_->frequencies().setFrame(freqFrame, false);
     268  table_->frequencies().setFrame(freqFrame,true);
     269  //table_->focus().setParallactify(true);
    268270}
    269271
     
    329331    if ( status != 0 ) break;
    330332    n += 1;
    331 
    332333    Regex filterrx(".*[SL|PA]$");
    333334    Regex obsrx("^AT.+");
     
    391392    /// @todo this has to change when nchan isn't global anymore
    392393    //id = table_->frequencies().addEntry(Double(header_->nchan/2),
    393     //                                        pksrec.refFreq, pksrec.freqInc);
     394    //                                    pksrec.refFreq, pksrec.freqInc);
    394395    if ( pksrec.nchan == 1 ) {
    395396      id = table_->frequencies().addEntry(Double(0),
     
    416417    RecordFieldPtr<uInt> mweatheridCol(rec, "WEATHER_ID");
    417418    *mweatheridCol = id;
     419
    418420    RecordFieldPtr<uInt> mfocusidCol(rec, "FOCUS_ID");
    419     id = table_->focus().addEntry(pksrec.focusAxi, pksrec.focusTan,
    420                                   pksrec.focusRot);
     421    id = table_->focus().addEntry(pksrec.parAngle, pksrec.focusAxi,
     422                                  pksrec.focusTan, pksrec.focusRot);
    421423    *mfocusidCol = id;
    422424    RecordFieldPtr<Array<Double> > dirCol(rec, "DIRECTION");
     
    426428    RecordFieldPtr<Float> elCol(rec, "ELEVATION");
    427429    *elCol = pksrec.elevation;
    428 
    429     RecordFieldPtr<Float> parCol(rec, "PARANGLE");
    430     *parCol = pksrec.parAngle;
    431430
    432431    RecordFieldPtr< Array<Float> > specCol(rec, "SPECTRA");
     
    542541  }
    543542
    544   // set frame keyword of FREQUENCIES table
     543  // set FRAME and BASEFRAME keyword of FREQUENCIES table
    545544  if ( header_->freqref != "TOPO" ) {
    546545    table_->frequencies().setFrame( header_->freqref, false ) ;
     546    table_->frequencies().setFrame( header_->freqref, true ) ;
    547547  }
    548548
  • branches/alma/src/STFocus.cpp

    r957 r1757  
    3434}
    3535
    36 asap::STFocus::STFocus( casa::Table tab ) : STSubTable(tab, name_)
     36STFocus::STFocus( casa::Table tab ) :
     37  STSubTable(tab, name_)
    3738{
     39  parangleCol_.attach(table_,"PARANGLE");
    3840  rotationCol_.attach(table_,"ROTATION");
    3941  axisCol_.attach(table_,"AXIS");
     
    5052}
    5153
    52 STFocus& asap::STFocus::operator =( const STFocus & other )
     54STFocus& STFocus::operator =( const STFocus & other )
    5355{
    5456  if (this != &other) {
    5557    static_cast<STSubTable&>(*this) = other;
     58    parangleCol_.attach(table_,"PARANGLE");
    5659    rotationCol_.attach(table_,"ROTATION");
    5760    axisCol_.attach(table_,"AXIS");
     
    6568  return *this;
    6669}
    67 void asap::STFocus::setup( )
     70void STFocus::setup( )
    6871{
    6972  // add to base class table
     73  table_.addColumn(ScalarColumnDesc<Float>("PARANGLE"));
    7074  table_.addColumn(ScalarColumnDesc<Float>("ROTATION"));
    7175  table_.addColumn(ScalarColumnDesc<Float>("AXIS"));
     
    7680  table_.addColumn(ScalarColumnDesc<Float>("XYPHASE"));
    7781  table_.addColumn(ScalarColumnDesc<Float>("XYPHASEOFFSET"));
     82  table_.rwKeywordSet().define("PARALLACTIFY", False);
    7883
    7984  // new cached columns
     85  parangleCol_.attach(table_,"PARANGLE");
    8086  rotationCol_.attach(table_,"ROTATION");
    8187  axisCol_.attach(table_,"AXIS");
     
    8894}
    8995
    90 uInt STFocus::addEntry( Float fax, Float ftan, Float frot, Float hand,
    91                         Float user, Float mount,
    92                         Float xyphase, Float xyphaseoffset)
     96  uInt STFocus::addEntry( Float pa, Float fax, Float ftan, Float frot, Float hand,
     97                          Float user, Float mount,
     98                          Float xyphase, Float xyphaseoffset)
    9399{
    94   Table result = table_( near(table_.col("ROTATION"), frot)
    95                     && near(table_.col("AXIS"), fax)
    96                     && near(table_.col("TAN"), ftan)
    97                     && near(table_.col("HAND"), hand)
    98                     && near(table_.col("USERPHASE"), user)
    99                     && near(table_.col("MOUNT"), mount)
    100                     && near(table_.col("XYPHASE"), xyphase)
    101                     && near(table_.col("XYPHASEOFFSET"), xyphaseoffset)
    102                     );
     100  Table result = table_(  near(table_.col("PARANGLE"), pa)
     101                          && near(table_.col("ROTATION"), frot)
     102                          && near(table_.col("AXIS"), fax)
     103                          && near(table_.col("TAN"), ftan)
     104                          && near(table_.col("HAND"), hand)
     105                          && near(table_.col("USERPHASE"), user)
     106                          && near(table_.col("MOUNT"), mount)
     107                          && near(table_.col("XYPHASE"), xyphase)
     108                          && near(table_.col("XYPHASEOFFSET"), xyphaseoffset)
     109                          );
    103110  uInt resultid = 0;
    104111  if ( result.nrow() > 0) {
     
    113120      resultid++;
    114121    }
     122    parangleCol_.put(rno, pa);
    115123    rotationCol_.put(rno, frot);
    116124    axisCol_.put(rno, fax);
     
    126134}
    127135
    128 void asap::STFocus::getEntry( Float& rotation, Float& angle, Float& ftan,
    129                               Float& hand, Float& user, Float& mount,
    130                               Float& xyphase, Float& xyphaseoffset,
    131                               uInt id) const
     136  void STFocus::getEntry( Float& pa, Float& rotation, Float& angle, Float& ftan,
     137                                Float& hand, Float& user, Float& mount,
     138                                Float& xyphase, Float& xyphaseoffset,
     139                                uInt id) const
    132140{
    133141  Table t = table_(table_.col("ID") == Int(id) );
     
    138146  // get first row - there should only be one matching id
    139147  const TableRecord& rec = row.get(0);
     148  pa = rec.asFloat("PARANGLE");
    140149  rotation = rec.asFloat("ROTATION");
    141150  angle = rec.asFloat("AXIS");
     
    149158
    150159
    151 casa::Float asap::STFocus::getTotalFeedAngle( casa::uInt id ) const
     160casa::Float STFocus::getTotalAngle( casa::uInt id ) const
    152161{
    153162  Float total = 0.0f;
    154163  Table t = table_(table_.col("ID") == Int(id) );
    155164  if (t.nrow() == 0 ) {
    156     throw(AipsError("STFocus::getEntry - id out of range"));
     165    throw(AipsError("STFocus::getTotalAngle - id out of range"));
     166  }
     167  if (table_.keywordSet().asBool("PARALLACTIFY")) {
     168    return 0.0f;
    157169  }
    158170  ROTableRow row(t);
    159171  // get first row - there should only be one matching id
    160172  const TableRecord& rec = row.get(0);
     173  total += rec.asFloat("PARANGLE"); 
    161174  total += rec.asFloat("ROTATION");
    162175  total += rec.asFloat("USERPHASE");
     
    164177  return total;
    165178}
    166 }
    167179
    168 casa::Float asap::STFocus::getFeedHand( casa::uInt id ) const
     180
     181casa::Float STFocus::getFeedHand( casa::uInt id ) const
    169182{
    170183  Table t = table_(table_.col("ID") == Int(id) );
     
    177190}
    178191
     192void STFocus::setParallactify(bool istrue) {
     193  table_.rwKeywordSet().define("PARALLACTIFY", Bool(istrue));
     194}
     195
     196}
  • branches/alma/src/STFocus.h

    r1353 r1757  
    3737  STFocus& operator=(const STFocus& other);
    3838
    39   casa::uInt addEntry( casa::Float faxis, casa::Float ftan,
     39  casa::uInt addEntry( casa::Float pa, casa::Float faxis, casa::Float ftan,
    4040                       casa::Float frot, casa::Float hand=1.0f,
    4141                       casa::Float mount=0.0f, casa::Float user=0.0f,
    42                        casa::Float xyphase=0.0f, casa::Float xyphaseoffset=0.0f);
     42                       casa::Float xyphase=0.0f,
     43                       casa::Float xyphaseoffset=0.0f);
    4344
    44   void getEntry( casa::Float& fax, casa::Float& ftan,
     45  void getEntry( casa::Float& pa, casa::Float& fax, casa::Float& ftan,
    4546                 casa::Float& frot, casa::Float& hand,
    4647                 casa::Float& mount, casa::Float& user,
     
    4849                 casa::uInt id) const;
    4950
    50   casa::Float getTotalFeedAngle(casa::uInt id) const;
     51  casa::Float getTotalAngle(casa::uInt id) const;
     52
     53  casa::Float getParAngle(casa::uInt id) const {
     54    return parangleCol_(id);
     55  }
    5156  casa::Float getFeedHand(casa::uInt id) const;
     57
     58  void setParallactify(bool istrue=false);
    5259
    5360  const casa::String& name() const { return name_; }
     
    5764  static const casa::String name_;
    5865  casa::ScalarColumn<casa::Float> rotationCol_, axisCol_,
    59                                   tanCol_,handCol_,
    60                                   mountCol_,userCol_,
    61                                   xyphCol_,xyphoffCol_;
     66    tanCol_,handCol_, parangleCol_,
     67    mountCol_,userCol_, xyphCol_,xyphoffCol_,;
    6268};
    6369
  • branches/alma/src/STFrequencies.cpp

    r1603 r1757  
    170170**/
    171171SpectralCoordinate
    172   asap::STFrequencies::getSpectralCoordinate( const MDirection& md,
     172  STFrequencies::getSpectralCoordinate( const MDirection& md,
    173173                                              const MPosition& mp,
    174174                                              const MEpoch& me,
     
    242242{
    243243  Vector<Float> offset(1,0.0);
    244   Vector<Float> factors(1,1.0/width);
     244  Vector<Float> factors(1,width);
    245245  Vector<Int> newshape;
    246246  CoordinateSystem csys;
     
    317317        << rec.asDouble("REFVAL") << setw(7)
    318318        << rec.asDouble("REFPIX")
    319         << setw(12)
     319        << setw(15)
    320320        << rec.asDouble("INCREMENT");
    321321  }
     
    324324    int f = outstr.find_first_not_of(' ');
    325325    int l = outstr.find_last_not_of(' ', outstr.size());
    326     if (f < 0) { 
    327       f = 0; 
    328     }
    329     if ( l < f  || l < f ) { 
     326    if (f < 0) {
     327      f = 0;
     328    }
     329    if ( l < f  || l < f ) {
    330330      l = outstr.size();
    331331    }
     
    439439}
    440440
    441 void STFrequencies::shiftRefPix(int npix, uInt id) 
     441void STFrequencies::shiftRefPix(int npix, uInt id)
    442442{
    443443  Table t = table_(table_.col("ID") == Int(id) );
  • branches/alma/src/STLineFinder.cpp

    r1603 r1757  
    3434#include "STLineFinder.h"
    3535#include "STFitter.h"
     36#include "IndexedCompare.h"
    3637
    3738// STL
     
    110111
    111112protected:
    112    // supplementary function to control running mean calculations.
    113    // It adds a specified channel to the running mean box and
     113   // supplementary function to control running mean/median calculations.
     114   // It adds a specified channel to the running box and
    114115   // removes (ch-maxboxnchan+1)'th channel from there
    115116   // Channels, for which the mask is false or index is beyond the
     
    152153                                           // last point of the detected line
    153154                                           //
     155   bool itsUseMedian;                      // true if median statistics is used
     156                                           // to determine the noise level, otherwise
     157                                           // it is the mean of the lowest 80% of deviations
     158                                           // (default)
     159   int itsNoiseSampleSize;                 // sample size used to estimate the noise statistics
     160                                           // Negative value means the whole spectrum is used (default)
    154161public:
    155162
     
    157164   LFAboveThreshold(std::list<pair<int,int> > &in_lines,
    158165                    int in_min_nchan = 3,
    159                     casa::Float in_threshold = 5) throw();
     166                    casa::Float in_threshold = 5,
     167                    bool use_median = false,
     168                    int noise_sample_size = -1) throw();
    160169   virtual ~LFAboveThreshold() throw();
    161170
     
    200209///////////////////////////////////////////////////////////////////////////////
    201210
     211///////////////////////////////////////////////////////////////////////////////
     212//
     213// LFNoiseEstimator  a helper class designed to estimate off-line variance
     214//                   using statistics depending on the distribution of
     215//                   values (e.g. like a median)
     216//
     217//                   Two statistics are supported: median and an average of
     218//                   80% of smallest values.
     219//
     220
     221struct LFNoiseEstimator {
     222   // construct an object
     223   // size - maximum sample size. After a size number of elements is processed
     224   // any new samples would cause the algorithm to drop the oldest samples in the
     225   // buffer.
     226   explicit LFNoiseEstimator(size_t size);
     227
     228   // add a new sample
     229   // in - the new value
     230   void add(float in);
     231
     232   // median of the distribution
     233   float median() const;
     234
     235   // mean of lowest 80% of the samples
     236   float meanLowest80Percent() const;
     237
     238   // return true if the buffer is full (i.e. statistics are representative)
     239   inline bool filledToCapacity() const { return itsBufferFull;}
     240
     241protected:
     242   // update cache of sorted indices
     243   // (it is assumed that itsSampleNumber points to the newly
     244   // replaced element)
     245   void updateSortedCache() const;
     246
     247   // build sorted cache from the scratch
     248   void buildSortedCache() const;
     249
     250   // number of samples accumulated so far
     251   // (can be less than the buffer size)
     252   size_t numberOfSamples() const;
     253
     254   // this helper method builds the cache if
     255   // necessary using one of the methods
     256   void fillCacheIfNecessary() const;
     257
     258private:
     259   // buffer with samples (unsorted)
     260   std::vector<float> itsVariances;
     261   // current sample number (<=itsVariances.size())
     262   size_t itsSampleNumber;
     263   // true, if the buffer all values in the sample buffer are used
     264   bool itsBufferFull;
     265   // cached indices into vector of samples
     266   mutable std::vector<size_t> itsSortedIndices;
     267   // true if any of the statistics have been obtained at least
     268   // once. This flag allows to implement a more efficient way of
     269   // calculating statistics, if they are needed at once and not
     270   // after each addition of a new element
     271   mutable bool itsStatisticsAccessed;
     272};
     273
     274//
     275///////////////////////////////////////////////////////////////////////////////
     276
     277
    202278} // namespace asap
     279
     280///////////////////////////////////////////////////////////////////////////////
     281//
     282// LFNoiseEstimator  a helper class designed to estimate off-line variance
     283//                   using statistics depending on the distribution of
     284//                   values (e.g. like a median)
     285//
     286//                   Two statistics are supported: median and an average of
     287//                   80% of smallest values.
     288//
     289
     290// construct an object
     291// size - maximum sample size. After a size number of elements is processed
     292// any new samples would cause the algorithm to drop the oldest samples in the
     293// buffer.
     294LFNoiseEstimator::LFNoiseEstimator(size_t size) : itsVariances(size),
     295     itsSampleNumber(0), itsBufferFull(false), itsSortedIndices(size),
     296     itsStatisticsAccessed(false)
     297{
     298   AlwaysAssert(size>0,AipsError);
     299}
     300
     301
     302// add a new sample
     303// in - the new value
     304void LFNoiseEstimator::add(float in)
     305{
     306   if (isnan(in)) {
     307       // normally it shouldn't happen
     308       return;
     309   }
     310   itsVariances[itsSampleNumber] = in;
     311
     312   if (itsStatisticsAccessed) {
     313       // only do element by element addition if on-the-fly
     314       // statistics are needed
     315       updateSortedCache();
     316   }
     317
     318   // advance itsSampleNumber now
     319   ++itsSampleNumber;
     320   if (itsSampleNumber == itsVariances.size()) {
     321       itsSampleNumber = 0;
     322       itsBufferFull = true;
     323   }
     324   AlwaysAssert(itsSampleNumber<itsVariances.size(),AipsError);
     325}
     326
     327// number of samples accumulated so far
     328// (can be less than the buffer size)
     329size_t LFNoiseEstimator::numberOfSamples() const
     330{
     331  // the number of samples accumulated so far may be less than the
     332  // buffer size
     333  const size_t nSamples = itsBufferFull ? itsVariances.size(): itsSampleNumber;
     334  AlwaysAssert( (nSamples > 0) && (nSamples <= itsVariances.size()), AipsError);
     335  return nSamples;
     336}
     337
     338// this helper method builds the cache if
     339// necessary using one of the methods
     340void LFNoiseEstimator::fillCacheIfNecessary() const
     341{
     342  if (!itsStatisticsAccessed) {
     343      if ((itsSampleNumber!=0) || itsBufferFull) {
     344          // build the whole cache efficiently
     345          buildSortedCache();
     346      } else {
     347          updateSortedCache();
     348      }
     349      itsStatisticsAccessed = true;
     350  } // otherwise, it is updated in 'add' using on-the-fly method
     351}
     352
     353// median of the distribution
     354float LFNoiseEstimator::median() const
     355{
     356  fillCacheIfNecessary();
     357  // the number of samples accumulated so far may be less than the
     358  // buffer size
     359  const size_t nSamples = numberOfSamples();
     360  const size_t medSample = nSamples / 2;
     361  AlwaysAssert(medSample < itsSortedIndices.size(), AipsError);
     362  return itsVariances[itsSortedIndices[medSample]];
     363}
     364
     365// mean of lowest 80% of the samples
     366float LFNoiseEstimator::meanLowest80Percent() const
     367{
     368  fillCacheIfNecessary();
     369  // the number of samples accumulated so far may be less than the
     370  // buffer size
     371  const size_t nSamples = numberOfSamples();
     372  float result = 0;
     373  size_t numpt=size_t(0.8*nSamples);
     374  if (!numpt) {
     375      numpt=nSamples; // no much else left,
     376                     // although it is very inaccurate
     377  }
     378  AlwaysAssert( (numpt > 0) && (numpt<itsSortedIndices.size()), AipsError);
     379  for (size_t ch=0; ch<numpt; ++ch) {
     380       result += itsVariances[itsSortedIndices[ch]];
     381  }
     382  result /= float(numpt);
     383  return result;
     384}
     385
     386// update cache of sorted indices
     387// (it is assumed that itsSampleNumber points to the newly
     388// replaced element)
     389void LFNoiseEstimator::updateSortedCache() const
     390{
     391  // the number of samples accumulated so far may be less than the
     392  // buffer size
     393  const size_t nSamples = numberOfSamples();
     394
     395  if (itsBufferFull) {
     396      // first find the index of the element which is being replaced
     397      size_t index = nSamples;
     398      for (size_t i=0; i<nSamples; ++i) {
     399           AlwaysAssert(i < itsSortedIndices.size(), AipsError);
     400           if (itsSortedIndices[i] == itsSampleNumber) {
     401               index = i;
     402               break;
     403           }
     404      }
     405      AlwaysAssert( index < nSamples, AipsError);
     406
     407      const vector<size_t>::iterator indStart = itsSortedIndices.begin();
     408      // merge this element with preceeding block first
     409      if (index != 0) {
     410          // merge indices on the basis of variances
     411          inplace_merge(indStart,indStart+index,indStart+index+1,
     412                        indexedCompare<size_t>(itsVariances.begin()));
     413      }
     414      // merge with the following block
     415      if (index + 1 != nSamples) {
     416          // merge indices on the basis of variances
     417          inplace_merge(indStart,indStart+index+1,indStart+nSamples,
     418                        indexedCompare<size_t>(itsVariances.begin()));
     419      }
     420  } else {
     421      // itsSampleNumber is the index of the new element
     422      AlwaysAssert(itsSampleNumber < itsSortedIndices.size(), AipsError);
     423      itsSortedIndices[itsSampleNumber] = itsSampleNumber;
     424      if (itsSampleNumber >= 1) {
     425          // we have to place this new sample in
     426          const vector<size_t>::iterator indStart = itsSortedIndices.begin();
     427          // merge indices on the basis of variances
     428          inplace_merge(indStart,indStart+itsSampleNumber,indStart+itsSampleNumber+1,
     429                        indexedCompare<size_t>(itsVariances.begin()));
     430      }
     431  }
     432}
     433
     434// build sorted cache from the scratch
     435void LFNoiseEstimator::buildSortedCache() const
     436{
     437  // the number of samples accumulated so far may be less than the
     438  // buffer size
     439  const size_t nSamples = numberOfSamples();
     440  AlwaysAssert(nSamples <= itsSortedIndices.size(), AipsError);
     441  for (size_t i=0; i<nSamples; ++i) {
     442       itsSortedIndices[i]=i;
     443  }
     444
     445  // sort indices, but check the array of variances
     446  const vector<size_t>::iterator indStart = itsSortedIndices.begin();
     447  stable_sort(indStart,indStart+nSamples, indexedCompare<size_t>(itsVariances.begin()));
     448}
     449
     450//
     451///////////////////////////////////////////////////////////////////////////////
    203452
    204453///////////////////////////////////////////////////////////////////////////////
     
    275524}
    276525
    277 // supplementary function to control running mean calculations.
    278 // It adds a specified channel to the running mean box and
     526// supplementary function to control running mean/median calculations.
     527// It adds a specified channel to the running box and
    279528// removes (ch-max_box_nchan+1)'th channel from there
    280529// Channels, for which the mask is false or index is beyond the
     
    339588                (meanch2-square(meanch));
    340589      linmean=coeff*(Float(cur_channel)-meanch)+mean;
    341       linvariance=sqrt(sumf2/Float(box_chan_cntr)-square(mean)-
    342                     square(coeff)*(meanch2-square(meanch)));
     590      linvariance=sumf2/Float(box_chan_cntr)-square(mean)-
     591                    square(coeff)*(meanch2-square(meanch));
     592      if (linvariance<0.) {
     593          // this shouldn't happen normally, but could be due to round-off error
     594          linvariance = 0;
     595      } else {
     596          linvariance = sqrt(linvariance);
     597      }
    343598  }
    344599  need2recalculate=False;
     
    351606///////////////////////////////////////////////////////////////////////////////
    352607//
    353 // LFAboveThreshold - a running mean algorithm for line detection
     608// LFAboveThreshold - a running mean/median algorithm for line detection
    354609//
    355610//
     
    359614LFAboveThreshold::LFAboveThreshold(std::list<pair<int,int> > &in_lines,
    360615                                   int in_min_nchan,
    361                                    casa::Float in_threshold) throw() :
     616                                   casa::Float in_threshold,
     617                                   bool use_median,
     618                                   int noise_sample_size) throw() :
    362619             min_nchan(in_min_nchan), threshold(in_threshold),
    363              lines(in_lines), running_box(NULL) {}
     620             lines(in_lines), running_box(NULL), itsUseMedian(use_median),
     621             itsNoiseSampleSize(noise_sample_size) {}
    364622
    365623LFAboveThreshold::~LFAboveThreshold() throw()
     
    474732      running_box=new RunningBox(spectrum,mask,edge,max_box_nchan);
    475733
    476 
    477734      // determine the off-line variance first
    478735      // an assumption made: lines occupy a small part of the spectrum
    479736
    480       std::vector<float> variances(edge.second-edge.first);
    481       DebugAssert(variances.size(),AipsError);
    482 
    483       for (;running_box->haveMore();running_box->next())
    484            variances[running_box->getChannel()-edge.first]=
    485                                 running_box->getLinVariance();
    486 
    487       // in the future we probably should do a proper Chi^2 estimation
    488       // now a simple 80% of smaller values will be used.
    489       // it may degrade the performance of the algorithm for weak lines
    490       // due to a bias of the Chi^2 distribution.
    491       stable_sort(variances.begin(),variances.end());
    492 
    493       Float offline_variance=0;
    494       uInt offline_cnt=uInt(0.8*variances.size());
    495       if (!offline_cnt) offline_cnt=variances.size(); // no much else left,
    496                                     // although it is very inaccurate
    497       for (uInt n=0;n<offline_cnt;++n)
    498            offline_variance+=variances[n];
    499       offline_variance/=Float(offline_cnt);
     737      const size_t noiseSampleSize = itsNoiseSampleSize<0 ? size_t(edge.second-edge.first) :
     738                      std::min(size_t(itsNoiseSampleSize), size_t(edge.second-edge.first));
     739      DebugAssert(noiseSampleSize,AipsError);
     740      const bool globalNoise = (size_t(edge.second - edge.first) == noiseSampleSize);
     741      LFNoiseEstimator ne(noiseSampleSize);
     742
     743      for (;running_box->haveMore();running_box->next()) {
     744           ne.add(running_box->getLinVariance());
     745           if (ne.filledToCapacity()) {
     746               break;
     747           }
     748      }
     749
     750      Float offline_variance = -1; // just a flag that it is unset
     751           
     752      if (globalNoise) {
     753          offline_variance = itsUseMedian ? ne.median() : ne.meanLowest80Percent();
     754      }
    500755
    501756      // actual search algorithm
     
    510765                                 running_box->next()) {
    511766           const int ch=running_box->getChannel();
    512            if (running_box->getNumberOfBoxPoints()>=minboxnchan)
     767           if (!globalNoise) {
     768               // add a next point for a local noise estimate
     769               ne.add(running_box->getLinVariance());
     770           }   
     771           if (running_box->getNumberOfBoxPoints()>=minboxnchan) {
     772               if (!globalNoise) {
     773                   offline_variance = itsUseMedian ? ne.median() : ne.meanLowest80Percent();
     774               }
     775               AlwaysAssert(offline_variance>0.,AipsError);
    513776               processChannel(mask[ch] && (fabs(running_box->aboveMean()) >=
    514777                  threshold*offline_variance), mask);
    515            else processCurLine(mask); // just finish what was accumulated before
     778           } else processCurLine(mask); // just finish what was accumulated before
    516779
    517780           signs[ch]=getAboveMeanSign();
    518            // os<<ch<<" "<<spectrum[ch]<<" "<<fabs(running_box->aboveMean())<<" "<<
    519            // threshold*offline_variance<<endl;
    520 
    521            const Float buf=running_box->aboveMean();
    522            if (buf>0) signs[ch]=1;
    523            else if (buf<0) signs[ch]=-1;
    524            else if (buf==0) signs[ch]=0;
    525            //os<<ch<<" "<<spectrum[ch]<<" "<<running_box->getLinMean()<<" "<<
    526            //             threshold*offline_variance<<endl;
     781            //os<<ch<<" "<<spectrum[ch]<<" "<<fabs(running_box->aboveMean())<<" "<<
     782            //threshold*offline_variance<<endl;
    527783      }
    528784      if (lines.size())
     
    649905//              Setting a very large value doesn't usually provide
    650906//              valid detections.
    651 // in_box_size  the box size for running mean calculation. Default is
     907// in_box_size  the box size for running mean/median calculation. Default is
    652908//              1./5. of the whole spectrum size
     909// in_noise_box the box size for off-line noise estimation (if working with
     910//              local noise. Negative value means use global noise estimate
     911//              Default is -1 (i.e. estimate using the whole spectrum)
     912// in_median    true if median statistics is used as opposed to average of
     913//              the lowest 80% of deviations (default)
    653914void STLineFinder::setOptions(const casa::Float &in_threshold,
    654915                              const casa::Int &in_min_nchan,
    655916                              const casa::Int &in_avg_limit,
    656                               const casa::Float &in_box_size) throw()
     917                              const casa::Float &in_box_size,
     918                              const casa::Float &in_noise_box,
     919                              const casa::Bool &in_median) throw()
    657920{
    658921  threshold=in_threshold;
     
    660923  avg_limit=in_avg_limit;
    661924  box_size=in_box_size;
     925  itsNoiseBox = in_noise_box;
     926  itsUseMedian = in_median;
    662927}
    663928
     
    683948                const casa::uInt &whichRow) throw(casa::AipsError)
    684949{
    685   //const int minboxnchan=4;
    686950  if (scan.null())
    687951      throw AipsError("STLineFinder::findLines - a scan should be set first,"
     
    700964      throw AipsError("STLineFinder::findLines - in_scan and in_mask have different"
    701965            "number of spectral channels.");
     966
     967  // taking flagged channels into account
     968  vector<bool> flaggedChannels = scan->getMask(whichRow);
     969  if (flaggedChannels.size()) {
     970      // there is a mask set for this row
     971      if (flaggedChannels.size() != mask.nelements()) {
     972          throw AipsError("STLineFinder::findLines - internal inconsistency: number of mask elements do not match the number of channels");
     973      }
     974      for (size_t ch = 0; ch<mask.nelements(); ++ch) {
     975           mask[ch] &= flaggedChannels[ch];
     976      }
     977  }
     978
    702979  // number of elements in in_edge
    703980  if (in_edge.size()>2)
     
    7321009      throw AipsError("STLineFinder::findLines - box_size is too small");
    7331010
     1011  // number of elements in the sample for noise estimate
     1012  const int noise_box = itsNoiseBox<0 ? -1 : int(nchan * itsNoiseBox);
     1013
     1014  if ((noise_box!= -1) and (noise_box<2))
     1015      throw AipsError("STLineFinder::findLines - noise_box is supposed to be at least 2 elements");
     1016
    7341017  spectrum.resize();
    7351018  spectrum = Vector<Float>(scan->getSpectrum(whichRow));
     
    7551038     try {
    7561039         // line find algorithm
    757          LFAboveThreshold lfalg(new_lines,avg_factor*min_nchan, threshold);
     1040         LFAboveThreshold lfalg(new_lines,avg_factor*min_nchan, threshold, itsUseMedian,noise_box);
    7581041         lfalg.findLines(spectrum,temp_mask,edge,max_box_nchan);
    7591042         signs.resize(lfalg.getSigns().nelements());
  • branches/alma/src/STLineFinder.h

    r1353 r1757  
    150150   // in_box_size  the box size for running mean calculation. Default is
    151151   //              1./5. of the whole spectrum size
     152   // in_noise_box the box size for off-line noise estimation (if working with
     153   //              local noise. Negative value means use global noise estimate
     154   //              Default is -1 (i.e. estimate using the whole spectrum)
     155   // in_median    true if median statistics is used as opposed to average of
     156   //              the lowest 80% of deviations (default)
    152157   void setOptions(const casa::Float &in_threshold=sqrt(3.),
    153158                   const casa::Int &in_min_nchan=3,
    154159                   const casa::Int &in_avg_limit=8,
    155                    const casa::Float &in_box_size=0.2) throw();
     160                   const casa::Float &in_box_size=0.2,
     161                   const casa::Float &in_noise_box=-1.,
     162                   const casa::Bool &in_median = casa::False) throw();
    156163
    157164   // set the scan to work with (in_scan parameter)
     
    241248   // a buffer for the spectrum
    242249   mutable casa::Vector<casa::Float>  spectrum;
     250
     251   // the box size for off-line noise estimation (if working with
     252   // local noise. Negative value means use global noise estimate
     253   // Default is -1 (i.e. estimate using the whole spectrum)
     254   casa::Float itsNoiseBox;
     255
     256   // true if median statistics is used as opposed to average of
     257   // the lowest 80% of deviations (default)
     258   casa::Bool itsUseMedian;
    243259};
    244260
  • branches/alma/src/STMath.cpp

    r1719 r1757  
    5252#include "RowAccumulator.h"
    5353#include "STAttr.h"
     54#include "STSelector.h"
     55
    5456#include "STMath.h"
    55 #include "STSelector.h"
    56 
    5757using namespace casa;
    5858
     
    740740}
    741741
    742 CountedPtr<Scantable> STMath::binaryOperate(const CountedPtr<Scantable>& left, 
    743                                             const CountedPtr<Scantable>& right, 
     742CountedPtr<Scantable> STMath::binaryOperate(const CountedPtr<Scantable>& left,
     743                                            const CountedPtr<Scantable>& right,
    744744                                            const std::string& mode)
    745745{
     
    13791379{
    13801380
    1381  
     1381
    13821382  STSelector sel;
    13831383  CountedPtr< Scantable > ws = getScantable(s, false);
     
    15181518  // for each row
    15191519  // assume that the data order are same between sig and ref
    1520   RowAccumulator acc( asap::TINTSYS ) ;
     1520  RowAccumulator acc( asap::W_TINTSYS ) ;
    15211521  for ( int i = 0 ; i < sig->nrow() ; i++ ) {
    15221522    // get values
     
    19521952  // initialize the lookup table if necessary
    19531953  if ( lookup.empty() ) {
    1954     lookup["NONE"]   = asap::NONE;
    1955     lookup["TINT"] = asap::TINT;
    1956     lookup["TINTSYS"]  = asap::TINTSYS;
    1957     lookup["TSYS"]  = asap::TSYS;
    1958     lookup["VAR"]  = asap::VAR;
     1954    lookup["NONE"]   = asap::W_NONE;
     1955    lookup["TINT"] = asap::W_TINT;
     1956    lookup["TINTSYS"]  = asap::W_TINTSYS;
     1957    lookup["TSYS"]  = asap::W_TSYS;
     1958    lookup["VAR"]  = asap::W_VAR;
    19591959  }
    19601960
     
    20002000    String msg;
    20012001    if ( nc > 0 ) {
    2002       ppoly = new Polynomial<Float>(nc);
     2002      ppoly = new Polynomial<Float>(nc-1);
    20032003      coeff = coeffs;
    20042004      msg = String("user");
     
    20062006      STAttr sdAttr;
    20072007      coeff = sdAttr.gainElevationPoly(inst);
    2008       ppoly = new Polynomial<Float>(3);
     2008      ppoly = new Polynomial<Float>(coeff.nelements()-1);
    20092009      msg = String("built in");
    20102010    }
     
    21442144    if (d < 0) {
    21452145      Instrument inst =
    2146         STAttr::convertInstrument(tab.keywordSet().asString("AntennaName"), 
     2146        STAttr::convertInstrument(tab.keywordSet().asString("AntennaName"),
    21472147                                  True);
    21482148      STAttr sda;
     
    22072207
    22082208CountedPtr< Scantable > STMath::opacity( const CountedPtr< Scantable > & in,
    2209                                          float tau )
     2209                                         const std::vector<float>& tau )
    22102210{
    22112211  CountedPtr< Scantable > out = getScantable(in, false);
    22122212
    2213   Table tab = out->table();
    2214   ROScalarColumn<Float> elev(tab, "ELEVATION");
    2215   ArrayColumn<Float> specCol(tab, "SPECTRA");
    2216   ArrayColumn<uChar> flagCol(tab, "FLAGTRA");
    2217   ArrayColumn<Float> tsysCol(tab, "TSYS");
    2218   for ( uInt i=0; i<tab.nrow(); ++i) {
    2219     Float zdist = Float(C::pi_2) - elev(i);
    2220     Float factor = exp(tau/cos(zdist));
    2221     MaskedArray<Float> ma = maskedArray(specCol(i), flagCol(i));
    2222     ma *= factor;
    2223     specCol.put(i, ma.getArray());
    2224     flagCol.put(i, flagsFromMA(ma));
    2225     Vector<Float> tsys;
    2226     tsysCol.get(i, tsys);
    2227     tsys *= factor;
    2228     tsysCol.put(i, tsys);
     2213  Table outtab = out->table();
     2214
     2215  const uInt ntau = uInt(tau.size());
     2216  std::vector<float>::const_iterator tauit = tau.begin();
     2217  AlwaysAssert((ntau == 1 || ntau == in->nif() || ntau == in->nif() * in->npol()),
     2218               AipsError);
     2219  TableIterator iiter(outtab, "IFNO");
     2220  while ( !iiter.pastEnd() ) {
     2221    Table itab = iiter.table();
     2222    TableIterator piter(outtab, "POLNO");
     2223    while ( !piter.pastEnd() ) {
     2224      Table tab = piter.table();
     2225      ROScalarColumn<Float> elev(tab, "ELEVATION");
     2226      ArrayColumn<Float> specCol(tab, "SPECTRA");
     2227      ArrayColumn<uChar> flagCol(tab, "FLAGTRA");
     2228      ArrayColumn<Float> tsysCol(tab, "TSYS");
     2229      for ( uInt i=0; i<tab.nrow(); ++i) {
     2230        Float zdist = Float(C::pi_2) - elev(i);
     2231        Float factor = exp(*tauit/cos(zdist));
     2232        MaskedArray<Float> ma = maskedArray(specCol(i), flagCol(i));
     2233        ma *= factor;
     2234        specCol.put(i, ma.getArray());
     2235        flagCol.put(i, flagsFromMA(ma));
     2236        Vector<Float> tsys;
     2237        tsysCol.get(i, tsys);
     2238        tsys *= factor;
     2239        tsysCol.put(i, tsys);
     2240      }
     2241      if (ntau == in->nif()*in->npol() ) {
     2242        tauit++;
     2243      }
     2244      piter++;
     2245    }
     2246    if (ntau >= in->nif() ) {
     2247      tauit++;
     2248    }
     2249    iiter++;
    22292250  }
    22302251  return out;
     
    22332254CountedPtr< Scantable > STMath::smoothOther( const CountedPtr< Scantable >& in,
    22342255                                             const std::string& kernel,
    2235                                              float width )
     2256                                             float width, int order)
    22362257{
    22372258  CountedPtr< Scantable > out = getScantable(in, false);
     
    22542275      mathutil::runningMedian(specout, maskout, spec , mask, width);
    22552276      convertArray(flag, maskout);
     2277    } else if ( kernel == "poly" ) {
     2278      mathutil::polyfit(specout, maskout, spec, !mask, width, order);
     2279      convertArray(flag, !maskout);
    22562280    }
    22572281    flagCol.put(i, flag);
     
    22622286
    22632287CountedPtr< Scantable > STMath::smooth( const CountedPtr< Scantable >& in,
    2264                                         const std::string& kernel, float width )
    2265 {
    2266   if (kernel == "rmedian"  || kernel == "hanning") {
    2267     return smoothOther(in, kernel, width);
     2288                                        const std::string& kernel, float width,
     2289                                        int order)
     2290{
     2291  if (kernel == "rmedian"  || kernel == "hanning" || kernel == "poly") {
     2292    return smoothOther(in, kernel, width, order);
    22682293  }
    22692294  CountedPtr< Scantable > out = getScantable(in, false);
     
    23512376          id = out->molecules().addEntry(rf, name, fname);
    23522377          molidcol.put(k, id);
    2353           Float frot,fax,ftan,fhand,fmount,fuser, fxy, fxyp;
    2354           (*it)->focus().getEntry(fax, ftan, frot, fhand,
     2378          Float fpa,frot,fax,ftan,fhand,fmount,fuser, fxy, fxyp;
     2379          (*it)->focus().getEntry(fpa, fax, ftan, frot, fhand,
    23552380                                  fmount,fuser, fxy, fxyp,
    23562381                                  rec.asuInt("FOCUS_ID"));
    2357           id = out->focus().addEntry(fax, ftan, frot, fhand,
     2382          id = out->focus().addEntry(fpa, fax, ftan, frot, fhand,
    23582383                                     fmount,fuser, fxy, fxyp);
    23592384          focusidcol.put(k, id);
     
    23992424  cols[3] = String("CYCLENO");
    24002425  TableIterator iter(tout, cols);
    2401   CountedPtr<STPol> stpol = STPol::getPolClass(out->factories_, 
     2426  CountedPtr<STPol> stpol = STPol::getPolClass(out->factories_,
    24022427                                               out->getPolType() );
    24032428  while (!iter.pastEnd()) {
     
    24052430    ArrayColumn<Float> speccol(t, "SPECTRA");
    24062431    ScalarColumn<uInt> focidcol(t, "FOCUS_ID");
    2407     ScalarColumn<Float> parancol(t, "PARANGLE");
    24082432    Matrix<Float> pols(speccol.getColumn());
    24092433    try {
    24102434      stpol->setSpectra(pols);
    2411       Float fang,fhand,parang;
    2412       fang = in->focusTable_.getTotalFeedAngle(focidcol(0));
     2435      Float fang,fhand;
     2436      fang = in->focusTable_.getTotalAngle(focidcol(0));
    24132437      fhand = in->focusTable_.getFeedHand(focidcol(0));
    2414       parang = parancol(0);
    2415       /// @todo re-enable this
    2416       // disable total feed angle to support paralactifying Caswell style
    2417       stpol->setPhaseCorrections(parang, -parang, fhand);
     2438      stpol->setPhaseCorrections(fang, fhand);
    24182439      // use a member function pointer in STPol.  This only works on
    24192440      // the STPol pointer itself, not the Counted Pointer so
     
    26812702      uInt row = tab.rowNumbers()[0];
    26822703      stpol->setSpectra(in->getPolMatrix(row));
    2683       Float fang,fhand,parang;
    2684       fang = in->focusTable_.getTotalFeedAngle(in->mfocusidCol_(row));
     2704      Float fang,fhand;
     2705      fang = in->focusTable_.getTotalAngle(in->mfocusidCol_(row));
    26852706      fhand = in->focusTable_.getFeedHand(in->mfocusidCol_(row));
    2686       parang = in->paraCol_(row);
    2687       /// @todo re-enable this
    2688       // disable total feed angle to support paralactifying Caswell style
    2689       stpol->setPhaseCorrections(parang, -parang, fhand);
     2707      stpol->setPhaseCorrections(fang, fhand);
    26902708      Int npolout = 0;
    26912709      for (uInt i=0; i<tab.nrow(); ++i) {
     
    27372755CountedPtr< Scantable >
    27382756  asap::STMath::lagFlag( const CountedPtr< Scantable > & in,
    2739                           double frequency, double width )
     2757                         double start, double end,
     2758                         const std::string& mode)
    27402759{
    27412760  CountedPtr< Scantable > out = getScantable(in, false);
     
    27552774      Vector<Float> spec = specCol(i);
    27562775      Vector<uChar> flag = flagCol(i);
    2757       Int lag0 = Int(spec.nelements()*abs(inc)/(frequency+width)+0.5);
    2758       Int lag1 = Int(spec.nelements()*abs(inc)/(frequency-width)+0.5);
     2776      int fstart = -1;
     2777      int fend = -1;
    27592778      for (unsigned int k=0; k < flag.nelements(); ++k ) {
    27602779        if (flag[k] > 0) {
    2761           spec[k] = 0.0;
     2780          fstart = k;
     2781          while (flag[k] > 0 && k < flag.nelements()) {
     2782            fend = k;
     2783            k++;
     2784          }
    27622785        }
     2786        Float interp = 0.0;
     2787        if (fstart-1 > 0 ) {
     2788          interp = spec[fstart-1];
     2789          if (fend+1 < spec.nelements()) {
     2790            interp = (interp+spec[fend+1])/2.0;
     2791          }
     2792        } else {
     2793          interp = spec[fend+1];
     2794        }
     2795        if (fstart > -1 && fend > -1) {
     2796          for (int j=fstart;j<=fend;++j) {
     2797            spec[j] = interp;
     2798          }
     2799        }
     2800        fstart =-1;
     2801        fend = -1;
    27632802      }
    27642803      Vector<Complex> lags;
    27652804      ffts.fft0(lags, spec);
    2766       Int start =  max(0, lag0);
    2767       Int end =  min(Int(lags.nelements()-1), lag1);
    2768       if (start == end) {
    2769         lags[start] = Complex(0.0);
     2805      Int lag0(start+0.5);
     2806      Int lag1(end+0.5);
     2807      if (mode == "frequency") {
     2808        lag0 = Int(spec.nelements()*abs(inc)/(start)+0.5);
     2809        lag1 = Int(spec.nelements()*abs(inc)/(end)+0.5);
     2810      }
     2811      Int lstart =  max(0, lag0);
     2812      Int lend =  min(Int(lags.nelements()-1), lag1);
     2813      if (lstart == lend) {
     2814        lags[lstart] = Complex(0.0);
    27702815      } else {
    2771         for (int j=start; j <=end ;++j) {
     2816        if (lstart > lend) {
     2817          Int tmp = lend;
     2818          lend = lstart;
     2819          lstart = tmp;
     2820        }
     2821        for (int j=lstart; j <=lend ;++j) {
    27722822          lags[j] = Complex(0.0);
    27732823        }
  • branches/alma/src/STMath.h

    r1680 r1757  
    146146
    147147  casa::CountedPtr<Scantable>
    148     binaryOperate( const casa::CountedPtr<Scantable>& left, 
    149                    const casa::CountedPtr<Scantable>& right, 
     148    binaryOperate( const casa::CountedPtr<Scantable>& left,
     149                   const casa::CountedPtr<Scantable>& right,
    150150                   const std::string& mode);
    151151
     
    290290  casa::CountedPtr<Scantable>
    291291    smooth(const casa::CountedPtr<Scantable>& in, const std::string& kernel,
    292                       float width);
     292                      float width, int order=2);
    293293
    294294  casa::CountedPtr<Scantable>
     
    302302
    303303  casa::CountedPtr<Scantable> opacity(const casa::CountedPtr<Scantable>& in,
    304                                       float tau);
     304                                      const std::vector<float>& tau);
    305305
    306306  casa::CountedPtr<Scantable>
     
    338338   */
    339339  casa::CountedPtr<Scantable>
    340     lagFlag( const casa::CountedPtr<Scantable>& in, double frequency,
    341               double width);
     340    lagFlag( const casa::CountedPtr<Scantable>& in, double start,
     341             double end, const std::string& mode="frequency");
    342342
    343343  // test for average spectra with different channel/resolution
     
    374374                              bool tokelvin, float cfac);
    375375
    376   casa::CountedPtr< Scantable > 
     376  casa::CountedPtr< Scantable >
    377377    smoothOther( const casa::CountedPtr< Scantable >& in,
    378378                 const std::string& kernel,
    379                  float width );
     379                 float width, int order=2 );
    380380
    381381  casa::CountedPtr< Scantable >
  • branches/alma/src/STMathWrapper.h

    r1680 r1757  
    146146
    147147  ScantableWrapper
    148     smooth(const ScantableWrapper& in, const std::string& kernel, float width)
    149   { return ScantableWrapper(STMath::smooth(in.getCP(), kernel, width)); }
     148    smooth(const ScantableWrapper& in, const std::string& kernel, float width,
     149           int order=2)
     150  { return ScantableWrapper(STMath::smooth(in.getCP(), kernel, width, order)); }
    150151
    151152  ScantableWrapper
     
    164165
    165166  ScantableWrapper opacity(const ScantableWrapper& in,
    166                                       float tau)
     167                          const std::vector<float>& tau)
    167168  { return ScantableWrapper(STMath::opacity(in.getCP(), tau)); }
    168169
     
    201202
    202203  ScantableWrapper lagFlag( const ScantableWrapper& in,
    203                             double frequency, double width )
    204   { return ScantableWrapper(STMath::lagFlag(in.getCP(), frequency, width)); }
     204                            double start, double end,
     205                            const std::string& mode="frequency" )
     206  { return ScantableWrapper(STMath::lagFlag(in.getCP(), start, end,
     207                                            mode)); }
    205208
    206209  // test for average spectra with different channel/resolution
  • branches/alma/src/STPol.h

    r1015 r1757  
    3535
    3636  typedef  void (STPol::*polOperation)( casa::Float phase );
    37   STPol(): totalfeed_(0.0),parangle_(0.0),feedhand_(1.0) {}
     37  STPol(): totalangle_(0.0),feedhand_(1.0) {}
    3838  virtual ~STPol() {}
    3939
     
    8383
    8484
    85   void setPhaseCorrections(casa::Float parangle=0.0, casa::Float totalfeed=0.0,
    86                            casa::Float feedhand=1.0)
    87     { totalfeed_=totalfeed;parangle_=parangle;feedhand_=feedhand;}
     85  void setPhaseCorrections(casa::Float totalang=0.0, casa::Float feedhand=1.0)
     86    { totalangle_=totalang;feedhand_=feedhand;}
    8887
    89   casa::Float getTotalPhase() const { return totalfeed_+parangle_; }
     88  casa::Float getTotalPhase() const { return totalangle_; }
    9089  casa::Float getFeedHand() const { return feedhand_; }
    9190
     
    9998  static std::map<std::string, std::map<int, std::string> > labelmap_;
    10099
    101   casa::Float totalfeed_,parangle_,feedhand_;
     100  casa::Float totalangle_,feedhand_;
    102101  std::string mode_;
    103102  casa::Matrix<casa::Float> basespectra_;
  • branches/alma/src/STWriter.cpp

    r1683 r1757  
    4242#include <atnf/PKSIO/PKSMS2writer.h>
    4343#include <atnf/PKSIO/PKSSDwriter.h>
     44#include <atnf/PKSIO/SrcType.h>
    4445
    4546#include <tables/Tables/Table.h>
     
    5152#include "STAsciiWriter.h"
    5253#include "STHeader.h"
     54#include "STMath.h"
     55
    5356
    5457#include "STWriter.h"
     
    104107                    const std::string &filename)
    105108{
     109  // If we write out foreign formats we have to convert the frequency system
     110  // into the output frame, as we do everything related to SPectarlCoordinates
     111  // in asap on-the-fly.
     112
     113  CountedPtr<Scantable> inst = in;
     114  if (in->frequencies().getFrame(true) != in->frequencies().getFrame(false)) {
     115    STMath stm(false);
     116    inst = stm.frequencyAlign(in);
     117  }
    106118
    107119  if (format_=="ASCII") {
    108120    STAsciiWriter iw;
     121    // ASCII calls SpectralCoordinate::toWorld so no freqAlign use 'in'
    109122    if (iw.write(*in, filename)) {
    110123      return 0;
     
    117130      iw.setClass(True);
    118131    }
    119     if (iw.write(*in, filename)) {
     132    if (iw.write(*inst, filename)) {
    120133      return 0;
    121134    }
     
    127140  // this is a little different from what I have done
    128141  // before. Need to check with the Offline User Test data
    129   STHeader hdr = in->getHeader();
     142  STHeader hdr = inst->getHeader();
    130143  //const Int nPol  = hdr.npol;
    131144  //const Int nChan = hdr.nchan;
    132   std::vector<uint> ifs = in->getIFNos();
    133   int nIF = in->nif();//ifs.size();
     145  std::vector<uint> ifs = inst->getIFNos();
     146  int nIF = inst->nif();//ifs.size();
    134147  Vector<uInt> nPol(nIF),nChan(nIF);
    135148  Vector<Bool> havexpol(nIF);
    136149  String fluxUnit = hdr.fluxunit;
    137 
     150  fluxUnit.upcase();
    138151  nPol = 0;nChan = 0; havexpol = False;
    139152  for (uint i=0;i<ifs.size();++i) {
    140     nPol(ifs[i]) = in->npol();
    141     nChan(ifs[i]) = in->nchan(ifs[i]);
     153    nPol(ifs[i]) = inst->npol();
     154    nChan(ifs[i]) = inst->nchan(ifs[i]);
    142155    havexpol(ifs[i]) = nPol(ifs[i]) > 2;
    143156  }
    144 
    145   const Table table = in->table();
     157//   Vector<String> obstypes(2);
     158//   obstypes(0) = "TR";//on
     159//   obstypes(1) = "RF TR";//off
     160  const Table table = inst->table();
     161
    146162
    147163  // Create the output file and write static data.
     
    155171    throw(AipsError("Failed to create output file"));
    156172  }
    157 
    158173
    159174  Int count = 0;
     
    206221          String tcalt;
    207222          Vector<String> stmp0, stmp1;
    208           in->frequencies().getEntry(crpix,crval, pksrec.freqInc,
     223          inst->frequencies().getEntry(crpix,crval, pksrec.freqInc,
    209224                                     rec.asuInt("FREQ_ID"));
    210           in->focus().getEntry(pksrec.focusAxi, pksrec.focusTan,
    211                                pksrec.focusRot, tmp0,tmp1,tmp2,tmp3,tmp4,
    212                                rec.asuInt("FOCUS_ID"));
    213           in->molecules().getEntry(pksrec.restFreq,stmp0,stmp1,
     225          inst->focus().getEntry(pksrec.parAngle, pksrec.focusAxi, pksrec.focusTan,
     226                                 pksrec.focusRot, tmp0,tmp1,tmp2,tmp3,tmp4,
     227                                 rec.asuInt("FOCUS_ID"));
     228          inst->molecules().getEntry(pksrec.restFreq,stmp0,stmp1,
    214229                                   rec.asuInt("MOLECULE_ID"));
    215           in->tcal().getEntry(pksrec.tcalTime, pksrec.tcal,
     230          inst->tcal().getEntry(pksrec.tcalTime, pksrec.tcal,
    216231                              rec.asuInt("TCAL_ID"));
    217           in->weather().getEntry(pksrec.temperature, pksrec.pressure,
     232          inst->weather().getEntry(pksrec.temperature, pksrec.pressure,
    218233                                 pksrec.humidity, pksrec.windSpeed,
    219234                                 pksrec.windAz, rec.asuInt("WEATHER_ID"));
     
    230245          pksrec.fieldName = rec.asString("FIELDNAME");
    231246          pksrec.srcName   = rec.asString("SRCNAME");
    232           pksrec.obsType   = hdr.obstype;
     247          //pksrec.obsType   = obstypes[rec.asInt("SRCTYPE")];
     248          pksrec.obsType = getObsTypes( rec.asInt("SRCTYPE") ) ;
    233249          pksrec.bandwidth = nchan * abs(pksrec.freqInc);
    234250          pksrec.azimuth   = rec.asFloat("AZIMUTH");
    235251          pksrec.elevation = rec.asFloat("ELEVATION");
    236           pksrec.parAngle  = rec.asFloat("PARANGLE");
    237252          pksrec.refBeam   = rec.asInt("REFBEAMNO") + 1;
    238253          pksrec.sigma.resize(npol);
     
    293308{
    294309  String poltype = tab.keywordSet().asString("POLTYPE");
    295   if ( poltype == "stokes") {
     310// Full stokes is not supported. Just allow stokes I
     311  if ( poltype == "stokes" && tab.nrow() != 1) {
    296312    String msg = "poltype = " + poltype + " not yet supported in output.";
    297313    throw(AipsError(msg));
     
    340356}
    341357
    342 }
     358// get obsType string from SRCTYPE value
     359String STWriter::getObsTypes( Int srctype )
     360{
     361  String obsType ;
     362  switch( srctype ) {
     363  case Int(SrcType::PSON):
     364    obsType = "PSON" ;
     365    break ;
     366  case Int(SrcType::PSOFF):
     367    obsType = "PSOFF" ;
     368    break ;
     369  case Int(SrcType::NOD):
     370    obsType = "NOD" ;
     371    break ;
     372  case Int(SrcType::FSON):
     373    obsType = "FSON" ;
     374    break ;
     375  case Int(SrcType::FSOFF):
     376    obsType = "FSOFF" ;
     377    break ;
     378  case Int(SrcType::SKY):
     379    obsType = "SKY" ;
     380    break ;
     381  case Int(SrcType::HOT):
     382    obsType = "HOT" ;
     383    break ;
     384  case Int(SrcType::WARM):
     385    obsType = "WARM" ;
     386    break ;
     387  case Int(SrcType::COLD):
     388    obsType = "COLD" ;
     389    break ;
     390  case Int(SrcType::PONCAL):
     391    obsType = "PSON:CALON" ;
     392    break ;
     393  case Int(SrcType::POFFCAL):
     394    obsType = "PSOFF:CALON" ;
     395    break ;
     396  case Int(SrcType::NODCAL):
     397    obsType = "NOD:CALON" ;
     398    break ;
     399  case Int(SrcType::FONCAL):
     400    obsType = "FSON:CALON" ;
     401    break ;
     402  case Int(SrcType::FOFFCAL):
     403    obsType = "FSOFF:CALOFF" ;
     404    break ;
     405  case Int(SrcType::FSLO):
     406    obsType = "FSLO" ;
     407    break ;
     408  case Int(SrcType::FLOOFF):
     409    obsType = "FS:LOWER:OFF" ;
     410    break ;
     411  case Int(SrcType::FLOSKY):
     412    obsType = "FS:LOWER:SKY" ;
     413    break ;
     414  case Int(SrcType::FLOHOT):
     415    obsType = "FS:LOWER:HOT" ;
     416    break ;
     417  case Int(SrcType::FLOWARM):
     418    obsType = "FS:LOWER:WARM" ;
     419    break ;
     420  case Int(SrcType::FLOCOLD):
     421    obsType = "FS:LOWER:COLD" ;
     422    break ;
     423  case Int(SrcType::FSHI):
     424    obsType = "FSHI" ;
     425    break ;
     426  case Int(SrcType::FHIOFF):
     427    obsType = "FS:HIGHER:OFF" ;
     428    break ;
     429  case Int(SrcType::FHISKY):
     430    obsType = "FS:HIGHER:SKY" ;
     431    break ;
     432  case Int(SrcType::FHIHOT):
     433    obsType = "FS:HIGHER:HOT" ;
     434    break ;
     435  case Int(SrcType::FHIWARM):
     436    obsType = "FS:HIGHER:WARM" ;
     437    break ;
     438  case Int(SrcType::FHICOLD):
     439    obsType = "FS:HIGHER:COLD" ;
     440    break ;
     441  default:
     442    obsType = "NOTYPE" ;
     443  }
     444
     445  return obsType ;
     446}
     447
     448}
  • branches/alma/src/STWriter.h

    r1388 r1757  
    3636#include <casa/aips.h>
    3737#include <casa/Utilities/CountedPtr.h>
     38#include <casa/BasicSL/String.h>
    3839
    3940#include "Logger.h"
     
    8485  void replacePtTab(const casa::Table& tab, const std::string& fname);
    8586
     87  casa::String getObsTypes( casa::Int srctype ) ;
     88
    8689  std::string     format_;
    8790  PKSwriter* writer_;
  • branches/alma/src/Scantable.cpp

    r1707 r1757  
    261261  td.addColumn(ScalarColumnDesc<Float>("AZIMUTH"));
    262262  td.addColumn(ScalarColumnDesc<Float>("ELEVATION"));
    263   td.addColumn(ScalarColumnDesc<Float>("PARANGLE"));
    264263  td.addColumn(ScalarColumnDesc<Float>("OPACITY"));
    265264
     
    303302  elCol_.attach(table_, "ELEVATION");
    304303  dirCol_.attach(table_, "DIRECTION");
    305   paraCol_.attach(table_, "PARANGLE");
    306304  fldnCol_.attach(table_, "FIELDNAME");
    307305  rbeamCol_.attach(table_, "REFBEAMNO");
    308306
     307  mweatheridCol_.attach(table_,"WEATHER_ID");
    309308  mfitidCol_.attach(table_,"FIT_ID");
    310309  mfreqidCol_.attach(table_, "FREQ_ID");
     
    501500}
    502501
    503 MPosition Scantable::getAntennaPosition () const
     502MPosition Scantable::getAntennaPosition() const
    504503{
    505504  Vector<Double> antpos;
     
    515514  /// @todo reindex SCANNO, recompute nbeam, nif, npol
    516515  inname = path.expandedName();
    517   table_.deepCopy(inname, Table::New);
     516  // WORKAROUND !!! for Table bug
     517  // Remove when fixed in casacore
     518  if ( table_.tableType() == Table::Memory  && !selector_.empty() ) {
     519    Table tab = table_.copyToMemoryTable(generateName());
     520    tab.deepCopy(inname, Table::New);
     521    tab.markForDelete();
     522
     523  } else {
     524    table_.deepCopy(inname, Table::New);
     525  }
    518526}
    519527
     
    646654}
    647655
    648 std::vector<uint> Scantable::getNumbers(ScalarColumn<uInt>& col)
     656std::vector<uint> Scantable::getNumbers(const ScalarColumn<uInt>& col) const
    649657{
    650658  Vector<uInt> nos(col.getColumn());
     
    840848    specCol_.get(whichrow, arr);
    841849  } else {
    842     CountedPtr<STPol> stpol(STPol::getPolClass(Scantable::factories_, basetype));
     850    CountedPtr<STPol> stpol(STPol::getPolClass(Scantable::factories_,
     851                                               basetype));
    843852    uInt row = uInt(whichrow);
    844853    stpol->setSpectra(getPolMatrix(row));
    845854    Float fang,fhand,parang;
    846     fang = focusTable_.getTotalFeedAngle(mfocusidCol_(row));
     855    fang = focusTable_.getTotalAngle(mfocusidCol_(row));
    847856    fhand = focusTable_.getFeedHand(mfocusidCol_(row));
    848     parang = paraCol_(row);
    849     /// @todo re-enable this
    850     // disable total feed angle to support paralactifying Caswell style
    851     stpol->setPhaseCorrections(parang, -parang, fhand);
     857    stpol->setPhaseCorrections(fang, fhand);
    852858    arr = stpol->getSpectrum(requestedpol, ptype);
    853859  }
     
    921927      << setw(15) << "Polarisations:" << setw(4) << npol()
    922928      << "(" << getPolType() << ")" << endl
    923       << setw(15) << "Channels:"  << setw(4) << nchan() << endl;
    924   oss << endl;
     929      << setw(15) << "Channels:" << nchan() << endl;
    925930  String tmp;
    926931  oss << setw(15) << "Observer:"
     
    967972      << setw(10) << "Time" << setw(18) << "Integration" << endl;
    968973  oss << setw(5) << "" << setw(5) << "Beam" << setw(3) << "" << dirtype << endl;
    969   oss << setw(10) << "" << setw(3) << "IF" << setw(6) << ""
     974  oss << setw(10) << "" << setw(3) << "IF" << setw(3) << ""
    970975      << setw(8) << "Frame" << setw(16)
    971       << "RefVal" << setw(10) << "RefPix" << setw(12) << "Increment" <<endl;
     976      << "RefVal" << setw(10) << "RefPix" << setw(12) << "Increment"
     977      << setw(7) << "Channels"
     978      << endl;
    972979  oss << asap::SEPERATOR << endl;
    973980  TableIterator iter(table_, "SCANNO");
     
    10041011        ROTableRow irow(isubt);
    10051012        const TableRecord& irec = irow.get(0);
    1006         oss << setw(10) << "";
     1013        oss << setw(9) << "";
    10071014        oss << setw(3) << std::right << irec.asuInt("IFNO") << std::left
    1008             << setw(2) << "" << frequencies().print(irec.asuInt("FREQ_ID"))
     1015            << setw(1) << "" << frequencies().print(irec.asuInt("FREQ_ID"))
     1016            << setw(3) << "" << nchan(irec.asuInt("IFNO"))
    10091017            << endl;
    10101018
     
    10401048    Double tm;
    10411049    table_.keywordSet().get("UTC",tm);
    1042     return MEpoch(MVEpoch(tm)); 
     1050    return MEpoch(MVEpoch(tm));
    10431051  }
    10441052}
     
    10471055{
    10481056  return formatDirection(getDirection(uInt(whichrow)));
     1057}
     1058
     1059
     1060SpectralCoordinate Scantable::getSpectralCoordinate(int whichrow) const {
     1061  const MPosition& mp = getAntennaPosition();
     1062  const MDirection& md = getDirection(whichrow);
     1063  const MEpoch& me = timeCol_(whichrow);
     1064  //Double rf = moleculeTable_.getRestFrequency(mmolidCol_(whichrow));
     1065  Vector<Double> rf = moleculeTable_.getRestFrequency(mmolidCol_(whichrow));
     1066  return freqTable_.getSpectralCoordinate(md, mp, me, rf,
     1067                                          mfreqidCol_(whichrow));
    10491068}
    10501069
     
    10611080    return stlout;
    10621081  }
    1063 
    1064   const MPosition& mp = getAntennaPosition();
    1065   const MDirection& md = getDirection(whichrow);
    1066   const MEpoch& me = timeCol_(whichrow);
    1067   //Double rf = moleculeTable_.getRestFrequency(mmolidCol_(whichrow));
    1068   Vector<Double> rf = moleculeTable_.getRestFrequency(mmolidCol_(whichrow));
    1069   SpectralCoordinate spc =
    1070     freqTable_.getSpectralCoordinate(md, mp, me, rf, mfreqidCol_(whichrow));
     1082  SpectralCoordinate spc = getSpectralCoordinate(whichrow);
    10711083  Vector<Double> pixel(nchan);
    10721084  Vector<Double> world;
     
    12251237           Sort::QuickSort|Sort::NoDuplicates );
    12261238  for (uInt i=0; i<fids.nelements(); ++i) {
    1227     frequencies().shiftRefPix(npix, i);
    1228   }
    1229 }
    1230 
    1231 std::string asap::Scantable::getAntennaName() const
     1239    frequencies().shiftRefPix(npix, fids[i]);
     1240  }
     1241}
     1242
     1243std::string Scantable::getAntennaName() const
    12321244{
    12331245  String out;
     
    12361248}
    12371249
    1238 int asap::Scantable::checkScanInfo(const std::vector<int>& scanlist) const
     1250int Scantable::checkScanInfo(const std::vector<int>& scanlist) const
    12391251{
    12401252  String tbpath;
     
    13211333}
    13221334
    1323 std::vector<double>  asap::Scantable::getDirectionVector(int whichrow) const
     1335std::vector<double> Scantable::getDirectionVector(int whichrow) const
    13241336{
    13251337  Vector<Double> Dir = dirCol_(whichrow).getAngle("rad").getValue();
     
    16811693}
    16821694
     1695std::vector<float> Scantable::getWeather(int whichrow) const
     1696{
     1697  std::vector<float> out(5);
     1698  //Float temperature, pressure, humidity, windspeed, windaz;
     1699  weatherTable_.getEntry(out[0], out[1], out[2], out[3], out[4],
     1700                         mweatheridCol_(uInt(whichrow)));
     1701
     1702
     1703  return out;
     1704}
     1705
    16831706}
    16841707//namespace asap
  • branches/alma/src/Scantable.h

    r1707 r1757  
    2222#include <casa/Utilities/CountedPtr.h>
    2323
    24 #include <casa/Exceptions/Error.h>
    25 
    26 #include <coordinates/Coordinates/SpectralCoordinate.h>
    27 
    2824#include <tables/Tables/Table.h>
    2925#include <tables/Tables/ArrayColumn.h>
     
    3228#include <measures/TableMeasures/ScalarMeasColumn.h>
    3329
     30#include <coordinates/Coordinates/SpectralCoordinate.h>
     31
    3432#include <casa/Arrays/Vector.h>
    3533#include <casa/Quanta/Quantum.h>
     34
     35#include <casa/Exceptions/Error.h>
    3636
    3737#include "Logger.h"
     
    173173   */
    174174  casa::MDirection getDirection( int whichrow ) const;
    175  
     175
    176176  /**
    177177   * get the direction type as a string, e.g. "J2000"
     
    191191   * @return a string describing the direction reference
    192192   */
    193   std::string getDirectionRefString() const;   
     193  std::string getDirectionRefString() const;
    194194
    195195  /**
     
    298298
    299299  int getBeam(int whichrow) const;
    300   std::vector<uint> getBeamNos() { return getNumbers(beamCol_); }
     300  std::vector<uint> getBeamNos() const { return getNumbers(beamCol_); }
    301301
    302302  int getIF(int whichrow) const;
    303   std::vector<uint> getIFNos() { return getNumbers(ifCol_); }
     303  std::vector<uint> getIFNos() const { return getNumbers(ifCol_); }
    304304
    305305  int getPol(int whichrow) const;
    306   std::vector<uint> getPolNos() { return getNumbers(polCol_); }
    307 
    308   std::vector<uint> getScanNos() { return getNumbers(scanCol_); }
     306  std::vector<uint> getPolNos() const { return getNumbers(polCol_); }
     307
     308  std::vector<uint> getScanNos() const { return getNumbers(scanCol_); }
    309309  int getScan(int whichrow) const { return scanCol_(whichrow); }
    310310
     
    335335    { return azCol_(whichrow); }
    336336  float getParAngle(int whichrow) const
    337     { return paraCol_(whichrow); }
     337    { return focus().getParAngle(mfocusidCol_(whichrow)); }
    338338  int getTcalId(int whichrow) const
    339339    { return mtcalidCol_(whichrow); }
     
    384384
    385385  std::vector<double> getAbcissa(int whichrow) const;
     386
     387  std::vector<float> getWeather(int whichrow) const;
    386388
    387389  std::string getAbcissaLabel(int whichrow) const;
     
    408410
    409411  void shift(int npix);
     412
     413  casa::SpectralCoordinate getSpectralCoordinate(int whichrow) const;
    410414
    411415  void convertDirection(const std::string& newframe);
     
    443447   * against the information found in GBT_GO table for
    444448   * scan number orders to get correct pairs.
    445    * @param[in] scan list 
    446    * @return status 
     449   * @param[in] scan list
     450   * @return status
    447451   */
    448452  int checkScanInfo(const std::vector<int>& scanlist) const;
    449453
    450454  /**
    451    * Get the direction as a vector, for a specific row 
     455   * Get the direction as a vector, for a specific row
    452456   * @param[in] whichrow the row numbyyer
    453    * @return the direction in a vector 
     457   * @return the direction in a vector
    454458   */
    455459  std::vector<double> getDirectionVector(int whichrow) const;
     460
     461  /**
     462   * Set a flag indicating whether the data was parallactified
     463   * @param[in] flag true or false
     464   */
     465  void parallactify(bool flag)
     466    { focus().setParallactify(flag); }
    456467
    457468  /**
     
    523534  int rowToScanIndex(int therow);
    524535
    525   std::vector<uint> getNumbers(casa::ScalarColumn<casa::uInt>& col);
    526 
    527   static const casa::uInt version_ = 2;
     536  std::vector<uint> getNumbers(const casa::ScalarColumn<casa::uInt>& col) const;
     537
     538  static const casa::uInt version_ = 3;
    528539
    529540  STSelector selector_;
     
    549560  casa::ScalarColumn<casa::Float> azCol_;
    550561  casa::ScalarColumn<casa::Float> elCol_;
    551   casa::ScalarColumn<casa::Float> paraCol_;
    552562  casa::ScalarColumn<casa::String> srcnCol_, fldnCol_;
    553563  casa::ScalarColumn<casa::uInt> scanCol_, beamCol_, ifCol_, polCol_, cycleCol_, flagrowCol_;
  • branches/alma/src/ScantableWrapper.h

    r1707 r1757  
    2020#include "STFit.h"
    2121#include "Scantable.h"
     22#include "STCoordinate.h"
    2223
    2324namespace asap {
     
    233234    { return table_->checkScanInfo(scanlist); }
    234235 
    235   std::vector<double>  getDirectionVector(int whichrow) const
     236  std::vector<double> getDirectionVector(int whichrow) const
    236237    { return table_->getDirectionVector(whichrow); }
     238
     239  void parallactify(bool flag)
     240    { table_->parallactify(flag); }
     241
     242  STCoordinate getCoordinate(int row) {
     243    return STCoordinate(table_->getSpectralCoordinate(row));
     244  }
     245
     246  std::vector<float> getWeather(int whichrow) const
     247    { return table_->getWeather(whichrow); }
    237248
    238249  void reshapeSpectrum( int nmin, int nmax )
  • branches/alma/src/python_Scantable.cpp

    r1707 r1757  
    133133    .def("_setsourcetype", &ScantableWrapper::setSourceType)
    134134    .def("_getdirectionvec", &ScantableWrapper::getDirectionVector)
     135    .def("_parallactify", &ScantableWrapper::parallactify)
     136    .def("get_coordinate", &ScantableWrapper::getCoordinate)
     137    .def("_get_weather", &ScantableWrapper::getWeather)
    135138    .def("_reshape", &ScantableWrapper::reshapeSpectrum,
    136139         (boost::python::arg("nmin")=-1,
  • branches/alma/src/python_asap.cpp

    r1693 r1757  
    7575  asap::python::python_LineCatalog();
    7676  asap::python::python_Logger();
     77  asap::python::python_STCoordinate();
     78  asap::python::python_STAtmosphere();
    7779  asap::python::python_SrcType();
    7880
  • branches/alma/src/python_asap.h

    r1693 r1757  
    4747    void python_LineCatalog();
    4848    void python_Logger();
     49    void python_STCoordinate();
     50    void python_STAtmosphere();
    4951    void python_SrcType();
    5052
  • branches/alma/test

    • Property svn:ignore set to
      .asaprc
  • branches/alma/test/file-io.py

    r1267 r1757  
    1717
    1818data.save('output/test.asap',overwrite=True)
    19 data.save('output/test.ascii',format='ASCII',overwrite=True)
     19data.save('output/testascii',format='ASCII',overwrite=True)
    2020data.save('output/test.sdfits',format='SDFITS',overwrite=True)
     21data.save('output/testfits',format='FITS',overwrite=True)
     22data.save('output/testclass',format='CLASS',overwrite=True)
    2123
    2224data2 = scantable('output/test.sdfits')
  • branches/alma/test/parkes-pol.py

    r1038 r1757  
    4747plotter.set_range(-30,0)
    4848selection.reset()
     49plotter.plot(plotscans)
    4950selection.set_polarisations(['I','Q', 'U', 'V'])
    5051plotter.set_selection(selection)
     52plotter.save('output/parkes_iquv.png',dpi=80)
    5153selection.set_polarisations(['I','Plinear'])
    5254plotter.set_selection(selection)
     55plotter.save('output/parkes_iplin.png',dpi=80)
    5356selection.set_polarisations(['RR','LL'])
    5457plotter.set_selection(selection)
    55 plotter.plot(plotscans)
    5658plotter.save('output/parkes_rrll.png',dpi=80)
    5759
  • branches/alma/web/index.html

    r1379 r1757  
    4848<h2>Current Release</h2>
    4949<b class="asap">ASAP</b> latest stable version 2.2 was released on May, 2<sup>nd</sup> 2007. It can be obtained in the <a href="#download">Download</a> section.
     50
     51<div style="color: red;">
     52  Note: Due to a bug in this release, Mopra users should follow <a href="https://svn.atnf.csiro.au/trac/asap/wiki/AsapFaq" >these</a> instructions.
     53</div>
     54 
    5055
    5156<h2>Screenshots</h2>
     
    118123  <li><b class="asap">ASAP</b> source code is available through our subversion repository
    119124    <pre>
    120         svn co http://sourcecode.atnf.csiro.au/repos/asap/tags/asap2.2.0
     125        svn co http://svn.atnf.csiro.au/asap/tags/asap2.2.0
    121126    </pre>
    122127  </li>
Note: See TracChangeset for help on using the changeset viewer.