Revision: 21587
Author: gervandiepen
Date: Wed Mar 25 14:33:54 2015 UTC
Log: Split MS into MS, MSSel, and MSOper
https://code.google.com/p/casacore/source/detail?r=21587
Added:
/branches/nov14/ms/MSOper
/branches/nov14/ms/MSOper/MS1ToMS2Converter.cc
/branches/nov14/ms/MSOper/MS1ToMS2Converter.h
/branches/nov14/ms/MSOper/MSConcat.cc
/branches/nov14/ms/MSOper/MSConcat.h
/branches/nov14/ms/MSOper/MSDerivedValues.cc
/branches/nov14/ms/MSOper/MSDerivedValues.h
/branches/nov14/ms/MSOper/MSFlagger.cc
/branches/nov14/ms/MSOper/MSFlagger.h
/branches/nov14/ms/MSOper/MSKeys.cc
/branches/nov14/ms/MSOper/MSKeys.h
/branches/nov14/ms/MSOper/MSLister.cc
/branches/nov14/ms/MSOper/MSLister.h
/branches/nov14/ms/MSOper/MSMetaData.cc
/branches/nov14/ms/MSOper/MSMetaData.h
/branches/nov14/ms/MSOper/MSReader.cc
/branches/nov14/ms/MSOper/MSReader.h
/branches/nov14/ms/MSOper/MSSummary.cc
/branches/nov14/ms/MSOper/MSSummary.h
/branches/nov14/ms/MSOper/MSValidIds.cc
/branches/nov14/ms/MSOper/MSValidIds.h
/branches/nov14/ms/MSOper/NewMSSimulator.cc
/branches/nov14/ms/MSOper/NewMSSimulator.h
/branches/nov14/ms/MSOper/test
/branches/nov14/ms/MSOper/test/CMakeLists.txt
/branches/nov14/ms/MSOper/test/tMSDerivedValues.cc
/branches/nov14/ms/MSOper/test/tMSMetaData.cc
/branches/nov14/ms/MSOper/test/tMSMetaData.run
/branches/nov14/ms/MSOper/test/tMSReader.cc
/branches/nov14/ms/MSOper/test/tMSReader.run
/branches/nov14/ms/MSOper/test/tMSSummary.cc
/branches/nov14/ms/MSOper.h
/branches/nov14/ms/MSSel
/branches/nov14/ms/MSSel/MSAntennaGram.cc
/branches/nov14/ms/MSSel/MSAntennaGram.h
/branches/nov14/ms/MSSel/MSAntennaGram.ll
/branches/nov14/ms/MSSel/MSAntennaGram.yy
/branches/nov14/ms/MSSel/MSAntennaIndex.cc
/branches/nov14/ms/MSSel/MSAntennaIndex.h
/branches/nov14/ms/MSSel/MSAntennaParse.cc
/branches/nov14/ms/MSSel/MSAntennaParse.h
/branches/nov14/ms/MSSel/MSArrayGram.cc
/branches/nov14/ms/MSSel/MSArrayGram.h
/branches/nov14/ms/MSSel/MSArrayGram.ll
/branches/nov14/ms/MSSel/MSArrayGram.yy
/branches/nov14/ms/MSSel/MSArrayParse.cc
/branches/nov14/ms/MSSel/MSArrayParse.h
/branches/nov14/ms/MSSel/MSCorrGram.cc
/branches/nov14/ms/MSSel/MSCorrGram.h
/branches/nov14/ms/MSSel/MSCorrGram.ll
/branches/nov14/ms/MSSel/MSCorrGram.yy
/branches/nov14/ms/MSSel/MSCorrParse.cc
/branches/nov14/ms/MSSel/MSCorrParse.h
/branches/nov14/ms/MSSel/MSDataDescIndex.cc
/branches/nov14/ms/MSSel/MSDataDescIndex.h
/branches/nov14/ms/MSSel/MSDopplerIndex.cc
/branches/nov14/ms/MSSel/MSDopplerIndex.h
/branches/nov14/ms/MSSel/MSFeedIndex.cc
/branches/nov14/ms/MSSel/MSFeedIndex.h
/branches/nov14/ms/MSSel/MSFieldGram.cc
/branches/nov14/ms/MSSel/MSFieldGram.h
/branches/nov14/ms/MSSel/MSFieldGram.ll
/branches/nov14/ms/MSSel/MSFieldGram.yy
/branches/nov14/ms/MSSel/MSFieldIndex.cc
/branches/nov14/ms/MSSel/MSFieldIndex.h
/branches/nov14/ms/MSSel/MSFieldParse.cc
/branches/nov14/ms/MSSel/MSFieldParse.h
/branches/nov14/ms/MSSel/MSFreqOffIndex.cc
/branches/nov14/ms/MSSel/MSFreqOffIndex.h
/branches/nov14/ms/MSSel/MSObsIndex.cc
/branches/nov14/ms/MSSel/MSObsIndex.h
/branches/nov14/ms/MSSel/MSObservationGram.cc
/branches/nov14/ms/MSSel/MSObservationGram.h
/branches/nov14/ms/MSSel/MSObservationGram.ll
/branches/nov14/ms/MSSel/MSObservationGram.yy
/branches/nov14/ms/MSSel/MSObservationParse.cc
/branches/nov14/ms/MSSel/MSObservationParse.h
/branches/nov14/ms/MSSel/MSParse.cc
/branches/nov14/ms/MSSel/MSParse.h
/branches/nov14/ms/MSSel/MSPointingIndex.cc
/branches/nov14/ms/MSSel/MSPointingIndex.h
/branches/nov14/ms/MSSel/MSPolIndex.cc
/branches/nov14/ms/MSSel/MSPolIndex.h
/branches/nov14/ms/MSSel/MSPolnGram.cc
/branches/nov14/ms/MSSel/MSPolnGram.h
/branches/nov14/ms/MSSel/MSPolnParse.cc
/branches/nov14/ms/MSSel/MSPolnParse.h
/branches/nov14/ms/MSSel/MSScanGram.cc
/branches/nov14/ms/MSSel/MSScanGram.h
/branches/nov14/ms/MSSel/MSScanGram.ll
/branches/nov14/ms/MSSel/MSScanGram.yy
/branches/nov14/ms/MSSel/MSScanParse.cc
/branches/nov14/ms/MSSel/MSScanParse.h
/branches/nov14/ms/MSSel/MSSelUtil.h
/branches/nov14/ms/MSSel/MSSelUtil.tcc
/branches/nov14/ms/MSSel/MSSelUtil2.h
/branches/nov14/ms/MSSel/MSSelUtil2.tcc
/branches/nov14/ms/MSSel/MSSelectableMainColumn.h
/branches/nov14/ms/MSSel/MSSelectableTable.cc
/branches/nov14/ms/MSSel/MSSelectableTable.h
/branches/nov14/ms/MSSel/MSSelection.cc
/branches/nov14/ms/MSSel/MSSelection.h
/branches/nov14/ms/MSSel/MSSelectionError.cc
/branches/nov14/ms/MSSel/MSSelectionError.h
/branches/nov14/ms/MSSel/MSSelectionErrorHandler.cc
/branches/nov14/ms/MSSel/MSSelectionErrorHandler.h
/branches/nov14/ms/MSSel/MSSelectionKeywords.cc
/branches/nov14/ms/MSSel/MSSelectionKeywords.h
/branches/nov14/ms/MSSel/MSSelectionTools.cc
/branches/nov14/ms/MSSel/MSSelectionTools.h
/branches/nov14/ms/MSSel/MSSelector.cc
/branches/nov14/ms/MSSel/MSSelector.h
/branches/nov14/ms/MSSel/MSSourceIndex.cc
/branches/nov14/ms/MSSel/MSSourceIndex.h
/branches/nov14/ms/MSSel/MSSpWindowIndex.cc
/branches/nov14/ms/MSSel/MSSpWindowIndex.h
/branches/nov14/ms/MSSel/MSSpwGram.cc
/branches/nov14/ms/MSSel/MSSpwGram.h
/branches/nov14/ms/MSSel/MSSpwGram.ll
/branches/nov14/ms/MSSel/MSSpwGram.yy
/branches/nov14/ms/MSSel/MSSpwIndex.cc
/branches/nov14/ms/MSSel/MSSpwIndex.h
/branches/nov14/ms/MSSel/MSSpwParse.cc
/branches/nov14/ms/MSSel/MSSpwParse.h
/branches/nov14/ms/MSSel/MSStateGram.cc
/branches/nov14/ms/MSSel/MSStateGram.h
/branches/nov14/ms/MSSel/MSStateGram.ll
/branches/nov14/ms/MSSel/MSStateGram.yy
/branches/nov14/ms/MSSel/MSStateIndex.cc
/branches/nov14/ms/MSSel/MSStateIndex.h
/branches/nov14/ms/MSSel/MSStateParse.cc
/branches/nov14/ms/MSSel/MSStateParse.h
/branches/nov14/ms/MSSel/MSSysCalIndex.cc
/branches/nov14/ms/MSSel/MSSysCalIndex.h
/branches/nov14/ms/MSSel/MSTableIndex.cc
/branches/nov14/ms/MSSel/MSTableIndex.h
/branches/nov14/ms/MSSel/MSTimeDefinitions.h
/branches/nov14/ms/MSSel/MSTimeGram.cc
/branches/nov14/ms/MSSel/MSTimeGram.h
/branches/nov14/ms/MSSel/MSTimeGram.ll
/branches/nov14/ms/MSSel/MSTimeGram.yy
/branches/nov14/ms/MSSel/MSTimeParse.cc
/branches/nov14/ms/MSSel/MSTimeParse.h
/branches/nov14/ms/MSSel/MSUvDistGram.cc
/branches/nov14/ms/MSSel/MSUvDistGram.h
/branches/nov14/ms/MSSel/MSUvDistGram.ll
/branches/nov14/ms/MSSel/MSUvDistGram.yy
/branches/nov14/ms/MSSel/MSUvDistParse.cc
/branches/nov14/ms/MSSel/MSUvDistParse.h
/branches/nov14/ms/MSSel/MSWeatherIndex.cc
/branches/nov14/ms/MSSel/MSWeatherIndex.h
/branches/nov14/ms/MSSel/test
/branches/nov14/ms/MSSel/test/CMakeLists.txt
/branches/nov14/ms/MSSel/test/tMSAntennaGram.cc
/branches/nov14/ms/MSSel/test/tMSAntennaGram.run
/branches/nov14/ms/MSSel/test/tMSAntennaGram2.cc
/branches/nov14/ms/MSSel/test/tMSAntennaGram2.run
/branches/nov14/ms/MSSel/test/tMSAntennaGram3.cc
/branches/nov14/ms/MSSel/test/tMSAntennaGram3.out
/branches/nov14/ms/MSSel/test/tMSCorrGram.cc
/branches/nov14/ms/MSSel/test/tMSCorrGram.run
/branches/nov14/ms/MSSel/test/tMSFieldGram.cc
/branches/nov14/ms/MSSel/test/tMSFieldGram.run
/branches/nov14/ms/MSSel/test/tMSScanGram.cc
/branches/nov14/ms/MSSel/test/tMSScanGram.run
/branches/nov14/ms/MSSel/test/tMSSpwGram.cc
/branches/nov14/ms/MSSel/test/tMSSpwGram.run
/branches/nov14/ms/MSSel/test/tMSTimeGram.cc
/branches/nov14/ms/MSSel/test/tMSTimeGram.run
/branches/nov14/ms/MSSel/test/tMSUvDistGram.cc
/branches/nov14/ms/MSSel/test/tMSUvDistGram.run
/branches/nov14/ms/MSSel.h
Deleted:
/branches/nov14/ms/MeasurementSets/MS1ToMS2Converter.cc
/branches/nov14/ms/MeasurementSets/MS1ToMS2Converter.h
/branches/nov14/ms/MeasurementSets/MSAntennaGram.cc
/branches/nov14/ms/MeasurementSets/MSAntennaGram.h
/branches/nov14/ms/MeasurementSets/MSAntennaGram.ll
/branches/nov14/ms/MeasurementSets/MSAntennaGram.yy
/branches/nov14/ms/MeasurementSets/MSAntennaIndex.cc
/branches/nov14/ms/MeasurementSets/MSAntennaIndex.h
/branches/nov14/ms/MeasurementSets/MSAntennaParse.cc
/branches/nov14/ms/MeasurementSets/MSAntennaParse.h
/branches/nov14/ms/MeasurementSets/MSArrayGram.cc
/branches/nov14/ms/MeasurementSets/MSArrayGram.h
/branches/nov14/ms/MeasurementSets/MSArrayGram.ll
/branches/nov14/ms/MeasurementSets/MSArrayGram.yy
/branches/nov14/ms/MeasurementSets/MSArrayParse.cc
/branches/nov14/ms/MeasurementSets/MSArrayParse.h
/branches/nov14/ms/MeasurementSets/MSConcat.cc
/branches/nov14/ms/MeasurementSets/MSConcat.h
/branches/nov14/ms/MeasurementSets/MSCorrGram.cc
/branches/nov14/ms/MeasurementSets/MSCorrGram.h
/branches/nov14/ms/MeasurementSets/MSCorrGram.ll
/branches/nov14/ms/MeasurementSets/MSCorrGram.yy
/branches/nov14/ms/MeasurementSets/MSCorrParse.cc
/branches/nov14/ms/MeasurementSets/MSCorrParse.h
/branches/nov14/ms/MeasurementSets/MSDataDescIndex.cc
/branches/nov14/ms/MeasurementSets/MSDataDescIndex.h
/branches/nov14/ms/MeasurementSets/MSDerivedValues.cc
/branches/nov14/ms/MeasurementSets/MSDerivedValues.h
/branches/nov14/ms/MeasurementSets/MSDopplerIndex.cc
/branches/nov14/ms/MeasurementSets/MSDopplerIndex.h
/branches/nov14/ms/MeasurementSets/MSFeedIndex.cc
/branches/nov14/ms/MeasurementSets/MSFeedIndex.h
/branches/nov14/ms/MeasurementSets/MSFieldGram.cc
/branches/nov14/ms/MeasurementSets/MSFieldGram.h
/branches/nov14/ms/MeasurementSets/MSFieldGram.ll
/branches/nov14/ms/MeasurementSets/MSFieldGram.yy
/branches/nov14/ms/MeasurementSets/MSFieldIndex.cc
/branches/nov14/ms/MeasurementSets/MSFieldIndex.h
/branches/nov14/ms/MeasurementSets/MSFieldParse.cc
/branches/nov14/ms/MeasurementSets/MSFieldParse.h
/branches/nov14/ms/MeasurementSets/MSFlagger.cc
/branches/nov14/ms/MeasurementSets/MSFlagger.h
/branches/nov14/ms/MeasurementSets/MSFreqOffIndex.cc
/branches/nov14/ms/MeasurementSets/MSFreqOffIndex.h
/branches/nov14/ms/MeasurementSets/MSKeys.cc
/branches/nov14/ms/MeasurementSets/MSKeys.h
/branches/nov14/ms/MeasurementSets/MSLister.cc
/branches/nov14/ms/MeasurementSets/MSLister.h
/branches/nov14/ms/MeasurementSets/MSMetaData.cc
/branches/nov14/ms/MeasurementSets/MSMetaData.h
/branches/nov14/ms/MeasurementSets/MSObsIndex.cc
/branches/nov14/ms/MeasurementSets/MSObsIndex.h
/branches/nov14/ms/MeasurementSets/MSObservationGram.cc
/branches/nov14/ms/MeasurementSets/MSObservationGram.h
/branches/nov14/ms/MeasurementSets/MSObservationGram.ll
/branches/nov14/ms/MeasurementSets/MSObservationGram.yy
/branches/nov14/ms/MeasurementSets/MSObservationParse.cc
/branches/nov14/ms/MeasurementSets/MSObservationParse.h
/branches/nov14/ms/MeasurementSets/MSParse.cc
/branches/nov14/ms/MeasurementSets/MSParse.h
/branches/nov14/ms/MeasurementSets/MSPointingIndex.cc
/branches/nov14/ms/MeasurementSets/MSPointingIndex.h
/branches/nov14/ms/MeasurementSets/MSPolIndex.cc
/branches/nov14/ms/MeasurementSets/MSPolIndex.h
/branches/nov14/ms/MeasurementSets/MSPolnGram.cc
/branches/nov14/ms/MeasurementSets/MSPolnGram.h
/branches/nov14/ms/MeasurementSets/MSPolnParse.cc
/branches/nov14/ms/MeasurementSets/MSPolnParse.h
/branches/nov14/ms/MeasurementSets/MSReader.cc
/branches/nov14/ms/MeasurementSets/MSReader.h
/branches/nov14/ms/MeasurementSets/MSScanGram.cc
/branches/nov14/ms/MeasurementSets/MSScanGram.h
/branches/nov14/ms/MeasurementSets/MSScanGram.ll
/branches/nov14/ms/MeasurementSets/MSScanGram.yy
/branches/nov14/ms/MeasurementSets/MSScanParse.cc
/branches/nov14/ms/MeasurementSets/MSScanParse.h
/branches/nov14/ms/MeasurementSets/MSSelUtil.h
/branches/nov14/ms/MeasurementSets/MSSelUtil.tcc
/branches/nov14/ms/MeasurementSets/MSSelUtil2.h
/branches/nov14/ms/MeasurementSets/MSSelUtil2.tcc
/branches/nov14/ms/MeasurementSets/MSSelectableMainColumn.h
/branches/nov14/ms/MeasurementSets/MSSelectableTable.cc
/branches/nov14/ms/MeasurementSets/MSSelectableTable.h
/branches/nov14/ms/MeasurementSets/MSSelection.cc
/branches/nov14/ms/MeasurementSets/MSSelection.h
/branches/nov14/ms/MeasurementSets/MSSelectionError.cc
/branches/nov14/ms/MeasurementSets/MSSelectionError.h
/branches/nov14/ms/MeasurementSets/MSSelectionErrorHandler.cc
/branches/nov14/ms/MeasurementSets/MSSelectionErrorHandler.h
/branches/nov14/ms/MeasurementSets/MSSelectionKeywords.cc
/branches/nov14/ms/MeasurementSets/MSSelectionKeywords.h
/branches/nov14/ms/MeasurementSets/MSSelectionTools.cc
/branches/nov14/ms/MeasurementSets/MSSelectionTools.h
/branches/nov14/ms/MeasurementSets/MSSelector.cc
/branches/nov14/ms/MeasurementSets/MSSelector.h
/branches/nov14/ms/MeasurementSets/MSSourceIndex.cc
/branches/nov14/ms/MeasurementSets/MSSourceIndex.h
/branches/nov14/ms/MeasurementSets/MSSpWindowIndex.cc
/branches/nov14/ms/MeasurementSets/MSSpWindowIndex.h
/branches/nov14/ms/MeasurementSets/MSSpwGram.cc
/branches/nov14/ms/MeasurementSets/MSSpwGram.h
/branches/nov14/ms/MeasurementSets/MSSpwGram.ll
/branches/nov14/ms/MeasurementSets/MSSpwGram.yy
/branches/nov14/ms/MeasurementSets/MSSpwIndex.cc
/branches/nov14/ms/MeasurementSets/MSSpwIndex.h
/branches/nov14/ms/MeasurementSets/MSSpwParse.cc
/branches/nov14/ms/MeasurementSets/MSSpwParse.h
/branches/nov14/ms/MeasurementSets/MSStateGram.cc
/branches/nov14/ms/MeasurementSets/MSStateGram.h
/branches/nov14/ms/MeasurementSets/MSStateGram.ll
/branches/nov14/ms/MeasurementSets/MSStateGram.yy
/branches/nov14/ms/MeasurementSets/MSStateIndex.cc
/branches/nov14/ms/MeasurementSets/MSStateIndex.h
/branches/nov14/ms/MeasurementSets/MSStateParse.cc
/branches/nov14/ms/MeasurementSets/MSStateParse.h
/branches/nov14/ms/MeasurementSets/MSSummary.cc
/branches/nov14/ms/MeasurementSets/MSSummary.h
/branches/nov14/ms/MeasurementSets/MSSysCalIndex.cc
/branches/nov14/ms/MeasurementSets/MSSysCalIndex.h
/branches/nov14/ms/MeasurementSets/MSTableIndex.cc
/branches/nov14/ms/MeasurementSets/MSTableIndex.h
/branches/nov14/ms/MeasurementSets/MSTimeDefinitions.h
/branches/nov14/ms/MeasurementSets/MSTimeGram.cc
/branches/nov14/ms/MeasurementSets/MSTimeGram.h
/branches/nov14/ms/MeasurementSets/MSTimeGram.ll
/branches/nov14/ms/MeasurementSets/MSTimeGram.yy
/branches/nov14/ms/MeasurementSets/MSTimeParse.cc
/branches/nov14/ms/MeasurementSets/MSTimeParse.h
/branches/nov14/ms/MeasurementSets/MSUvDistGram.cc
/branches/nov14/ms/MeasurementSets/MSUvDistGram.h
/branches/nov14/ms/MeasurementSets/MSUvDistGram.ll
/branches/nov14/ms/MeasurementSets/MSUvDistGram.yy
/branches/nov14/ms/MeasurementSets/MSUvDistParse.cc
/branches/nov14/ms/MeasurementSets/MSUvDistParse.h
/branches/nov14/ms/MeasurementSets/MSValidIds.cc
/branches/nov14/ms/MeasurementSets/MSValidIds.h
/branches/nov14/ms/MeasurementSets/MSWeatherIndex.cc
/branches/nov14/ms/MeasurementSets/MSWeatherIndex.h
/branches/nov14/ms/MeasurementSets/NewMSSimulator.cc
/branches/nov14/ms/MeasurementSets/NewMSSimulator.h
/branches/nov14/ms/MeasurementSets/test/tMSAntennaGram.cc
/branches/nov14/ms/MeasurementSets/test/tMSAntennaGram.run
/branches/nov14/ms/MeasurementSets/test/tMSAntennaGram2.cc
/branches/nov14/ms/MeasurementSets/test/tMSAntennaGram2.run
/branches/nov14/ms/MeasurementSets/test/tMSAntennaGram3.cc
/branches/nov14/ms/MeasurementSets/test/tMSAntennaGram3.out
/branches/nov14/ms/MeasurementSets/test/tMSCorrGram.cc
/branches/nov14/ms/MeasurementSets/test/tMSCorrGram.run
/branches/nov14/ms/MeasurementSets/test/tMSDerivedValues.cc
/branches/nov14/ms/MeasurementSets/test/tMSFieldGram.cc
/branches/nov14/ms/MeasurementSets/test/tMSFieldGram.run
/branches/nov14/ms/MeasurementSets/test/tMSMetaData.cc
/branches/nov14/ms/MeasurementSets/test/tMSMetaData.run
/branches/nov14/ms/MeasurementSets/test/tMSReader.cc
/branches/nov14/ms/MeasurementSets/test/tMSReader.run
/branches/nov14/ms/MeasurementSets/test/tMSScanGram.cc
/branches/nov14/ms/MeasurementSets/test/tMSScanGram.run
/branches/nov14/ms/MeasurementSets/test/tMSSpwGram.cc
/branches/nov14/ms/MeasurementSets/test/tMSSpwGram.run
/branches/nov14/ms/MeasurementSets/test/tMSSummary.cc
/branches/nov14/ms/MeasurementSets/test/tMSTimeGram.cc
/branches/nov14/ms/MeasurementSets/test/tMSTimeGram.run
/branches/nov14/ms/MeasurementSets/test/tMSUvDistGram.cc
/branches/nov14/ms/MeasurementSets/test/tMSUvDistGram.run
Modified:
/branches/nov14/derivedmscal/DerivedMC/UDFMSCal.cc
/branches/nov14/derivedmscal/DerivedMC/test/tDerivedMSCal.cc
/branches/nov14/ms/CMakeLists.txt
/branches/nov14/ms/MeasurementSets/MSDopplerUtil.cc
/branches/nov14/ms/MeasurementSets/MSIter.cc
/branches/nov14/ms/MeasurementSets/MSRange.cc
/branches/nov14/ms/MeasurementSets/MSRange.h
/branches/nov14/ms/MeasurementSets/MeasurementSet.cc
/branches/nov14/ms/MeasurementSets/test/CMakeLists.txt
/branches/nov14/ms/MeasurementSets.h
/branches/nov14/ms/apps/msselect.cc
/branches/nov14/ms/ms.dox
/branches/nov14/msfits/MSFits/MSFitsInput.cc
/branches/nov14/msfits/MSFits/test/tMSConcat.cc
/branches/nov14/msfits/MSFits/test/tMSSelection.cc
/branches/nov14/msfits/MSFits/test/tfits2ms.cc
=======================================
--- /dev/null
+++ /branches/nov14/ms/MSOper/MS1ToMS2Converter.cc Wed Mar 25 14:33:54 2015
UTC
@@ -0,0 +1,945 @@
+//# MS1ToMS2Converter.cc: MS1 to MS2 converter
+//# Copyright (C) 2000
+//# Associated Universities, Inc. Washington DC, USA.
+//#
+//# This library is free software; you can redistribute it and/or modify it
+//# under the terms of the GNU Library General Public License as published
by
+//# the Free Software Foundation; either version 2 of the License, or (at
your
+//# option) any later version.
+//#
+//# This library is distributed in the hope that it will be useful, but
WITHOUT
+//# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+//# FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
+//# License for more details.
+//#
+//# You should have received a copy of the GNU Library General Public
License
+//# along with this library; if not, write to the Free Software Foundation,
+//# Inc., 675 Massachusetts Ave, Cambridge, MA 02139, USA.
+//#
+//# Correspondence concerning AIPS++ should be addressed as follows:
+//# Internet email:
aips2-...@nrao.edu.
+//# Postal address: AIPS++ Project Office
+//# National Radio Astronomy Observatory
+//# 520 Edgemont Road
+//# Charlottesville, VA 22903-2475 USA
+//#
+//# $Id$
+
+#include <casacore/ms/MSOper/MS1ToMS2Converter.h>
+
+#include <casacore/ms/MeasurementSets/MeasurementSet.h>
+#include <casacore/ms/MeasurementSets/MSTableImpl.h>
+#include <casacore/tables/DataMan/IncrementalStMan.h>
+#include <casacore/tables/Tables/ScalarColumn.h>
+#include <casacore/tables/Tables/ArrayColumn.h>
+#include <casacore/tables/Tables/SetupNewTab.h>
+#include <casacore/tables/Tables/TableDesc.h>
+#include <casacore/tables/Tables/TableRecord.h>
+#include <casacore/tables/Tables/ScaColDesc.h>
+#include <casacore/tables/Tables/ArrColDesc.h>
+#include <casacore/measures/TableMeasures/ArrayMeasColumn.h>
+#include <casacore/measures/TableMeasures/TableMeasDesc.h>
+#include <casacore/measures/TableMeasures/TableMeasValueDesc.h>
+#include <casacore/measures/TableMeasures/TableQuantumDesc.h>
+#include <casacore/measures/Measures/MDirection.h>
+#include <casacore/measures/Measures/MEpoch.h>
+#include <casacore/measures/Measures/MPosition.h>
+#include <casacore/measures/Measures/MFrequency.h>
+#include <casacore/measures/Measures/MRadialVelocity.h>
+#include <casacore/casa/Arrays/Vector.h>
+#include <casacore/casa/Arrays/Matrix.h>
+#include <casacore/casa/Arrays/Cube.h>
+#include <casacore/casa/Arrays/ArrayMath.h>
+#include <casacore/casa/Arrays/ArrayLogical.h>
+#include <casacore/casa/Arrays/Slice.h>
+#include <casacore/casa/BasicSL/String.h>
+#include <casacore/casa/Exceptions/Error.h>
+#include <casacore/casa/iostream.h>
+
+
+
+namespace casacore { //# NAMESPACE CASACORE - BEGIN
+
+MS1ToMS2Converter::MS1ToMS2Converter(const String& ms2,
+ const String& ms1,
+ Bool inPlace)
+: ms1_p (ms1),
+ ms2_p (ms2),
+ inPlace_p(inPlace)
+{
+ LogOrigin OR("MS1ToMS2Converter", "MS1ToMS2Converter()", WHERE);
+ os_p = LogIO(OR);
+ if (inPlace_p) {
+ ms2_p = ms1_p;
+ }
+}
+
+MS1ToMS2Converter::~MS1ToMS2Converter()
+{}
+
+void MS1ToMS2Converter::removeColumn(Table& t, const String& col)
+{
+ if (t.canRemoveColumn(col)) {
+ // t.removeColumn(col);
+ t.renameColumn("_OBSOLETE_"+col,col);
+ } else {
+ t.renameColumn("_OBSOLETE_"+col,col);
+ }
+}
+
+Bool MS1ToMS2Converter::convert()
+{
+ // Check that table needs to be converted, if so (deep)copy it if needed.
+ {
+ Table t(ms1_p);
+ if (t.keywordSet().isDefined("MS_VERSION") &&
+ t.keywordSet().asFloat("MS_VERSION")>=2.0) {
+ throw(AipsError("Input MS already in MS2 format"));
+ }
+ if (!inPlace_p) t.copy(ms2_p,Table::NewNoReplace);
+ }
+
+ // Fix the main table, rename columns, add columns, remove columns
+ Table t;
+ if (inPlace_p) {
+ t = Table(ms1_p, Table::Update);
+ } else {
+ t = Table(ms2_p,Table::Update);
+ }
+ t.rwKeywordSet().define("MS_VERSION", Float(2.0));
+
+ t.renameColumn("DATA_DESC_ID","SPECTRAL_WINDOW_ID");
+
+ t.renameColumn("PROCESSOR_ID","CORRELATOR_ID");
+
+ if (t.keywordSet().isDefined("FLAG_HISTORY")) {
+ t.renameColumn("FLAG_CATEGORY","FLAG_HISTORY");
+ TableColumn flagc(t, "FLAG_CATEGORY");
+ if (!flagc.keywordSet().isDefined("CATEGORY"))
+ flagc.rwKeywordSet().define("CATEGORY", Vector<String>());
+ }
+
+ removeColumn(t,"PULSAR_ID");
+
+ t.rwKeywordSet().removeField("ARRAY");
+
+ if (t.keywordSet().isDefined("SORTED_TABLE"))
+ t.rwKeywordSet().removeField("SORTED_TABLE");
+
+ if (t.keywordSet().isDefined("SORT_COLUMNS"))
+ t.rwKeywordSet().removeField("SORT_COLUMNS");
+
+ TableDesc td;
+ IncrementalStMan ism;
+ MeasurementSet::addColumnToDesc(td,MS::PHASE_ID);
+ MeasurementSet::addColumnToDesc(td,MS::STATE_ID);
+ MeasurementSet::addColumnToDesc(td,MS::TIME_CENTROID);
+ if (!(t.keywordSet().isDefined("FLAG_CATEGORY")))
+ MeasurementSet::addColumnToDesc(td,MS::FLAG_CATEGORY);
+ t.addColumn(td,ism);
+
+ TableColumn flagc(t, "FLAG_CATEGORY");
+ if (!flagc.keywordSet().isDefined("CATEGORY")) {
+ flagc.rwKeywordSet().define("CATEGORY", Vector<String>());
+ }
+
+
+ ScalarColumn<Int> stateId(t,MS::columnName(MS::STATE_ID));
+ stateId.fillColumn(0);
+ ScalarColumn<Double> time(t,MS::columnName(MS::TIME));
+ ScalarColumn<Double> timeCentroid(t,MS::columnName(MS::TIME_CENTROID));
+ timeCentroid.putColumn(time.getColumn());
+
+
+ ArrayColumn<Double> uvw(t,MS::columnName(MS::UVW));
+ TableDesc uvwtd;
+ MeasurementSet::addColumnToDesc(uvwtd,MS::UVW);
+ uvw.rwKeywordSet().assign(uvwtd[0].keywordSet());
+
+ ScalarColumn<Double> exp(t,MS::columnName(MS::EXPOSURE));
+ TableDesc exptd;
+ MeasurementSet::addColumnToDesc(exptd,MS::EXPOSURE);
+ exp.rwKeywordSet().assign(exptd[0].keywordSet());
+
+ ScalarColumn<Double> inter(t,MS::columnName(MS::INTERVAL));
+ TableDesc intertd;
+ MeasurementSet::addColumnToDesc(intertd,MS::INTERVAL);
+ inter.rwKeywordSet().assign(intertd[0].keywordSet());
+
+ TableDesc timetd;
+ MeasurementSet::addColumnToDesc(timetd,MS::TIME);
+ time.rwKeywordSet().assign(timetd[0].keywordSet());
+
+ Int maxAnt;
+
+ // ANTENNA
+ {
+ Table anTab(ms2_p+"/ANTENNA",Table::Update);
+ // Find out if we need to renumber antennas
+ ScalarColumn<Int> antIdCol(anTab, "ANTENNA_ID");
+ Vector<Int> ant=antIdCol.getColumn();
+ Int nRow=ant.nelements();
+ maxAnt=max(ant)+1;
+ Vector<Int> antMap(maxAnt);
+ Bool renumber=False;
+ for (Int i=0; i<nRow; i++) {
+ if (i!=ant(i)) renumber=True;
+ antMap(ant(i))=i;
+ }
+
+ if (renumber) {
+ // cout <<"Renumbering antennas in main table and all
subtables"<<endl;
+ // Main
+ {
+ Vector<Int> newAnt1(t.nrow());
+ Vector<Int> newAnt2(t.nrow());
+ ScalarColumn<Int> ant1Col(t,"ANTENNA1");
+ ScalarColumn<Int> ant2Col(t,"ANTENNA2");
+ for (uInt i=0; i<t.nrow(); i++) {
+ newAnt1(i)=antMap(ant1Col(i));
+ newAnt2(i)=antMap(ant2Col(i));
+ }
+ ant1Col.putColumn(newAnt1);
+ ant2Col.putColumn(newAnt2);
+ }
+ // Feed
+ {
+ Table feedTab(ms2_p+"/FEED",Table::Update);
+ ScalarColumn<Int> ant(feedTab,"ANTENNA_ID");
+ for (uInt i=0; i<feedTab.nrow(); i++) {
+ ant.put(i,antMap(ant(i)));
+ }
+ removeColumn(feedTab,"ARRAY_ID");
+ }
+ // Syscal
+ if (Table::isReadable(ms2_p+"/SYSCAL")) {
+ Table syscalTab(ms2_p+"/SYSCAL",Table::Update);
+ ScalarColumn<Int> ant(syscalTab,"ANTENNA_ID");
+ for (uInt i=0; i<syscalTab.nrow(); i++) {
+ ant.put(i,antMap(ant(i)));
+ }
+ removeColumn(syscalTab,"ARRAY_ID");
+ }
+ // Weather
+ if (Table::isReadable(ms2_p+"/WEATHER")) {
+ Table wTab(ms2_p+"/WEATHER",Table::Update);
+ ScalarColumn<Int> ant(wTab,"ANTENNA_ID");
+ for (uInt i=0; i<wTab.nrow(); i++) {
+ ant.put(i,antMap(ant(i)));
+ }
+ removeColumn(wTab,"ARRAY_ID");
+ }
+ }
+
+ // remove columns
+ removeColumn(anTab,"ARRAY_ID");
+ removeColumn(anTab,"ANTENNA_ID");
+
+ TableDesc td;
+ MSAntenna::addColumnToDesc(td,MSAntenna::TYPE);
+ MSAntenna::addColumnToDesc(td,MSAntenna::FLAG_ROW);
+ anTab.addColumn(td[0]);
+ anTab.addColumn(td[1]);
+ ScalarColumn<String> type(anTab,"TYPE");
+ type.fillColumn("GROUND-BASED");
+ ScalarColumn<Bool> flagRow(anTab,"FLAG_ROW");
+ flagRow.fillColumn(False);
+
+
+ ArrayColumn<Double> pos(anTab,"POSITION");
+ TableDesc postd;
+ MSAntenna::addColumnToDesc(postd,MSAntenna::POSITION);
+ pos.rwKeywordSet().assign(postd[0].keywordSet());
+
+ ArrayColumn<Double> offs(anTab,"OFFSET");
+ TableDesc offstd;
+ MSAntenna::addColumnToDesc(offstd,MSAntenna::OFFSET);
+ offs.rwKeywordSet().assign(offstd[0].keywordSet());
+
+ ScalarColumn<Double> dish(anTab,"DISH_DIAMETER");
+ TableDesc dishtd;
+ MSAntenna::addColumnToDesc(dishtd,MSAntenna::DISH_DIAMETER);
+ dish.rwKeywordSet().assign(dishtd[0].keywordSet());
+
+ for (uInt j = MSAntenna::NUMBER_REQUIRED_COLUMNS + 1;
+ j < MSAntenna::NUMBER_PREDEFINED_COLUMNS; j = j + 1) {
+ MSAntenna::PredefinedColumns i = (MSAntenna::PredefinedColumns) j;
+ if (anTab.tableDesc().isColumn(MSAntenna::columnName(i))) {
+ TableColumn tbc(anTab, MSAntenna::columnName(i));
+ TableDesc td;
+ MSAntenna::addColumnToDesc(td, i);
+ tbc.rwKeywordSet().assign(td[0].keywordSet());
+ }
+ }
+ }
+
+ // DATA_DESCRIPTION
+ {
+ // create and fill table and write it out
+ {
+ Int nRow = t.keywordSet().asTable("SPECTRAL_WINDOW").nrow();
+ SetupNewTable ddSetup(ms2_p+"/DATA_DESCRIPTION",
+ MSDataDescription::requiredTableDesc(),
+ Table::New);
+ Table ddt(ddSetup,nRow);
+ ScalarColumn<Int> spw(ddt,"SPECTRAL_WINDOW_ID");
+ ScalarColumn<Int> pol(ddt,"POLARIZATION_ID");
+ ScalarColumn<Bool> flagRow(ddt,"FLAG_ROW");
+ Vector<Int> seq(nRow);
+ for (Int i=0;i<nRow;i++) seq(i)=i;
+ spw.putColumn(seq);
+ pol.putColumn(seq);
+ flagRow.fillColumn(False);
+ }
+ Table ddt(ms2_p+"/DATA_DESCRIPTION");
+ t.rwKeywordSet().
+ defineTable(MS::keywordName(MS::DATA_DESCRIPTION),ddt);
+ }
+
+ // FEED
+ {
+ Table feedTab(ms2_p+"/FEED",Table::Update);
+ ScalarColumn<Double> time(feedTab,"TIME");
+ TableDesc timetd;
+ MSFeed::addColumnToDesc(timetd,MSFeed::TIME);
+ time.rwKeywordSet().assign(timetd[0].keywordSet());
+
+ ArrayColumn<Double> pos(feedTab,"POSITION");
+ TableDesc postd;
+ MSFeed::addColumnToDesc(postd,MSFeed::POSITION);
+ pos.rwKeywordSet().assign(postd[0].keywordSet());
+
+ ArrayColumn<Double> beam(feedTab,"BEAM_OFFSET");
+ TableDesc beamtd;
+ MSFeed::addColumnToDesc(beamtd,MSFeed::BEAM_OFFSET);
+ beam.rwKeywordSet().assign(beamtd[0].keywordSet());
+
+ ArrayColumn<Double> recep(feedTab,"RECEPTOR_ANGLE");
+ TableDesc receptd;
+ MSFeed::addColumnToDesc(receptd,MSFeed::RECEPTOR_ANGLE);
+ recep.rwKeywordSet().assign(receptd[0].keywordSet());
+
+ ScalarColumn<Double> inter(feedTab,"INTERVAL");
+ TableDesc intertd;
+ MSFeed::addColumnToDesc(intertd,MSFeed::INTERVAL);
+ inter.rwKeywordSet().assign(intertd[0].keywordSet());
+
+ }
+
+ // FIELD
+ {
+ Table fldTab(ms2_p+"/FIELD",Table::Update);
+ removeColumn(fldTab,"FIELD_ID");
+
+ Matrix<Double> dd,ddr,pd,pdr,rd,rdr,pntd,pntdr;
+ uInt pdtp, rdtp, ddtp;
+ {
+ ROArrayColumn<Double> delDir(fldTab,"DELAY_DIR");
+ ROArrayColumn<Double> delDirRate(fldTab,"DELAY_DIR_RATE");
+ ROArrayColumn<Double> phaseDir(fldTab,"PHASE_DIR");
+ ROArrayColumn<Double> phaseDirRate(fldTab,"PHASE_DIR_RATE");
+ ROArrayColumn<Double> pointingDir(fldTab,"POINTING_DIR");
+ ROArrayColumn<Double> pointingDirRate(fldTab,"POINTING_DIR_RATE");
+ ROArrayColumn<Double> refDir(fldTab,"REFERENCE_DIR");
+ ROArrayColumn<Double> refDirRate(fldTab,"REFERENCE_DIR_RATE");
+ dd=delDir.getColumn();
+ ddr=delDirRate.getColumn();
+ pd=phaseDir.getColumn();
+ pdr=phaseDirRate.getColumn();
+ pntd=pointingDir.getColumn();
+ pntdr=pointingDirRate.getColumn();
+ rd=refDir.getColumn();
+ rdr=refDirRate.getColumn();
+
+ MDirection::Types tp;
+ MDirection::getType(tp,
phaseDir.keywordSet().asString("MEASURE_REFERENCE"));
+ pdtp = tp;
+ MDirection::getType(tp,
refDir.keywordSet().asString("MEASURE_REFERENCE"));
+ rdtp = tp;
+ MDirection::getType(tp,
delDir.keywordSet().asString("MEASURE_REFERENCE"));
+ ddtp = tp;
+ }
+ IPosition shape(2,2,2);
+ Int numPol = 1;
+ if (allEQ(pntdr,0.0) && allEQ(ddr,0.0) &&
+ allEQ(pdr,0.0) && allEQ(rdr,0.0)) {
+ // all rates are zero, use only one term
+ shape(1)=1;
+ numPol=0;
+ }
+
+ removeColumn(fldTab,"DELAY_DIR");
+ removeColumn(fldTab,"DELAY_DIR_RATE");
+ removeColumn(fldTab,"PHASE_DIR");
+ removeColumn(fldTab,"PHASE_DIR_RATE");
+ removeColumn(fldTab,"REFERENCE_DIR");
+ removeColumn(fldTab,"REFERENCE_DIR_RATE");
+ removeColumn(fldTab,"POINTING_DIR");
+ removeColumn(fldTab,"POINTING_DIR_RATE");
+ TableDesc td;
+ MSField::addColumnToDesc(td, MSField::DELAY_DIR,2);
+ MSField::addColumnToDesc(td, MSField::PHASE_DIR,2);
+ MSField::addColumnToDesc(td, MSField::REFERENCE_DIR,2);
+ MSField::addColumnToDesc(td, MSField::NUM_POLY);
+ MSField::addColumnToDesc(td, MSField::FLAG_ROW);
+ fldTab.addColumn(td[0]);
+ fldTab.addColumn(td[1]);
+ fldTab.addColumn(td[2]);
+ fldTab.addColumn(td[3]);
+ fldTab.addColumn(td[4]);
+
+ ArrayMeasColumn<MDirection> delAmc(fldTab, "DELAY_DIR");
+ ArrayMeasColumn<MDirection> phaseAmc(fldTab, "PHASE_DIR");
+ ArrayMeasColumn<MDirection> refAmc(fldTab, "REFERENCE_DIR");
+ delAmc.setDescRefCode(ddtp, False);
+ phaseAmc.setDescRefCode(pdtp, False);
+ refAmc.setDescRefCode(rdtp, False);
+
+ ArrayColumn<Double> delDir(fldTab,"DELAY_DIR");
+ ArrayColumn<Double> phaseDir(fldTab,"PHASE_DIR");
+ ArrayColumn<Double> refDir(fldTab,"REFERENCE_DIR");
+ ScalarColumn<Bool> flagRow(fldTab,"FLAG_ROW");
+ flagRow.fillColumn(False);
+ ScalarColumn<Int> numPoly(fldTab,"NUM_POLY");
+ numPoly.fillColumn(numPol);
+
+ Int nRow=fldTab.nrow();
+ Matrix<Double> zero(shape);
+ zero = 0.0;
+ for (Int i=0; i<nRow; i++) {
+ Matrix<Double> ddir(shape),pdir(shape),rdir(shape),pntdir(shape);
+ ddir(0,0)=dd(0,i); ddir(1,0)=dd(1,i);
+ pdir(0,0)=pd(0,i); pdir(1,0)=pd(1,i);
+ pntdir(0,0)=pntd(0,i); pntdir(1,0)=pntd(1,i);
+ rdir(0,0)=rd(0,i); rdir(1,0)=rd(1,i);
+ if (numPol==1) {
+ ddir(0,1)=ddr(0,i); ddir(1,1)=ddr(1,i);
+ pdir(0,1)=pdr(0,i); pdir(1,1)=pdr(1,i);
+ pntdir(0,1)=pntdr(0,i); pntdir(1,1)=pntdr(1,i);
+ rdir(0,1)=rdr(0,i); rdir(1,1)=rdr(1,i);
+ }
+ delDir.put(i,ddir);
+ if (!allEQ(pdir, zero))
+ phaseDir.put(i,pdir);
+ else phaseDir.put(i,pntdir);
+ refDir.put(i,rdir);
+ }
+
+ ScalarColumn<Double> time(fldTab,"TIME");
+ TableDesc timetd;
+ MSField::addColumnToDesc(timetd,MSField::TIME);
+ time.rwKeywordSet().assign(timetd[0].keywordSet());
+
+ }
+
+ // FLAG_CMD
+ {
+ Int nRow = 0;
+ SetupNewTable flagCmdSetup(ms2_p+"/FLAG_CMD",
+ MSFlagCmd::requiredTableDesc(),
+ Table::New);
+ Table flagCmdt(flagCmdSetup,nRow);
+
+ t.rwKeywordSet().defineTable(MS::keywordName(MS::FLAG_CMD),
+ flagCmdt);
+ }
+
+
+
+ // HISTORY
+ {
+ if (t.keywordSet().isDefined("OBS_LOG")) {
+ // Table hisTab=t.rwKeywordSet().asTable("OBS_LOG");
+ Table hisTab(ms2_p+"/OBS_LOG",Table::Update);
+
+
+ TableDesc td;
+ MSHistory::addColumnToDesc(td,MSHistory::PRIORITY);
+ MSHistory::addColumnToDesc(td,MSHistory::ORIGIN);
+ MSHistory::addColumnToDesc(td,MSHistory::OBJECT_ID);
+ MSHistory::addColumnToDesc(td,MSHistory::APPLICATION);
+ MSHistory::addColumnToDesc(td,MSHistory::CLI_COMMAND);
+ MSHistory::addColumnToDesc(td,MSHistory::APP_PARAMS);
+
+ hisTab.addColumn(td[0]);
+ hisTab.addColumn(td[1]);
+ hisTab.addColumn(td[2]);
+ hisTab.addColumn(td[3]);
+ hisTab.addColumn(td[4]);
+ hisTab.addColumn(td[5]);
+
+ ScalarColumn<Double> time(hisTab,"TIME");
+ TableDesc timetd;
+ MSHistory::addColumnToDesc(timetd,MSHistory::TIME);
+ time.rwKeywordSet().assign(timetd[0].keywordSet());
+
+ t.rwKeywordSet().removeField("OBS_LOG");
+ hisTab.rename(ms2_p+"/HISTORY",Table::New);
+ t.rwKeywordSet().defineTable("HISTORY", hisTab);
+ }
+ }
+
+
+ // OBSERVATION
+ {
+ Table obsTab(ms2_p+"/OBSERVATION",Table::Update);
+ removeColumn(obsTab, "CORR_SCHEDULE");
+ TableDesc td;
+ MSObservation::addColumnToDesc(td, MSObservation::TELESCOPE_NAME);
+ MSObservation::addColumnToDesc(td, MSObservation::TIME_RANGE);
+ MSObservation::addColumnToDesc(td, MSObservation::SCHEDULE);
+ MSObservation::addColumnToDesc(td, MSObservation::SCHEDULE_TYPE);
+ MSObservation::addColumnToDesc(td, MSObservation::LOG);
+ MSObservation::addColumnToDesc(td, MSObservation::RELEASE_DATE);
+ MSObservation::addColumnToDesc(td, MSObservation::FLAG_ROW);
+
+ obsTab.addColumn(td[0]);
+ obsTab.addColumn(td[1]);
+ obsTab.addColumn(td[2]);
+ obsTab.addColumn(td[3]);
+ obsTab.addColumn(td[4]);
+ obsTab.addColumn(td[5]);
+ obsTab.addColumn(td[6]);
+
+ Table arrTab(ms2_p+"/ARRAY",Table::Old);
+ ROScalarColumn<String> arrName(arrTab,"NAME");
+ ScalarColumn<String> telName(obsTab,"TELESCOPE_NAME");
+ ArrayColumn<Double> timeRange(obsTab, "TIME_RANGE");
+ ScalarColumn<Bool> flagRow(obsTab,"FLAG_ROW");
+ flagRow.fillColumn(False);
+
+ ROScalarColumn<Double> time(t, "TIME");
+ ROScalarColumn<Double> interval(t, "INTERVAL");
+ ROScalarColumn<Int> observationid(t, "OBSERVATION_ID");
+ ROScalarColumn<Int> arrayid(t, "ARRAY_ID");
+ Vector<Double> tim = time.getColumn();
+ Vector<Double> inter = interval.getColumn();
+ Vector<Int> obsid = observationid.getColumn();
+ Vector<Int> arrid = arrayid.getColumn();
+ Vector<String> arrnm = arrName.getColumn();
+
+ Int nObs = obsTab.nrow();
+ Int startInd;
+ Int endInd;
+ Int minPos, maxPos;
+ Vector<Double> vt(2);
+
+ for (Int obs=0; obs<nObs; obs++) {
+ // fill time range
+ startInd = 0;
+ endInd = t.nrow()-1;
+ for (uInt i=0; i<t.nrow(); i++) {
+ if (obsid(i) == obs) { startInd = i; break; }
+ }
+ for (uInt i=startInd; i<t.nrow(); i++) {
+ if (obsid(i) > obs) { endInd = i-1; break; }
+ }
+ vt(0) = tim(startInd);
+ vt(1) = tim(endInd);
+
+ vt(0) = min(tim(Slice(startInd,endInd-startInd+1, 1)));
+ vt(1) = max(tim(Slice(startInd,endInd-startInd+1, 1)));
+
+ // Sort just in case the time column is not sorted
+ vt(0) = tim(startInd);
+ vt(1) = tim(startInd);
+ minPos = startInd;
+ maxPos = startInd;
+ for (Int i=startInd; i<=endInd; i++) {
+ if (tim(i) < vt(0)) {
+ vt(0) = tim(i);
+ minPos = i;
+ }
+ if (tim(i) >= vt(1)) {
+ vt(1) = tim(i);
+ maxPos = i;
+ }
+ }
+
+ vt(0) = vt(0) - inter(minPos)/2;
+ vt(1) = vt(1) + inter(maxPos)/2;
+ timeRange.put(obs, vt);
+
+ // telescope name
+ telName.put(obs, arrnm(arrid(startInd)));
+ }
+ }
+
+ // POINTING
+ {
+ Int nRow =0;
+ SetupNewTable pointingSetup(ms2_p+"/POINTING",
+ MSPointing::requiredTableDesc(),
+ Table::New);
+ Table pointTab(pointingSetup,nRow);
+ // TableRecord tbrec = t.rwKeywordSet();
+ t.rwKeywordSet().defineTable(MS::keywordName(MS::POINTING),
+ pointTab);
+ ROScalarColumn<Double> time(t, MS::columnName(MS::TIME));
+ ROScalarColumn<Double> interval(t, MS::columnName(MS::INTERVAL));
+ ScalarColumn<Int> fieldId(t, MS::columnName(MS::FIELD_ID));
+ Vector<Double> tim = time.getColumn();
+ Vector<Double> inter = interval.getColumn();
+ Vector<Int> fi = fieldId.getColumn();
+
+
+ Table fldTab(ms2_p+"/FIELD", Table::Update);
+ Cube<Double> pd;
+ {
+ ROArrayColumn<Double> phaseDir(fldTab, "PHASE_DIR");
+ pd = phaseDir.getColumn();
+ }
+
+ // Table pointTab(ms2_p+"/POINTING", Table::Update);
+ ScalarColumn<Double> t2(pointTab,
MSPointing::columnName(MSPointing::TIME));
+ ScalarColumn<Double> i2(pointTab,
MSPointing::columnName(MSPointing::INTERVAL));
+ ArrayColumn<Double> phaseDir2(pointTab,
+ MSPointing::columnName(MSPointing::DIRECTION));
+ ScalarColumn<Int> a2(pointTab,
MSPointing::columnName(MSPointing::ANTENNA_ID));
+ ScalarColumn<Int> numPoly2(pointTab,
MSPointing::columnName(MSPointing::NUM_POLY));
+
+ nRow = t.nrow();
+ Int fld = -1;
+ Int pnt = 0;
+
+ ROScalarColumn<Int> numPoly(fldTab,"NUM_POLY");
+ IPosition shape(2,2,numPoly(0)+1);
+ Matrix<Double> pdir(shape);
+
+ for (Int i=0; i<nRow; i++) {
+ if (fi(i) != fld) {
+ fld = fi(i);
+ pdir = pd.xyPlane(fld);
+
+ pointTab.addRow(maxAnt);
+ for (Int j=0; j<maxAnt; j++) {
+ t2.put(maxAnt*pnt+j, tim(i));
+ i2.put(maxAnt*pnt+j, inter(i));
+ a2.put(maxAnt*pnt+j, j+1);
+ phaseDir2.put(maxAnt*pnt+j, pdir);
+ }
+ pnt++;
+ }
+ }
+
+ nRow = pointTab.nrow();
+
+ for (Int i=0; i<nRow; i++)
+ numPoly2.put(i, numPoly(0));
+
+ uInt ctp;
+ ROArrayColumn<Double> obspDir(fldTab,"_OBSOLETE_POINTING_DIR");
+ MDirection::Types tp;
+ MDirection::getType(tp,
obspDir.keywordSet().asString("MEASURE_REFERENCE"));
+ ctp = tp;
+ ArrayMeasColumn<MDirection> dirAmc(pointTab, "DIRECTION");
+ dirAmc.setDescRefCode(ctp, False);
+ ArrayMeasColumn<MDirection> tgAmc(pointTab, "TARGET");
+ tgAmc.setDescRefCode(ctp, False);
+
+
+ for (uInt j = MSPointing::NUMBER_REQUIRED_COLUMNS + 1;
+ j < MSPointing::NUMBER_PREDEFINED_COLUMNS; j = j + 1) {
+ MSPointing::PredefinedColumns i = (MSPointing::PredefinedColumns) j;
+ if (pointTab.tableDesc().isColumn(MSPointing::columnName(i))) {
+ TableColumn tbc(pointTab, MSPointing::columnName(i));
+ TableDesc td;
+ MSPointing::addColumnToDesc(td, i);
+ tbc.rwKeywordSet().assign(td[0].keywordSet());
+ }
+ }
+
+ }
+
+
+ // POLARIZATION
+ // SPECTRAL_WINDOW
+ {
+ Table spwTab(ms2_p+"/SPECTRAL_WINDOW",Table::Update);
+ Int nRow = spwTab.nrow();
+ SetupNewTable polarizationSetup(ms2_p+"/POLARIZATION",
+ MSPolarization::requiredTableDesc(),
+ Table::New);
+ Table polTab(polarizationSetup,nRow);
+ t.rwKeywordSet().defineTable(MS::keywordName(MS::POLARIZATION),
+ polTab);
+
+
+ // Table polTab(ms2_p+"/POLARIZATION",Table::Update);
+
+ TableDesc td;
+ MSSpectralWindow::addColumnToDesc(td,MSSpectralWindow::NAME);
+ MSSpectralWindow::addColumnToDesc(td,MSSpectralWindow::FREQ_GROUP);
+ MSSpectralWindow::addColumnToDesc(td,MSSpectralWindow::FREQ_GROUP_NAME);
+ MSSpectralWindow::addColumnToDesc(td,MSSpectralWindow::NET_SIDEBAND);
+ MSSpectralWindow::addColumnToDesc(td,MSSpectralWindow::CHAN_WIDTH);
+ MSSpectralWindow::addColumnToDesc(td,MSSpectralWindow::EFFECTIVE_BW);
+ MSSpectralWindow::addColumnToDesc(td,MSSpectralWindow::MEAS_FREQ_REF);
+ MSSpectralWindow::addColumnToDesc(td,MSSpectralWindow::FLAG_ROW);
+ for (Int i=0; i<8; i++) spwTab.addColumn(td[i]);
+
+ ScalarColumn<Int> snumCorr(spwTab, "NUM_CORR");
+ ROArrayColumn<Int> scorrType(spwTab, "CORR_TYPE");
+ ROArrayColumn<Int> scorrProduct(spwTab, "CORR_PRODUCT");
+
+ ScalarColumn<Int> pnumCorr(polTab, "NUM_CORR");
+ ArrayColumn<Int> pcorrType(polTab, "CORR_TYPE");
+ ArrayColumn<Int> pcorrProduct(polTab, "CORR_PRODUCT");
+
+ pnumCorr.putColumn(snumCorr.getColumn());
+
+ for (Int i=0; i<nRow; i++) {
+ pcorrType.put(i, scorrType(i));
+ pcorrProduct.put(i, scorrProduct(i));
+ }
+
+ ScalarColumn<Int> freqGrp(spwTab,"FREQ_GROUP");
+ freqGrp.fillColumn(0);
+ ScalarColumn<Int> netSideb(spwTab,"NET_SIDEBAND");
+ netSideb.fillColumn(1);
+
+ ArrayColumn<Double> resol(spwTab, "RESOLUTION");
+ ArrayColumn<Double> chanWdth(spwTab, "CHAN_WIDTH");
+ ArrayColumn<Double> effBw(spwTab, "EFFECTIVE_BW");
+ for (Int i=0; i<nRow; i++) {
+ chanWdth.put(i, resol(i));
+ effBw.put(i, resol(i));
+ }
+ ScalarColumn<Bool> flagRow(spwTab,"FLAG_ROW");
+ flagRow.fillColumn(False);
+
+ ScalarColumn<Double> reffreq(spwTab,"REF_FREQUENCY");
+ MFrequency::Types tp;
+ MFrequency::getType(tp,
reffreq.keywordSet().asString("MEASURE_REFERENCE"));
+ Int meas_freq_ref = tp;
+
+ ScalarColumn<Int> measCol(spwTab,"MEAS_FREQ_REF");
+ measCol.fillColumn(meas_freq_ref);
+
+ TableDesc reffreqtd;
+
MSSpectralWindow::addColumnToDesc(reffreqtd,MSSpectralWindow::REF_FREQUENCY);
+ reffreq.rwKeywordSet().assign(reffreqtd[0].keywordSet());
+
+
+ ArrayColumn<Double> chanfreq(spwTab,"CHAN_FREQ");
+ TableDesc chanfreqtd;
+
MSSpectralWindow::addColumnToDesc(chanfreqtd,MSSpectralWindow::CHAN_FREQ);
+ chanfreq.rwKeywordSet().assign(chanfreqtd[0].keywordSet());
+
+
+
+ ArrayColumn<Double> chanwidth(spwTab,"CHAN_WIDTH");
+ TableDesc chanwidthtd;
+
MSSpectralWindow::addColumnToDesc(chanwidthtd,MSSpectralWindow::CHAN_WIDTH);
+ chanwidth.rwKeywordSet().assign(chanwidthtd[0].keywordSet());
+
+ ArrayColumn<Double> bw(spwTab,"EFFECTIVE_BW");
+ TableDesc bwtd;
+ MSSpectralWindow::addColumnToDesc(bwtd,MSSpectralWindow::EFFECTIVE_BW);
+ bw.rwKeywordSet().assign(bwtd[0].keywordSet());
+
+ ArrayColumn<Double> res(spwTab,"RESOLUTION");
+ TableDesc restd;
+ MSSpectralWindow::addColumnToDesc(restd,MSSpectralWindow::RESOLUTION);
+ res.rwKeywordSet().assign(restd[0].keywordSet());
+
+ ScalarColumn<Double> tbw(spwTab,"TOTAL_BANDWIDTH");
+ TableDesc tbwtd;
+
MSSpectralWindow::addColumnToDesc(tbwtd,MSSpectralWindow::TOTAL_BANDWIDTH);
+ tbw.rwKeywordSet().assign(tbwtd[0].keywordSet());
+
+
+ for (uInt j = MSSpectralWindow::NUMBER_REQUIRED_COLUMNS + 1;
+ j < MSSpectralWindow::NUMBER_PREDEFINED_COLUMNS; j = j + 1) {
+ MSSpectralWindow::PredefinedColumns i =
(MSSpectralWindow::PredefinedColumns) j;
+ if (spwTab.tableDesc().isColumn(MSSpectralWindow::columnName(i))) {
+ TableColumn tbc(spwTab, MSSpectralWindow::columnName(i));
+ TableDesc td;
+ MSSpectralWindow::addColumnToDesc(td, i);
+ tbc.rwKeywordSet().assign(td[0].keywordSet());
+ }
+ }
+
+
+
+ }
+
+ // PROCESSOR
+ {
+ Int nRow = 0;
+ SetupNewTable processorSetup(ms2_p+"/PROCESSOR",
+ MSProcessor::requiredTableDesc(),
+ Table::New);
+ Table processorSetupt(processorSetup,nRow);
+ t.rwKeywordSet().defineTable(MS::keywordName(MS::PROCESSOR),
+ processorSetupt);
+
+ }
+
+ // SOURCE
+ {
+ Table sourceTab(ms2_p+"/SOURCE",Table::Update);
+ TableDesc td;
+ MSSource::addColumnToDesc(td, MSSource::NUM_LINES);
+ sourceTab.addColumn(td[0]);
+
+ ArrayColumn<Double> pos(sourceTab,"POSITION");
+ TableDesc postd;
+ MSSource::addColumnToDesc(postd,MSSource::POSITION);
+ pos.rwKeywordSet().assign(postd[0].keywordSet());
+
+ ArrayColumn<Double> direc(sourceTab,"DIRECTION");
+ TableDesc directd;
+ MSSource::addColumnToDesc(directd,MSSource::DIRECTION);
+ direc.rwKeywordSet().assign(directd[0].keywordSet());
+
+ ArrayColumn<Double> prop(sourceTab,"PROPER_MOTION");
+ TableDesc proptd;
+ MSSource::addColumnToDesc(proptd,MSSource::PROPER_MOTION);
+ prop.rwKeywordSet().assign(proptd[0].keywordSet());
+
+
+ ScalarColumn<Double> inter(sourceTab,"INTERVAL");
+ TableDesc intertd;
+ MSSource::addColumnToDesc(intertd,MSSource::INTERVAL);
+ inter.rwKeywordSet().assign(intertd[0].keywordSet());
+
+ ScalarColumn<Double> time(sourceTab, "TIME");
+ TableDesc timetd;
+ MSSource::addColumnToDesc(timetd,MSSource::TIME);
+ time.rwKeywordSet().assign(timetd[0].keywordSet());
+
+ for (uInt j = MSSource::NUMBER_REQUIRED_COLUMNS + 1;
+ j < MSSource::NUMBER_PREDEFINED_COLUMNS; j = j + 1) {
+ MSSource::PredefinedColumns i = (MSSource::PredefinedColumns) j;
+ if (sourceTab.tableDesc().isColumn(MSSource::columnName(i))) {
+ TableColumn tbc(sourceTab, MSSource::columnName(i));
+ TableDesc td;
+ MSSource::addColumnToDesc(td, i);
+ tbc.rwKeywordSet().assign(td[0].keywordSet());
+ }
+ }
+
+ if (sourceTab.tableDesc().isColumn("SYSVEL_OLD")) {
+ cout << "Array column SYSVEL_OLD seems to exist" << endl;
+ } else {
+ sourceTab.renameColumn("SYSVEL_OLD", "SYSVEL");
+ sourceTab.addColumn(ArrayColumnDesc<Double>("SYSVEL", 1));
+ // Construct a measure for this column in a temporary TableDesc.
+ // Copy that keywordset to get the measure in the SYSVEL column.
+ TableDesc td;
+ td.addColumn(ArrayColumnDesc<Double>("SYSVELX", 1));
+ TableMeasValueDesc mvval(td, "SYSVELX");
+ TableMeasDesc<MRadialVelocity> mval(mvval);
+ mval.write(td);
+ ROScalarColumn<Double> vold(sourceTab, "SYSVEL_OLD");
+ ArrayColumn<Double> sysvel(sourceTab, "SYSVEL");
+ sysvel.rwKeywordSet() = td.columnDesc("SYSVELX").keywordSet();
+ // Set data to the old SYSVEL.
+ Vector<Double> vec(1);
+ for (uInt i=0; i<sourceTab.nrow(); i++) {
+ vec(0) = vold(i);
+ sysvel.put(i, vec);
+ }
+ }
+
+ }
+
+ // STATE
+ {
+ Int nRow = 0;
+
+ SetupNewTable stateSetup(ms2_p+"/STATE",
+ MSState::requiredTableDesc(),
+ Table::New);
+ Table stateSetupt(stateSetup,nRow);
+
+ t.rwKeywordSet().defineTable(MS::keywordName(MS::STATE),
+ stateSetupt);
+
+ }
+
+ // SYSCAL
+ {
+ Table syscalTab(ms2_p+"/SYSCAL",Table::Update);
+ if (syscalTab.canRemoveColumn("ARRAY_ID"))
+ removeColumn(syscalTab,"ARRAY_ID");
+ removeColumn(syscalTab,"NUM_RECEPTORS");
+
+ ScalarColumn<Double> inter(syscalTab,"INTERVAL");
+ TableDesc intertd;
+ MSSysCal::addColumnToDesc(intertd,MSSysCal::INTERVAL);
+ inter.rwKeywordSet().assign(intertd[0].keywordSet());
+
+ ScalarColumn<Double> time(syscalTab, "TIME");
+ TableDesc timetd;
+ MSSysCal::addColumnToDesc(timetd,MSSysCal::TIME);
+ time.rwKeywordSet().assign(timetd[0].keywordSet());
+
+ for (uInt j = MSSysCal::NUMBER_REQUIRED_COLUMNS + 1;
+ j < MSSysCal::NUMBER_PREDEFINED_COLUMNS; j = j + 1) {
+ MSSysCal::PredefinedColumns i = (MSSysCal::PredefinedColumns) j;
+ if (syscalTab.tableDesc().isColumn(MSSysCal::columnName(i))) {
+ TableColumn tbc(syscalTab, MSSysCal::columnName(i));
+ TableDesc td;
+ MSSysCal::addColumnToDesc(td, i);
+ tbc.rwKeywordSet().assign(td[0].keywordSet());
+ }
+ }
+
+ }
+
+
+ // WEATHER
+ {
+ Table weatherTab(ms2_p+"/WEATHER",Table::Update);
+ if (weatherTab.canRemoveColumn("ARRAY_ID"))
+ removeColumn(weatherTab,"ARRAY_ID");
+
+ ScalarColumn<Double> inter(weatherTab,"INTERVAL");
+ TableDesc intertd;
+ MSWeather::addColumnToDesc(intertd,MSWeather::INTERVAL);
+ inter.rwKeywordSet().assign(intertd[0].keywordSet());
+
+ ScalarColumn<Double> time(weatherTab, "TIME");
+ TableDesc timetd;
+ MSWeather::addColumnToDesc(timetd,MSWeather::TIME);
+ time.rwKeywordSet().assign(timetd[0].keywordSet());
+
+ for (uInt j = MSWeather::NUMBER_REQUIRED_COLUMNS + 1;
+ j < MSWeather::NUMBER_PREDEFINED_COLUMNS; j = j + 1) {
+ MSWeather::PredefinedColumns i = (MSWeather::PredefinedColumns) j;
+ if (weatherTab.tableDesc().isColumn(MSWeather::columnName(i))) {
+ TableColumn tbc(weatherTab, MSWeather::columnName(i));
+ TableDesc td;
+ MSWeather::addColumnToDesc(td, i);
+ tbc.rwKeywordSet().assign(td[0].keywordSet());
+ }
+ }
+
+ }
+
+ // get correct shape for array weight
+ if (t.tableDesc().isColumn("WEIGHT_OLD")) {
+ cout << "Array column WEIGHT_OLD seems to exist" << endl;
+ } else {
+ t.renameColumn ("WEIGHT_OLD", "WEIGHT");
+ t.addColumn (ArrayColumnDesc<Float>("WEIGHT", 1));
+
+ ROArrayColumn<Float> sigma (t, "SIGMA");
+ ROScalarColumn<Float> wold (t, "WEIGHT_OLD");
+ ArrayColumn<Float> weight (t, "WEIGHT");
+ for (uInt i=0; i<t.nrow(); i++) {
+ Array<Float> arr(sigma.shape(i));
+ arr = wold(i);
+ weight.put (i, arr);
+ }
+ }
+
+
+ os_p << LogIO::NORMAL << "Conversion done" << LogIO::POST;
+ return True;
+}
+
+} //# NAMESPACE CASACORE - END
+
=======================================
--- /dev/null
+++ /branches/nov14/ms/MSOper/MS1ToMS2Converter.h Wed Mar 25 14:33:54 2015
UTC
@@ -0,0 +1,113 @@
+//# MS1ToMS2Converter.h: Definition for ms1 to ms2 converter
+//# Copyright (C) 1994,1995,1996,1997,1998,1999,2000
+//# Associated Universities, Inc. Washington DC, USA.
+//#
+//# This library is free software; you can redistribute it and/or modify it
+//# under the terms of the GNU Library General Public License as published
by
+//# the Free Software Foundation; either version 2 of the License, or (at
your
+//# option) any later version.
+//#
+//# This library is distributed in the hope that it will be useful, but
WITHOUT
+//# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+//# FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
+//# License for more details.
+//#
+//# You should have received a copy of the GNU Library General Public
License
+//# along with this library; if not, write to the Free Software Foundation,
+//# Inc., 675 Massachusetts Ave, Cambridge, MA 02139, USA.
+//#
+//# Correspondence concerning AIPS++ should be addressed as follows:
+//# Internet email:
aips2-...@nrao.edu.
+//# Postal address: AIPS++ Project Office
+//# National Radio Astronomy Observatory
+//# 520 Edgemont Road
+//# Charlottesville, VA 22903-2475 USA
+//#
+//# $Id$
+
+#ifndef MS_MS1TOMS2CONVERTER_H
+#define MS_MS1TOMS2CONVERTER_H
+
+//# Includes
+#include <casacore/casa/aips.h>
+#include <casacore/tables/Tables/Table.h>
+#include <casacore/casa/Logging/LogIO.h>
+
+namespace casacore { //# NAMESPACE CASACORE - BEGIN
+
+//# Forward declarations
+class String;
+
+
+// <summary>
+// Class to convert a MeasurementSet v1 to v2.
+// </summary>
+
+// <use visibility=export>
+
+// <reviewed reviewer="" date="yyyy/mm/dd" tests="" demos="">
+// </reviewed>
+
+// <synopsis>
+// This class converts a version 1 MeasurementSet to version 2.
+// The keyword MS_VERSION tells the version. If not present it is 1.
+// If it is found that the MS is already a version 2 one, nothing is done.
+// <p>
+// It is possible to do the conversion in place. If not, first a copy
+// is made which is thereafter changed in place.
+// <br>
+// The conversion process does the following steps:
+// <ul>
+// <li> Create the newly required columns and keywords
+// and fill them with new or existing data.
+// <li> Convert the old way of defining measure info to the new
+// TableMeasures way.
+// <li> Rename obsolete columns by prefixing their names with _OBSOLETE_.
+// </ul>
+//
+// The constructor only keeps the names of the input and output MS.
+// The actual conversion is done by the <src>convert</src> function.
+// </synopsis>
+
+
+class MS1ToMS2Converter
+{
+public:
+ // Create the converter for the given output (ms2) and input (ms1) name.
+ // The input name has to be an MS version 1. If not, nothing will be
done.
+ // <br>If <src>inPlace==True</src>, the ms2 name is ignored. In that
+ // case the ms is changed in place.
+ MS1ToMS2Converter (const String& ms2,
+ const String& ms1,
+ Bool inPlace);
+
+ ~MS1ToMS2Converter();
+
+ // Do the actual conversion.
+ Bool convert();
+
+private:
+ // Forbid copy constrcutor and assignment.
+ // <group>
+ MS1ToMS2Converter (const MS1ToMS2Converter&);
+ MS1ToMS2Converter& operator= (const MS1ToMS2Converter&);
+ // </group>
+
+ // If possible remove a column from the table.
+ // Otherwise rename it by prefixing it with _OBSOLETE_.
+ void removeColumn(Table& t, const String& col);
+
+
+ String ms1_p;
+ String ms2_p;
+ Bool inPlace_p;
+
+ // Logger
+ LogIO os_p;
+};
+
+
+
+} //# NAMESPACE CASACORE - END
+
+#endif
=======================================
--- /dev/null
+++ /branches/nov14/ms/MSOper/MSConcat.cc Wed Mar 25 14:33:54 2015 UTC
@@ -0,0 +1,2769 @@
+//# MSConcat.cc: A class for concatenating MeasurementSets.
+//# Copyright (C) 2000,2002,2003
+//# Associated Universities, Inc. Washington DC, USA.
+//#
+//# This library is free software; you can redistribute it and/or modify it
+//# under the terms of the GNU Library General Public License as published
by
+//# the Free Software Foundation; either version 2 of the License, or (at
your
+//# option) any later version.
+//#
+//# This library is distributed in the hope that it will be useful, but
WITHOUT
+//# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+//# FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
+//# License for more details.
+//#
+//# You should have received a copy of the GNU Library General Public
License
+//# along with this library; if not, write to the Free Software Foundation,
+//# Inc., 675 Massachusetts Ave, Cambridge, MA 02139, USA.
+//#
+//# Correspondence concerning AIPS++ should be addressed as follows:
+//# Internet email:
aips2-...@nrao.edu.
+//# Postal address: AIPS++ Project Office
+//# National Radio Astronomy Observatory
+//# 520 Edgemont Road
+//# Charlottesville, VA 22903-2475 USA
+//#
+//# $Id$
+
+#include <casacore/ms/MSOper/MSConcat.h>
+#include <casacore/casa/Arrays/Vector.h>
+#include <casacore/casa/Arrays/Matrix.h>
+#include <casacore/casa/Arrays/ArrayMath.h>
+#include <casacore/casa/Containers/Block.h>
+#include <casacore/casa/Containers/Record.h>
+#include <casacore/casa/Containers/RecordField.h>
+#include <casacore/casa/Containers/RecordFieldId.h>
+#include <casacore/casa/Exceptions/Error.h>
+#include <casacore/casa/Logging/LogIO.h>
+#include <casacore/casa/Logging/LogOrigin.h>
+#include <casacore/casa/BasicMath/Math.h>
+#include <casacore/ms/MeasurementSets/MSAntenna.h>
+#include <casacore/ms/MeasurementSets/MSAntennaColumns.h>
+#include <casacore/ms/MeasurementSets/MSDataDescColumns.h>
+#include <casacore/ms/MeasurementSets/MSFeed.h>
+#include <casacore/ms/MeasurementSets/MSField.h>
+#include <casacore/ms/MeasurementSets/MSFieldColumns.h>
+#include <casacore/ms/MeasurementSets/MSMainColumns.h>
+#include <casacore/ms/MeasurementSets/MSPolColumns.h>
+#include <casacore/ms/MeasurementSets/MSSpWindowColumns.h>
+#include <casacore/measures/Measures/MDirection.h>
+#include <casacore/measures/Measures/MFrequency.h>
+#include <casacore/measures/Measures/MeasConvert.h>
+#include <casacore/measures/TableMeasures/ScalarMeasColumn.h>
+#include <casacore/measures/TableMeasures/ScalarQuantColumn.h>
+#include <casacore/tables/Tables/ColumnsIndex.h>
+#include <casacore/tables/Tables/ScalarColumn.h>
+#include <casacore/tables/Tables/TableDesc.h>
+#include <casacore/tables/Tables/TableRow.h>
+#include <casacore/tables/Tables/TableVector.h>
+#include <casacore/tables/Tables/TabVecMath.h>
+#include <casacore/tables/Tables/TableCopy.h>
+#include <casacore/casa/Utilities/Assert.h>
+#include <casacore/casa/BasicSL/String.h>
+#include <casacore/casa/iostream.h>
+#include <casacore/casa/OS/Path.h>
+#include <casacore/casa/OS/Directory.h>
+
+namespace casacore {
+
+MSConcat::MSConcat(MeasurementSet& ms):
+ MSColumns(ms),
+ itsMS(ms),
+ itsFixedShape(isFixedShape(ms.tableDesc())),
+ newSourceIndex_p(-1), newSourceIndex2_p(-1), newSPWIndex_p(-1),
+ newObsIndexA_p(-1), newObsIndexB_p(-1), otherObsIdsWithCounterpart_p(-1),
+ solSystObjects_p(-1)
+{
+ itsDirTol=Quantum<Double>(1.0, "mas");
+ itsFreqTol=Quantum<Double>(1.0, "Hz");
+ itsWeightScale = 1.;
+ itsRespectForFieldName = False;
+ doSource_p=False;
+ doObsA_p = doObsB_p = False;
+}
+
+IPosition MSConcat::isFixedShape(const TableDesc& td) {
+ IPosition fixedShape(0);
+ Bool isFixed = False;
+ const Vector<String> hypercolumnNames=td.hypercolumnNames();
+ const uInt nHyperCols = hypercolumnNames.nelements();
+ Vector<String> dataColNames,coordColNames,idColNames;
+ uInt hc = 0;
+ while (isFixed == False && hc < nHyperCols) {
+ td.hypercolumnDesc(hypercolumnNames(hc), dataColNames, coordColNames,
+ idColNames);
+ const uInt nDataCol = dataColNames.nelements();
+ uInt dc = 0;
+ while (isFixed == False && dc < nDataCol) {
+ const String& dataColName = dataColNames(dc);
+ // The order of these if conditions is important as I am trying to
get
+ // the biggest possible fixed shape.
+ if (dataColName == MS::columnName(MS::FLAG_CATEGORY) ||
+ dataColName == MS::columnName(MS::DATA) ||
+ dataColName == MS::columnName(MS::FLAG) ||
+ dataColName == MS::columnName(MS::SIGMA_SPECTRUM) ||
+ dataColName == MS::columnName(MS::WEIGHT_SPECTRUM) ||
+ dataColName == MS::columnName(MS::CORRECTED_WEIGHT_SPECTRUM) ||
+ dataColName == MS::columnName(MS::FLOAT_DATA) ||
+ dataColName == MS::columnName(MS::CORRECTED_DATA) ||
+ dataColName == MS::columnName(MS::MODEL_DATA) ||
+ dataColName == MS::columnName(MS::LAG_DATA) ||
+ dataColName == MS::columnName(MS::SIGMA) ||
+ dataColName == MS::columnName(MS::WEIGHT) ||
+ dataColName == MS::columnName(MS::VIDEO_POINT)) {
+ const ColumnDesc& colDesc = td.columnDesc(dataColNames(dc));
+ isFixed = colDesc.isFixedShape();
+ if (isFixed) fixedShape = colDesc.shape();
+ }
+ dc++;
+ }
+ hc++;
+ dataColNames.resize(0);
+ coordColNames.resize(0);
+ idColNames.resize(0);
+ }
+ return fixedShape;
+}
+
+ Bool MSConcat::checkEphIdInField(const ROMSFieldColumns& otherFldCol)
const {
+ // test if this MS FIELD table has an ephID column
+
if(!itsMS.field().actualTableDesc().isColumn(MSField::columnName(MSField::EPHEMERIS_ID))){
+ // if not, test if the other MS uses ephem objects
+ Bool usesEphems = False;
+ for(uInt i=0; i<otherFldCol.nrow(); i++){
+ if(!otherFldCol.ephemPath(i).empty()){
+ usesEphems = True;
+ break;
+ }
+ }
+ if(usesEphems){ // if yes, the ephID column needs to be added to this
MS FIELD table
+ return False;
+ }
+ }
+ return True;
+}
+
+
+ void MSConcat::virtualconcat(MeasurementSet& otherMS,
+ const Bool checkShapeAndCateg,
+ const String& obsidAndScanTableName)
+{
+ LogIO log(LogOrigin("MSConcat", "virtualconcat", WHERE));
+
+
+ Bool reindexObsidAndScan=!obsidAndScanTableName.empty();
+
+ // check if certain columns are present and set flags accordingly
+ Bool doCorrectedData=False, doModelData=False;
+ Bool doFloatData=False;
+
+ if (itsMS.tableDesc().isColumn("FLOAT_DATA") &&
+ otherMS.tableDesc().isColumn("FLOAT_DATA"))
+ doFloatData=True;
+ else if (itsMS.tableDesc().isColumn("FLOAT_DATA") &&
+ !otherMS.tableDesc().isColumn("FLOAT_DATA")){
+ log << itsMS.tableName()
+ << " has FLOAT_DATA column but not " << otherMS.tableName()
+ << LogIO::EXCEPTION;
+ log << "Cannot concatenate these MSs yet...you may split the corrected
column of the SD as a work around."
+ << LogIO::EXCEPTION;
+ }
+ if (itsMS.tableDesc().isColumn("MODEL_DATA") &&
+ otherMS.tableDesc().isColumn("MODEL_DATA"))
+ doModelData=True;
+ else if (itsMS.tableDesc().isColumn("MODEL_DATA") &&
+ !otherMS.tableDesc().isColumn("MODEL_DATA")){
+ log << itsMS.tableName()
+ << " has MODEL_DATA column but not " << otherMS.tableName()
+ << LogIO::EXCEPTION;
+ log << "You may wish to create this column by loading "
+ << otherMS.tableName()
+ << " in imager or calibrater "
+ << LogIO::EXCEPTION;
+ }
+ if (itsMS.tableDesc().isColumn("CORRECTED_DATA") &&
+ otherMS.tableDesc().isColumn("CORRECTED_DATA"))
+ doCorrectedData=True;
+ else if (itsMS.tableDesc().isColumn("CORRECTED_DATA") &&
+ !otherMS.tableDesc().isColumn("CORRECTED_DATA"))
+ log << itsMS.tableName()
+ <<" has CORRECTED_DATA column but not " << otherMS.tableName()
+ << LogIO::EXCEPTION;
+
+ {
+ const ROMSFieldColumns otherMSFCols(otherMS.field());
+ if(!checkEphIdInField(otherMSFCols)){
+ log << "EPHEMERIS_ID column missing in FIELD table of MS " <<
itsMS.tableName()
+ << LogIO::EXCEPTION;
+ }
+ }
+
+ if(checkShapeAndCateg){
+ // verify that shape of the two MSs as described in POLARISATION, SPW,
and DATA_DESCR
+ // is the same
+ if (otherMS.nrow() > 0) {
+ if (itsFixedShape.nelements() > 0) {
+ const ROMSPolarizationColumns otherPolCols(otherMS.polarization());
+ const ROMSSpWindowColumns otherSpwCols(otherMS.spectralWindow());
+ const ROMSDataDescColumns otherDDCols(otherMS.dataDescription());
+ const uInt nShapes = otherDDCols.nrow();
+ for (uInt s = 0; s < nShapes; s++) {
+ checkShape(getShape(otherDDCols, otherSpwCols, otherPolCols, s));
+ }
+ }
+ const ROMSMainColumns otherMainCols(otherMS);
+ checkCategories(otherMainCols);
+ }
+ }
+
+ // merge STATE
+ Block<uInt> newStateIndices; // INTO TABLE
+ Bool doState = False;
+ // STATE is a required subtable but can be empty in which case the state
id in the main table is -1
+ Bool itsStateNull = (itsMS.state().isNull() || (itsMS.state().nrow() ==
0));
+ Bool otherStateNull = (otherMS.state().isNull() ||
(otherMS.state().nrow() == 0));
+
+ if(itsStateNull && otherStateNull){
+ log << LogIO::NORMAL << "No valid state tables present. Result won't
have one either." << LogIO::POST;
+ }
+ else if(itsStateNull && !otherStateNull){
+ log << LogIO::WARN << itsMS.tableName() << " does not have a valid
state table," << endl
+ << " the MS to be appended, however, has one. Result won't have one."
+ << LogIO::POST;
+ doState = True; // i.e. the appended MS Main table state id will have
to be set to -1
+ }
+ else if(!itsStateNull && otherStateNull){
+ log << LogIO::WARN << itsMS.tableName() << " does have a valid state
table," << endl
+ << " the MS to be appended, however, doesn't. Result won't have one."
+ << LogIO::POST;
+ doState = True; // i.e. itsMS Main table state id will have to be set
to -1
+
+ Vector<uInt> delrows(itsMS.state().nrow());
+ indgen(delrows);
+ itsMS.state().removeRow(delrows);
+ }
+ else{ // both state tables are filled
+ const uInt oldStateRows = itsMS.state().nrow();
+ newStateIndices = copyState(otherMS.state());
+ const uInt addedRows = itsMS.state().nrow() - oldStateRows;
+ const uInt matchedRows = otherMS.state().nrow() - addedRows;
+ log << "Added " << addedRows
+ << " rows and matched " << matchedRows
+ << " from the state subtable" << LogIO::POST;
+ doState = True; // state id entries in the main table will have to be
modified for otherMS
+ }
+
+ //See if there is a SOURCE table and concatenate and reindex it
+ {
+ uInt oldSRows = itsMS.source().nrow();
+ copySource(otherMS);
+ if(Table::isReadable(itsMS.sourceTableName())){
+ uInt addedRows = itsMS.source().nrow() - oldSRows;
+ if(addedRows>0){
+ log << "Added " << addedRows
+ << " rows to the source subtable" << LogIO::POST;
+ }
+ }
+ }
+
+ // DATA_DESCRIPTION
+ uInt oldRows = itsMS.dataDescription().nrow();
+ uInt oldSPWRows = itsMS.spectralWindow().nrow();
+ const Block<uInt> newDDIndices = copySpwAndPol(otherMS.spectralWindow(),
+ otherMS.polarization(),
+ otherMS.dataDescription());
+ {
+ uInt addedRows = itsMS.dataDescription().nrow() - oldRows;
+ uInt matchedRows = otherMS.dataDescription().nrow() - addedRows;
+ log << "Added " << addedRows
+ << " rows and matched " << matchedRows
+ << " from the data description subtable" << LogIO::POST;
+ addedRows = itsMS.spectralWindow().nrow() - oldSPWRows;
+ matchedRows = otherMS.spectralWindow().nrow() - addedRows;
+ log << "Added " << addedRows
+ << " rows and matched " << matchedRows
+ << " from the spectral window subtable" << LogIO::POST;
+ }
+
+ // correct the spw entries in the SOURCE table and remove redundant rows
+ oldRows = itsMS.source().nrow();
+ updateSource();
+ if(Table::isReadable(itsMS.sourceTableName())){
+ uInt removedRows = oldRows - itsMS.source().nrow();
+ if(removedRows>0){
+ log << "Removed " << removedRows
+ << " redundant rows from the source subtable" << LogIO::POST;
+ }
+ }
+
+ // merge ANTENNA and FEED
+ oldRows = itsMS.antenna().nrow();
+ uInt oldFeedRows = itsMS.feed().nrow();
+ const Block<uInt> newAntIndices = copyAntennaAndFeed(otherMS.antenna(),
+ otherMS.feed());
+ Bool antIndexTrivial = True;
+ for(uInt ii=0; ii<newAntIndices.size(); ii++){
+ //cout << "i, newAntIndices(i) " << ii << " " << newAntIndices[ii] <<
endl;
+ if(newAntIndices[ii]!=ii){
+ antIndexTrivial=False;
+ break;
+ }
+ }
+ {
+ uInt addedRows = itsMS.antenna().nrow() - oldRows;
+ uInt matchedRows = otherMS.antenna().nrow() - addedRows;
+ log << "Added " << addedRows
+ << " rows and matched " << matchedRows
+ << " from the antenna subtable" << endl;
+ addedRows = itsMS.feed().nrow() - oldFeedRows;
+ log << "Added " << addedRows
+ << " rows to the feed subtable" << endl;
+ }
+
+
+ // FIELD
+ oldRows = itsMS.field().nrow();
+ const Block<uInt> newFldIndices = copyField(otherMS);
+ {
+ const uInt addedRows = itsMS.field().nrow() - oldRows;
+ const uInt matchedRows = otherMS.field().nrow() - addedRows;
+ log << "Added " << addedRows
+ << " rows and matched " << matchedRows
+ << " from the field subtable" << LogIO::POST;
+ }
+
+ // OBSERVATION
+ copyObservation(otherMS.observation(), True);
+
+ // POINTING
+ if(!antIndexTrivial){
+ copyPointingB(otherMS.pointing(), newAntIndices);
+ }
+
+ /////////////////////////////////////////////////////
+
+ // copying all subtables over to otherMS
+ // will need to be done when creating the MMS from the concatenated MSs
+
+ //////////////////////////////////////////////////////
+
+ MSMainColumns mainCols(itsMS);
+ MSMainColumns otherMainCols(otherMS);
+
+ const uInt otherRows = otherMS.nrow();
+ const uInt theseRows = itsMS.nrow();
+
+ // create column objects for those columns which potentially need to be
modified
+
+ ArrayColumn<Complex> otherData;
+ ArrayColumn<Float> otherFloatData;
+ ArrayColumn<Complex> otherModelData, otherCorrectedData;
+
+ if(doFloatData){
+ otherFloatData.reference(otherMainCols.floatData());
+ }
+ else{
+ otherData.reference(otherMainCols.data());
+ }
+
+ if(doCorrectedData){
+ otherCorrectedData.reference(otherMainCols.correctedData());
+ }
+ if(doModelData){
+ otherModelData.reference(otherMainCols.modelData());
+ }
+
+ ArrayColumn<Double>& otherUvw = otherMainCols.uvw();
+ ArrayColumn<Float>& otherWeight = otherMainCols.weight();
+ ArrayColumn<Float>& otherWeightSp = otherMainCols.weightSpectrum();
+
+ ScalarColumn<Int>& otherAnt1Col = otherMainCols.antenna1();
+ ScalarColumn<Int>& otherAnt2Col = otherMainCols.antenna2();
+ ScalarColumn<Int>& otherDDIdCol = otherMainCols.dataDescId();
+ ScalarColumn<Int>& otherFieldIdCol = otherMainCols.fieldId();
+ ScalarColumn<Int>& otherScanCol = otherMainCols.scanNumber();
+ ScalarColumn<Int>& otherStateIdCol = otherMainCols.stateId();
+ ScalarColumn<Int>& otherObsIdCol =otherMainCols.observationId();
+
+ ScalarColumn<Int>& thisScanCol = mainCols.scanNumber();
+ ScalarColumn<Int>& thisStateIdCol = mainCols.stateId();
+ ScalarColumn<Int>& thisObsIdCol = mainCols.observationId();
+
+ Vector<Int> otherAnt1;
+ Vector<Int> otherAnt2;
+
+ if(!antIndexTrivial){
+ otherAnt1 = otherAnt1Col.getColumn();
+ otherAnt2 = otherAnt2Col.getColumn();
+ }
+
+ Vector<Int> otherDDId = otherDDIdCol.getColumn();
+ Vector<Int> otherFieldId = otherFieldIdCol.getColumn();
+ Vector<Int> otherScan = otherScanCol.getColumn();
+ Vector<Int> otherStateId(otherMS.nrow(),-1);
+ Vector<Int> otherObsIds;
+
+ if (doState && !otherStateNull){
+ otherStateId = otherStateIdCol.getColumn();
+ }
+
+ Int defaultScanOffset=0;
+ SimpleOrderedMap <Int, Int> scanOffsetForOid(-1);
+ SimpleOrderedMap <Int, Int> encountered(-1);
+ vector<Int> distinctObsIdSet;
+ vector<Int> minScan;
+ vector<Int> maxScan;
+
+ if(reindexObsidAndScan){
+
+ otherObsIds = otherObsIdCol.getColumn();
+ Vector<Int> theseObsIds=thisObsIdCol.getColumn();
+ Vector<Int> theseScans=thisScanCol.getColumn();
+
+ if(doObsA_p){ // the obs ids changed for the first table
+ for(uInt r = 0; r < theseRows; r++) {
+ if(newObsIndexA_p.isDefined(theseObsIds[r])){ // apply change
+ theseObsIds[r] = newObsIndexA_p(theseObsIds[r]);
+ }
+ }
+ thisObsIdCol.putColumn(theseObsIds);
+ }
+
+ // SCAN NUMBER
+ // find the distinct ObsIds in use in this MS
+ // and the maximum scan ID in each of them
+
+ Int maxScanThis=0;
+
+ // read the initial values from a file if it exists
+ std::ifstream ifs;
+ ifs.open(obsidAndScanTableName.c_str(), ifstream::in);
+ if (ifs.good()) {
+ log << LogIO::NORMAL << "Reading from " << obsidAndScanTableName <<
LogIO::POST;
+ uInt n;
+ Int tobsid, tminscan, tmaxscan;
+ ifs >> n;
+ for(uInt i=0; i<n; i++){
+ if(ifs.good()){
+ ifs >> tobsid; distinctObsIdSet.push_back(tobsid);
+ ifs >> tminscan; minScan.push_back(tminscan);
+ ifs >> tmaxscan; maxScan.push_back(tmaxscan);
+ }
+ else{
+ log << LogIO::WARN << "Error reading file " << obsidAndScanTableName <<
LogIO::POST;
+ break;
+ }
+ }
+ if(ifs.good()){
+ ifs >> maxScanThis;
+ }
+ else{
+ log << LogIO::WARN << "Error reading file " << obsidAndScanTableName <<
LogIO::POST;
+ log << LogIO::WARN << "Will continue with uninitialized obsid and scans
information" << LogIO::POST;
+ distinctObsIdSet.resize(0);
+ minScan.resize(0);
+ maxScan.resize(0);
+ maxScanThis=0;
+ }
+ //cout << "distinctObsIdSet " << Vector<Int>(distinctObsIdSet) <<
endl;
+ //cout << "minScan " << Vector<Int>(minScan) << endl;
+ //cout << "maxScan " << Vector<Int>(maxScan) << endl;
+ //cout << "maxScanThis " << maxScanThis << endl;
+ }
+ else{
+ log << LogIO::NORMAL << "Will create auxiliary file " <<
obsidAndScanTableName << LogIO::POST;
+
+ // determine the values for distinctObsIdSet, minScan, maxScanThis
from scratch
+ for(uInt r = 0; r < theseRows; r++) {
+ Int oid = theseObsIds[r];
+ Int scanid = theseScans[r];
+ Bool found = False;
+ uInt i;
+ for(i=0; i<distinctObsIdSet.size(); i++){
+ if(distinctObsIdSet[i]==oid){
+ found = True;
+ break;
+ }
+ }
+ if(found){
+ if(scanid<minScan[i]){
+ minScan[i] = scanid;
+ }
+ if(scanid>maxScan[i]){
+ maxScan[i] = scanid;
+ }
+ }
+ else {
+ distinctObsIdSet.push_back(oid);
+ minScan.push_back(scanid);
+ maxScan.push_back(scanid);
+ }
+ if(scanid>maxScanThis){
+ maxScanThis = scanid;
+ }
+ }
+
+ }
+ ifs.close();
+
+
+ // set the offset added to scan numbers in each observation
+ Int minScanOther = min(otherScan);
+ {
+ defaultScanOffset = maxScanThis + 1 - minScanOther;
+ if(defaultScanOffset<0){
+ defaultScanOffset=0;
+ }
+ }
+
+ for(uInt i=0; i<distinctObsIdSet.size(); i++){
+ Int scanOffset;
+ if(otherObsIdsWithCounterpart_p.isDefined(distinctObsIdSet[i]) &&
i!=0){
+ // This observation is present in both this and the other MS.
+ // Need to set the scanOffset based on previous observation
+ scanOffset = maxScan[i-1] + 1 - minScanOther;
+ }
+ else{
+ scanOffset = minScan[i] - 1; // assume scan numbers originally start at 1
+ }
+ if(scanOffset<0){
+ log << LogIO::WARN << "Zero or negative scan numbers in MS. May lead to
duplicate scan numbers in concatenated MS."
+ << LogIO::POST;
+ scanOffset = 0;
+ }
+ if(scanOffset==0){
+ encountered.define(distinctObsIdSet[i],0); // used later to decide
whether to notify user
+ }
+ scanOffsetForOid.define(distinctObsIdSet[i], scanOffset);
+ }
+
+
+ } // end if reindexObsidAndScan
+
+ if(doState && otherStateNull){ // the state ids for the first table will
have to be set to -1
+ Vector<Int> tempV(theseRows, -1);
+ thisStateIdCol.putColumn(tempV);
+ }
+
+ // finished all modifications of MS Main table one
+
+ // now start modifications of the second one
+
+ log << LogIO::NORMAL << "Working on appended Main table ..." <<
LogIO::POST;
+
+
+ Bool copyWtSp = (!otherWeightSp.isNull()) && otherWeightSp.isDefined(0);
+
+ // MAIN
+
+ Bool doWeightScale = (itsWeightScale!=1.);
+
+ if(reindexObsidAndScan){
+ for (uInt r = 0; r < otherRows; r++) {
+ Int oid = 0;
+ if(doObsB_p && newObsIndexB_p.isDefined(otherObsIds[r])){
+ // the obs ids have been changed for the table to be appended
+ oid = newObsIndexB_p(otherObsIds[r]);
+ }
+ else{ // this OBS id didn't change
+ oid = otherObsIds[r];
+ }
+
+ if(oid != otherObsIds[r]){ // obsid actually changed
+ if(!scanOffsetForOid.isDefined(oid)){ // offset not set, use default
+ scanOffsetForOid.define(oid, defaultScanOffset);
+ }
+ if(!encountered.isDefined(oid) && scanOffsetForOid(oid)!=0){
+ log << LogIO::NORMAL << "Will offset scan numbers by " <<
scanOffsetForOid(oid)
+ << " for observations with Obs ID " << oid
+ << " in order to make scan numbers unique." << LogIO::POST;
+ encountered.define(oid,0);
+ }
+ otherScan[r] = otherScan[r] + scanOffsetForOid(oid);
+ }
+
+ otherObsIds[r] = oid;
+
+ }
+
+ // update or create the file with the initial values for the next
concat
+
+ Int maxScanOther = 0;
+ for(uInt r = 0; r < otherRows; r++) {
+ Int oid = otherObsIds[r];
+ Int scanid = otherScan[r];
+ Bool found = False;
+ uInt i;
+ for(i=0; i<distinctObsIdSet.size(); i++){
+ if(distinctObsIdSet[i]==oid){
+ found = True;
+ break;
+ }
+ }
+ if(found){
+ if(scanid<minScan[i]){
+ minScan[i] = scanid;
+ }
+ if(scanid>maxScan[i]){
+ maxScan[i] = scanid;
+ }
+ }
+ else {
+ distinctObsIdSet.push_back(oid);
+ minScan.push_back(scanid);
+ maxScan.push_back(scanid);
+ }
+ if(scanid>maxScanOther){
+ maxScanOther = scanid;
+ }
+ }
+
+ std::ofstream ofs;
+ ofs.open (obsidAndScanTableName.c_str(), ofstream::out);
+ if (!ofs) {
+ log << LogIO::WARN << "Error opening file " << obsidAndScanTableName
+ << "will continue but the next virtual concat will lack this
information:" << LogIO::POST;
+ log << "distinctObsIdSet " << Vector<Int>(distinctObsIdSet) << endl;
+ log << "minScan " << Vector<Int>(minScan) << endl;
+ log << "maxScan " << Vector<Int>(maxScan) << endl;
+ log << "maxScanOther " << maxScanOther << LogIO::POST;
+ }
+ else{
+ log << LogIO::NORMAL << "Writing to " << obsidAndScanTableName <<
LogIO::POST;
+ uInt n = distinctObsIdSet.size();
+ ofs << n << endl;
+ for(uInt i=0; i<n; i++){
+ ofs << distinctObsIdSet[i] << endl;
+ ofs << minScan[i] << endl;
+ ofs << maxScan[i] << endl;
+ }
+ ofs << maxScanOther << endl; // note: this max is determined after
the modification of scanOther
+ }
+ ofs.close();
+
+
+ }
+
+ if(doState){
+ for (uInt r = 0; r < otherRows; r++) {
+ if(!(itsStateNull || otherStateNull)){
+ otherStateId[r] = newStateIndices[otherStateId[r]];
+ }
+ }
+ }
+
+ for (uInt r = 0; r < otherRows; r++) {
+
+ Bool doConjugateVis = False;
+
+ if(!antIndexTrivial){
+ Int newA1 = newAntIndices[otherAnt1[r]];
+ Int newA2 = newAntIndices[otherAnt2[r]];
+
+ if(newA1>newA2){ // swap indices and multiply UVW by -1
+ //cout << " corrected order r: " << r << " " << newA2 << " " << newA1
<< endl;
+ otherAnt1[r] = newA2;
+ otherAnt2[r] = newA1;
+ Array<Double> newUvw;
+ newUvw.assign(otherUvw(r));
+ //cout << " old UVW " << newUvw;
+ newUvw *= -1.;
+ //cout << ", new UVW " << newUvw << endl;
+ otherUvw.put(r, newUvw);
+ doConjugateVis = True;
+ }
+ else{
+ otherAnt1[r] = newA1;
+ otherAnt2[r] = newA2;
+ }
+ }
+
+ if(itsChanReversed[otherDDId[r]]){
+
+ Vector<Int> datShape;
+ Matrix<Complex> reversedData;
+ Matrix<Float> reversedFloatData;
+ if(doFloatData){
+ datShape=otherFloatData.shape(r).asVector();
+ reversedFloatData.resize(datShape[0], datShape[1]);
+ }
+ else{
+ datShape=otherData.shape(r).asVector();
+ reversedData.resize(datShape[0], datShape[1]);
+ }
+ Matrix<Complex> reversedCorrData(datShape[0], datShape[1]);
+ Matrix<Complex> reversedModData(datShape[0], datShape[1]);
+ for (Int k1=0; k1 < datShape[0]; ++k1){
+ for(Int k2=0; k2 < datShape[1]; ++k2){
+ if(doFloatData){
+ reversedFloatData(k1,k2)=(Matrix<Float>(otherFloatData(r)))(k1,
+ datShape[1]-1-k2);
+ }
+ else{
+ reversedData(k1,k2)=(Matrix<Complex>(otherData(r)))(k1,
+ datShape[1]-1-k2);
+ }
+ if(doModelData){
+ reversedModData(k1,k2)=(Matrix<Complex>(otherModelData(r)))(k1,
+ datShape[1]-1-k2);
+ }
+ if(doCorrectedData){
+ reversedCorrData(k1,k2)=(Matrix<Complex>(otherCorrectedData(r)))(k1,
+ datShape[1]-1-k2);
+ }
+
+ }
+ }
+ if(doFloatData){
+ otherFloatData.put(r, reversedFloatData);
+ }
+ else{
+ if(doConjugateVis){
+ otherData.put(r, conj(reversedData));
+ }
+ else{
+ otherData.put(r, reversedData);
+ }
+ }
+ if(doCorrectedData){
+ if(doConjugateVis){
+ otherCorrectedData.put(r, conj(reversedCorrData));
+ }
+ else{
+ otherCorrectedData.put(r, reversedCorrData);
+ }
+ }
+ if(doModelData){
+ if(doConjugateVis){
+ otherModelData.put(r, conj(reversedModData));
+ }
+ else{
+ otherModelData.put(r, reversedModData);
+ }
+ }
+ }
+ else{ // no reversal
+ if(!doFloatData){
+ if(doConjugateVis){ // conjugate because order of antennas was reversed
+ otherData.put(r, conj(otherData(r)));
+ }
+ }
+ if(doModelData){
+ if(doConjugateVis){
+ otherModelData.put(r, conj(otherModelData(r)));
+ }
+ }
+ if(doCorrectedData){
+ if(doConjugateVis){
+ otherCorrectedData.put(r, conj(otherCorrectedData(r)));
+ }
+ }
+ } // end if itsChanReversed
+
+ otherDDId[r] = newDDIndices[otherDDId[r]];
+ otherFieldId[r] = newFldIndices[otherFieldId[r]];
+
+ if(doWeightScale){
+ otherWeight.put(r, otherWeight(r)*itsWeightScale);
+ if (copyWtSp) otherWeightSp.put(r, otherWeightSp(r)*itsWeightScale);
+ }
+
+ } // end for
+
+ // write the scalar columns
+
+ log << LogIO::NORMAL << "Writing the scalar columns ..." << LogIO::POST;
+
+ if(!antIndexTrivial){
+ otherAnt1Col.putColumn(otherAnt1);
+ otherAnt2Col.putColumn(otherAnt2);
+ }
+ otherDDIdCol.putColumn(otherDDId);
+ otherFieldIdCol.putColumn(otherFieldId);
+
+ if(doState && !(itsStateNull || otherStateNull)){
+ otherStateIdCol.putColumn(otherStateId);
+ }
+
+ if(reindexObsidAndScan){
+ otherScanCol.putColumn(otherScan);
+ otherObsIdCol.putColumn(otherObsIds);
+ }
+
+ if(doModelData){ //update the MODEL_DATA keywords
+ updateModelDataKeywords(otherMS);
+ }
+
+}
+
+
+ //--------------------------------------------------------------------
+
+ void MSConcat::concatenate(const MeasurementSet& otherMS,
+ const uInt handling,
+ const String& destMSName)
+{
+ LogIO log(LogOrigin("MSConcat", "concatenate", WHERE));
+
+ if(destMSName.empty()){
+ log << "Appending " << otherMS.tableName() << " to " <<
itsMS.tableName() << endl << LogIO::POST;
+ }
+ else{
+ log << "Virtually appending " << otherMS.tableName() << " to " <<
itsMS.tableName() << endl << LogIO::POST;
+ }
+
+ switch(handling){
+ case 0: // normal concat
+ break;
+ case 1:
+ log << "*** At user\'s request, MAIN table will not be concatenated!"
<< LogIO::POST;
+ break;
+ case 2:
+ log << "*** At user\'s request, POINTING table will not be
concatenated!" << LogIO::POST;
+ break;
+ case 3:
+ log << "*** At user\'s request, MAIN and POINTING tables will not be
concatenated!" << LogIO::POST;
+ break;
+ default:
+ log << "Invalid value for handling switch: " << handling << " (valid
range is 0 - 3)"
+ << LogIO::EXCEPTION;
+ break;
+ }
+
+ // check if certain columns are present and set flags accordingly
+ Bool doCorrectedData=False, doModelData=False;
+ Bool doFloatData=False;
+
+ if(handling==0 || handling==2){
+
+ if (itsMS.tableDesc().isColumn("FLOAT_DATA") &&
+ otherMS.tableDesc().isColumn("FLOAT_DATA"))
+ doFloatData=True;
+ else if (itsMS.tableDesc().isColumn("FLOAT_DATA") &&
+ !otherMS.tableDesc().isColumn("FLOAT_DATA")){
+ log << itsMS.tableName()
+ << " has FLOAT_DATA column but not " << otherMS.tableName()
+ << LogIO::EXCEPTION;
+ log << "Cannot concatenate these MSs yet...you may split the
corrected column of the SD as a work around."
+ << LogIO::EXCEPTION;
+ }
+ if (itsMS.tableDesc().isColumn("MODEL_DATA") &&
+ otherMS.tableDesc().isColumn("MODEL_DATA"))
+ doModelData=True;
+ else if (itsMS.tableDesc().isColumn("MODEL_DATA") &&
+ !otherMS.tableDesc().isColumn("MODEL_DATA")){
+ log << itsMS.tableName()
+ << " has MODEL_DATA column but not " << otherMS.tableName()
+ << LogIO::EXCEPTION;
+ log << "You may wish to create this column by loading "
+ << otherMS.tableName()
+ << " in imager or calibrater "
+ << LogIO::EXCEPTION;
+ }
+ if (itsMS.tableDesc().isColumn("CORRECTED_DATA") &&
+ otherMS.tableDesc().isColumn("CORRECTED_DATA"))
+ doCorrectedData=True;
+ else if (itsMS.tableDesc().isColumn("CORRECTED_DATA") &&
+ !otherMS.tableDesc().isColumn("CORRECTED_DATA"))
+ log << itsMS.tableName()
+ <<" has CORRECTED_DATA column but not " << otherMS.tableName()
+ << LogIO::EXCEPTION;
+ }
+
+ {
+ const ROMSFieldColumns otherMSFCols(otherMS.field());
+ if(!checkEphIdInField(otherMSFCols)){
+ log << "EPHEMERIS_ID column missing in FIELD table of MS " <<
itsMS.tableName()
+ << LogIO::EXCEPTION;
+ }
+ }
+
+ // verify that shape of the two MSs as described in POLARISATION, SPW,
and DATA_DESCR
+ // is the same
+ const ROMSMainColumns otherMainCols(otherMS);
+ if (otherMS.nrow() > 0) {
+ if (itsFixedShape.nelements() > 0) {
+ const ROMSPolarizationColumns otherPolCols(otherMS.polarization());
+ const ROMSSpWindowColumns otherSpwCols(otherMS.spectralWindow());
+ const ROMSDataDescColumns otherDDCols(otherMS.dataDescription());
+ const uInt nShapes = otherDDCols.nrow();
+ for (uInt s = 0; s < nShapes; s++) {
+ checkShape(getShape(otherDDCols, otherSpwCols, otherPolCols, s));
+ }
+ }
+ checkCategories(otherMainCols);
+ }
+
+ log << LogIO::DEBUG1 << "ms shapes verified " << endl << LogIO::POST;
+
+ // merge STATE
+ Block<uInt> newStateIndices;
+ Bool doState = False;
+ // STATE is a required subtable but can be empty in which case the state
id in the main table is -1
+ Bool itsStateNull = (itsMS.state().isNull() || (itsMS.state().nrow() ==
0));
+ Bool otherStateNull = (otherMS.state().isNull() ||
(otherMS.state().nrow() == 0));
+
+ if(itsStateNull && otherStateNull){
+ log << LogIO::NORMAL << "No valid state tables present. Result won't
have one either." << LogIO::POST;
+ }
+ else if(itsStateNull && !otherStateNull){
+ log << LogIO::WARN << itsMS.tableName() << " does not have a valid
state table," << endl
+ << " the MS to be appended, however, has one. Result won't have one."
+ << LogIO::POST;
+ doState = True; // i.e. the appended MS Main table state id will have
to be set to -1
+ }
+ else if(!itsStateNull && otherStateNull){
+ log << LogIO::WARN << itsMS.tableName() << " does have a valid state
table," << endl
+ << " the MS to be appended, however, doesn't. Result won't have one."
+ << LogIO::POST;
+ doState = True; // i.e. itsMS Main table state id will have to be set
to -1
+
+ Vector<uInt> delrows(itsMS.state().nrow());
+ indgen(delrows);
+ itsMS.state().removeRow(delrows);
+ }
+ else{ // both state tables are filled
+ const uInt oldStateRows = itsMS.state().nrow();
+ newStateIndices = copyState(otherMS.state());
+ const uInt addedRows = itsMS.state().nrow() - oldStateRows;
+ const uInt matchedRows = otherMS.state().nrow() - addedRows;
+ log << "Added " << addedRows
+ << " rows and matched " << matchedRows
+ << " from the state subtable" << LogIO::POST;
+ doState = True; // state id entries in the main table will have to be
modified for otherMS
+ }
+
+ //See if there is a SOURCE table and concatenate and reindex it
+ {
+ uInt oldSRows = itsMS.source().nrow();
+ copySource(otherMS);
+ if(Table::isReadable(itsMS.sourceTableName())){
+ uInt addedRows = itsMS.source().nrow() - oldSRows;
+ if(addedRows>0){
+ log << "Added " << addedRows
+ << " rows to the source subtable" << LogIO::POST;
+ }
+ }
+ }
+
+
+ // DATA_DESCRIPTION
+ uInt oldRows = itsMS.dataDescription().nrow();
+ uInt oldSPWRows = itsMS.spectralWindow().nrow();
+ const Block<uInt> newDDIndices = copySpwAndPol(otherMS.spectralWindow(),
+ otherMS.polarization(),
+ otherMS.dataDescription());
+
+ {
+ uInt addedRows = itsMS.dataDescription().nrow() - oldRows;
+ uInt matchedRows = otherMS.dataDescription().nrow() - addedRows;
+ log << "Added " << addedRows
+ << " rows and matched " << matchedRows
+ << " from the data description subtable" << LogIO::POST;
+ addedRows = itsMS.spectralWindow().nrow() - oldSPWRows;
+ matchedRows = otherMS.spectralWindow().nrow() - addedRows;
+ log << "Added " << addedRows
+ << " rows and matched " << matchedRows
+ << " from the spectral window subtable" << LogIO::POST;
+ }
+
+
+ // correct the spw entries in the SOURCE table and remove redundant rows
+ oldRows = itsMS.source().nrow();
+ updateSource();
+ if(Table::isReadable(itsMS.sourceTableName())){
+ uInt removedRows = oldRows - itsMS.source().nrow();
+ if(removedRows>0){
+ log << "Removed " << removedRows
+ << " redundant rows from the source subtable" << LogIO::POST;
+ }
+ }
+
+
+ // merge ANTENNA and FEED
+ oldRows = itsMS.antenna().nrow();
+ uInt oldFeedRows = itsMS.feed().nrow();
+ const Block<uInt> newAntIndices = copyAntennaAndFeed(otherMS.antenna(),
+ otherMS.feed());
+ {
+ uInt addedRows = itsMS.antenna().nrow() - oldRows;
+ uInt matchedRows = otherMS.antenna().nrow() - addedRows;
+ log << "Added " << addedRows
+ << " rows and matched " << matchedRows
+ << " from the antenna subtable" << endl;
+ addedRows = itsMS.feed().nrow() - oldFeedRows;
+ log << "Added " << addedRows
+ << " rows to the feed subtable" << endl;
+ }
+
***The diff for this file has been truncated for email.***
=======================================
--- /dev/null
+++ /branches/nov14/ms/MSOper/MSConcat.h Wed Mar 25 14:33:54 2015 UTC
@@ -0,0 +1,204 @@
+//# MSConcat.h: A class for concatenating MeasurementSets.
+//# Copyright (C) 2000,2002,2003
+//# Associated Universities, Inc. Washington DC, USA.
+//#
+//# This library is free software; you can redistribute it and/or modify it
+//# under the terms of the GNU Library General Public License as published
by
+//# the Free Software Foundation; either version 2 of the License, or (at
your
+//# option) any later version.
+//#
+//# This library is distributed in the hope that it will be useful, but
WITHOUT
+//# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+//# FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
+//# License for more details.
+//#
+//# You should have received a copy of the GNU Library General Public
License
+//# along with this library; if not, write to the Free Software Foundation,
+//# Inc., 675 Massachusetts Ave, Cambridge, MA 02139, USA.
+//#
+//# Correspondence concerning AIPS++ should be addressed as follows:
+//# Internet email:
aips2-...@nrao.edu.
+//# Postal address: AIPS++ Project Office
+//# National Radio Astronomy Observatory
+//# 520 Edgemont Road
+//# Charlottesville, VA 22903-2475 USA
+//#
+//#
+//# $Id$
+
+#ifndef MS_MSCONCAT_H
+#define MS_MSCONCAT_H
+
+#include <casacore/casa/aips.h>
+#include <casacore/ms/MeasurementSets/MSColumns.h>
+#include <casacore/ms/MeasurementSets/MeasurementSet.h>
+#include <casacore/casa/Arrays/IPosition.h>
+
+namespace casacore { //# NAMESPACE CASACORE - BEGIN
+
+class TableDesc;
+class ROMSMainColumns;
+class ROMSDataDescColumns;
+class ROMSSpWindowColumns;
+class ROMSPolarizationColumns;
+class MSAntenna;
+class MSDataDescription;
+class MSFeed;
+class MSField;
+class MSPolarization;
+class MSSpectralWindow;
+template <class T> class Block;
+
+// <summary>A class with functions for concatenating
MeasurementSets</summary>
+
+// <use visibility=export>
+
+// <reviewed reviewer="" date="yyyy/mm/dd" tests="" demos="">
+// </reviewed>
+
+// <prerequisite>
+// <li> SomeClass
+// <li> SomeOtherClass
+// <li> some concept
+// </prerequisite>
+//
+// <etymology>
+// </etymology>
+//
+// <synopsis>
+// </synopsis>
+//
+// <example>
+// </example>
+//
+// <motivation>
+// </motivation>
+//
+// <templating arg=T>
+// <li>
+// <li>
+// </templating>
+//
+// <thrown>
+// <li>
+// <li>
+// </thrown>
+//
+// <todo asof="yyyy/mm/dd">
+// <li> add this feature
+// <li> fix this bug
+// <li> start discussion of this possible extension
+// </todo>
+
+class MSConcat: public MSColumns
+{
+public:
+ MSConcat(MeasurementSet& ms);
+
+ void virtualconcat(MeasurementSet& otherMS,
+ const Bool checkShapeAndCateg=True,
+ const String& obsidAndScanTableName="");
+
+ void concatenate(const MeasurementSet& otherMS,
+ const uInt handling=0, // 0 (default): complete concat of all tables
+ // 1 : don't concatenate the
MAIN table
+ // 2 : don't concatenate the
POINTING table
+ // 3 : neither concat MAIN nor
POINTING table
+ const String& destMSName=""); // support for virtual
concat
+
+ void setTolerance(Quantum<Double>& freqTol, Quantum<Double>& dirTol);
+ void setWeightScale(const Float weightScale);
+ void setRespectForFieldName(const Bool respectFieldName); // If True,
fields of same direction are not merged
+ // if their
name is different
+
+private:
+ MSConcat();
+ static IPosition isFixedShape(const TableDesc& td);
+ static IPosition getShape(const ROMSDataDescColumns& ddCols,
+ const ROMSSpWindowColumns& spwCols,
+ const ROMSPolarizationColumns& polCols,
+ uInt whichShape);
+ void checkShape(const IPosition& otherShape) const;
+ void checkCategories(const ROMSMainColumns& otherCols) const;
+ Bool checkEphIdInField(const ROMSFieldColumns& otherFldCol) const;
+ Bool copyPointing(const MSPointing& otherPoint, const Block<uInt>&
newAntIndices);
+ Bool copyPointingB(MSPointing& otherPoint, const Block<uInt>&
newAntIndices);
+ Int copyObservation(const MSObservation& otherObs, const Bool
remRedunObsId=True);
+ // by default remove redundant observation
table rows
+ Block<uInt> copyAntennaAndFeed(const MSAntenna& otherAnt,
+ const MSFeed& otherFeed);
+ Block<uInt> copyState(const MSState& otherState);
+ Block<uInt> copyField(const MeasurementSet& otherms);
+ Block<uInt> copySpwAndPol(const MSSpectralWindow& otherSpw,
+ const MSPolarization& otherPol,
+ const MSDataDescription& otherDD);
+ Bool copySource(const MeasurementSet& otherms);
+ Bool updateSource();
+ Bool sourceRowsEquivalent(const MSSourceColumns& sourceCol,
+ const uInt& rowi, const uInt& rowj,
+ const Bool dontTestDirection=False);
+
+ Bool obsRowsEquivalent(const MSObservationColumns& obsCol,
+ const uInt& rowi, const uInt& rowj);
+
+
+ void updateModelDataKeywords(MeasurementSet& ms);
+
+ MeasurementSet itsMS;
+ IPosition itsFixedShape;
+ Quantum<Double> itsFreqTol;
+ Quantum<Double> itsDirTol;
+ Float itsWeightScale;
+ Bool itsRespectForFieldName;
+ Vector<Bool> itsChanReversed;
+ SimpleOrderedMap <Int, Int> newSourceIndex_p;
+ SimpleOrderedMap <Int, Int> newSourceIndex2_p;
+ SimpleOrderedMap <Int, Int> newSPWIndex_p;
+ SimpleOrderedMap <Int, Int> newObsIndexA_p;
+ SimpleOrderedMap <Int, Int> newObsIndexB_p;
+ SimpleOrderedMap <Int, Int> otherObsIdsWithCounterpart_p;
+ SimpleOrderedMap <Int, Int> solSystObjects_p;
+
+ Bool doSource_p;
+ Bool doSource2_p;
+ Bool doSPW_p;
+ Bool doObsA_p;
+ Bool doObsB_p;
+
+};
+
+template<class T>
+Bool areEQ(const ROScalarColumn<T>& col, uInt row_i, uInt row_j)
+{
+ T value_i, value_j;
+ col.get(row_i, value_i);
+ col.get(row_j, value_j);
+ return (value_i == value_j);
+}
+
+template<class T>
+Bool areEQ(const ROArrayColumn<T>& col, uInt row_i, uInt row_j)
+{
+ Bool rval(False);
+ Array<T> arr_i;
+ Array<T> arr_j;
+
+ col.get(row_i, arr_i, True);
+ col.get(row_j, arr_j, True);
+ Int ni = arr_i.nelements();
+ Int nj = arr_j.nelements();
+ if( (ni==0 && nj==0) || // no data is regarded as equal
+ allEQ(arr_i, arr_j)){
+ rval = True;
+ }
+ return rval;
+}
+
+
+
+} //# NAMESPACE CASACORE - END
+
+#endif
+
+
+
=======================================
--- /dev/null
+++ /branches/nov14/ms/MSOper/MSDerivedValues.cc Wed Mar 25 14:33:54 2015
UTC
@@ -0,0 +1,399 @@
+//# MSDerivedValues.cc: Calculate values derived from a MS
+//# Copyright (C) 1996,1997,1999,2000
+//# Associated Universities, Inc. Washington DC, USA.
+//#
+//# This library is free software; you can redistribute it and/or modify it
+//# under the terms of the GNU Library General Public License as published
by
+//# the Free Software Foundation; either version 2 of the License, or (at
your
+//# option) any later version.
+//#
+//# This library is distributed in the hope that it will be useful, but
WITHOUT
+//# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+//# FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
+//# License for more details.
+//#
+//# You should have received a copy of the GNU Library General Public
License
+//# along with this library; if not, write to the Free Software Foundation,
+//# Inc., 675 Massachusetts Ave, Cambridge, MA 02139, USA.
+//#
+//# Correspondence concerning AIPS++ should be addressed as follows:
+//# Internet email:
aips2-...@nrao.edu.
+//# Postal address: AIPS++ Project Office
+//# National Radio Astronomy Observatory
+//# 520 Edgemont Road
+//# Charlottesville, VA 22903-2475 USA
+//#
+//# $Id$
+
+#include <casacore/ms/MSOper/MSDerivedValues.h>
+#include <casacore/ms/MeasurementSets/MSDopplerUtil.h>
+#include <casacore/casa/Arrays/ArrayMath.h>
+#include <casacore/ms/MeasurementSets/MSColumns.h>
+#include <casacore/measures/Measures/VelocityMachine.h>
+#include <casacore/casa/Logging/LogMessage.h>
+#include <casacore/casa/Logging/LogSink.h>
+#include <casacore/casa/Utilities/Assert.h>
+#include <casacore/casa/Exceptions/Error.h>
+
+namespace casacore { //# NAMESPACE CASACORE - BEGIN
+
+MSDerivedValues::MSDerivedValues()
+{
+ init();
+}
+
+MSDerivedValues::MSDerivedValues(const MSDerivedValues& other)
+{
+ operator=(other);
+}
+
+MSDerivedValues::~MSDerivedValues() {
+ //break reference
+ ms_p=MeasurementSet();
+}
+
+MSDerivedValues&
+MSDerivedValues::operator=(const MSDerivedValues& other)
+{
+ antenna_p=other.antenna_p;
+
+ // should copy all data here, for now, just init
+ init();
+
+ mount_p = other.mount_p;
+ radialVelocityType_p = other.radialVelocityType_p;
+
+ return *this;
+}
+
+const Vector<MPosition> &
+MSDerivedValues::getAntennaPositions () const
+{
+ return mAntPos_p;
+}
+
+
+Int MSDerivedValues::setAntennas(const ROMSAntennaColumns& ac)
+{
+ Int nAnt=ac.position().nrow();
+
+ mAntPos_p.resize(nAnt);
+ Vector<String> mount(nAnt);
+ Vector<Double> avPos(3); avPos=0;
+ for (Int ant=0; ant<nAnt; ant++) {
+ mAntPos_p(ant) = ac.positionMeas()(ant);
+ mount(ant) = ac.mount()(ant);
+ avPos+=ac.position()(ant);
+ }
+ if (nAnt>0) {
+ avPos/=Double(nAnt);
+ mObsPos_p = mAntPos_p(0);
+ mObsPos_p.set(MVPosition(avPos));
+ setAntennaMount(mount);
+ setAntenna(0);
+ }
+ return nAnt;
+}
+
+MSDerivedValues& MSDerivedValues::setAntennaPositions(const
Vector<MPosition>&
+ antPosition)
+{
+ Int nAnt=antPosition.nelements();
+ AlwaysAssert(nAnt>0,AipsError);
+ mAntPos_p.resize(nAnt);
+ mAntPos_p=antPosition;
+ Vector<Double> avPos(3); avPos=0;
+ for (Int i=0; i<nAnt; i++) {
+ avPos+=mAntPos_p(i).getValue().get();
+ }
+ avPos/=Double(nAnt);
+ mObsPos_p=mAntPos_p(0);
+ mObsPos_p.set(MVPosition(avPos));
+ setAntenna(0);
+ return *this;
+}
+
+MSDerivedValues& MSDerivedValues::setObservatoryPosition(const MPosition&
+ obsPosition)
+{
+ mObsPos_p=obsPosition;
+ setAntenna(-1);
+ return *this;
+}
+MSDerivedValues& MSDerivedValues::setMeasurementSet(const MeasurementSet&
ms){
+
+ ms_p=ms;
+ const ROMSAntennaColumns ac(ms_p.antenna());
+ //set antenna mounts and obs position
+ setAntennas(ac);
+ // set the restFrequency spwid 0, fieldid 0 for now
+ setRestFrequency(0, 0);
+ //set the frequency type
+ const ROMSSpWindowColumns spc(ms_p.spectralWindow());
+ MFrequency refreq0=spc.refFrequencyMeas()(0);
+ MFrequency::Types freqType =
+ MFrequency::castType(refreq0.getRef().getType());
+ setFrequencyReference(freqType);
+
+ hasMS_p=True;
+ return *this;
+
+}
+
+Bool MSDerivedValues::setRestFrequency(const Int fieldid, const Int spwid,
const Int whichline){
+
+ if(hasMS_p){
+ MSDopplerUtil msdoppler(ms_p);
+ Vector<Double> restFreqVec;
+ try{
+ msdoppler.dopplerInfo(restFreqVec ,spwid,fieldid);
+ }
+ catch(...){
+ setRestFrequency(Quantity(0.0, "Hz"));
+ return False;
+ }
+
+ if((restFreqVec.nelements() >0) &&
(uInt(whichline)<=restFreqVec.nelements())){
+ //using the first
+
+ setRestFrequency(Quantity(restFreqVec[whichline], "Hz"));
+
+ return True;
+ }
+ else{
+ setRestFrequency(Quantity(0.0, "Hz"));
+ }
+
+ }
+
+ return False;
+
+
+
+}
+MSDerivedValues& MSDerivedValues::setRestFrequency(const Quantity&
restfrq){
+
+ restFreq_p=restfrq;
+ return *this;
+
+}
+
+MSDerivedValues& MSDerivedValues::setAntennaMount(const Vector<String>&
mount)
+{
+ Int nAnt=mount.nelements();
+ if (nAnt>0) {
+ mount_p.resize(nAnt);
+ for (Int i=0; i<nAnt; i++) {
+ if (mount(i)=="alt-az" || mount(i)=="ALT-AZ" || mount(i)=="") {
+ mount_p(i)=0;
+ } else if (mount(i)=="alt-az+rotator" || mount(i)=="ALT-AZ+ROTATOR")
{
+ mount_p(i)=0;
+ } else if (mount(i)=="equatorial" || mount(i)=="EQUATORIAL") {
+ mount_p(i)=1;
+ } else if (mount(i)=="X-Y" || mount(i)=="x-y") {
+ mount_p(i)=2;
+ } else if (mount(i)=="orbiting" || mount(i)=="ORBITING") {
+ mount_p(i)=3;
+ } else {
+ mount_p(i)=4;
+ }
+ }
+ }
+ return *this;
+}
+MSDerivedValues& MSDerivedValues::setEpoch(const MEpoch& time)
+{
+ cUTCToLAST_p.setModel(time);
+ fAntFrame_p.resetEpoch(time);
+ return *this;
+}
+
+MSDerivedValues& MSDerivedValues::setFieldCenter(const MDirection&
fieldCenter)
+{
+ cRADecToAzEl_p.setModel(fieldCenter);
+ cRADecToHADec_p.setModel(fieldCenter);
+ fAntFrame_p.resetDirection(fieldCenter);
+ mFieldCenter_p=fieldCenter;
+ return *this;
+}
+
+MSDerivedValues& MSDerivedValues::setFieldCenter(uInt fieldid)
+{
+
+ if(hasMS_p && (ms_p.field().nrow() > fieldid)){
+ ROMSColumns msc(ms_p);
+ const MDirection dirn=msc.field().phaseDirMeas(fieldid);
+ setFieldCenter(dirn);
+ }
+ else{
+ MDirection dummy;
+ setFieldCenter(dummy);
+ }
+
+
+ return *this;
+
+
+}
+
+
+MSDerivedValues& MSDerivedValues::setAntenna(Int antenna)
+{
+ DebugAssert(antenna>=-1,AipsError);
+ DebugAssert(antenna<Int(mAntPos_p.nelements()),AipsError);
+ // Reset the reference frame used in the conversion machines to be
+ // for this antenna.
+ if (antenna==-1) {
+ fAntFrame_p.resetPosition(mObsPos_p);
+ } else {
+ fAntFrame_p.resetPosition(mAntPos_p(antenna));
+ }
+ antenna_p=max(0,antenna);
+ return *this;
+}
+
+// compute parallactic angle.
+Double MSDerivedValues::parAngle()
+{
+ DebugAssert(mAntPos_p.nelements()==mount_p.nelements(),AipsError);
+ // Calculate Parallactic angle for this UT. To do this we find
+ // the AzEl Directions of the phase center and of the (HA,Dec) pole
+ // and then calculate the position angle between these two directions.
+
+ // Do conversion. Can use the same conversion machine for
+ // all antennas & times since we just change the Frame
+ Double pa=0;
+
+ if (mount_p(antenna_p)==0) {
+ // Now we can do the conversions using the machines
+ mRADecInAzEl_p = cRADecToAzEl_p();
+ mHADecPoleInAzEl_p = cHADecToAzEl_p();
+
+ // Get the parallactic angle
+ pa = mRADecInAzEl_p.getValue().
+ positionAngle(mHADecPoleInAzEl_p.getValue());
+
+ // pa_p(iant)+= receptorAngle_p(iant);
+ //#if (iant==0)
+ //# cout<<"Antenna "<<iant<<" at time: "<<MVTime(mEpoch.getValue())<<
+ //# " has PA = "<<pa_p(iant)*57.28<<endl;
+
+ } else if (mount_p(antenna_p)==1) {
+ // nothing to do for equatorial mounts, pa is always 0
+ } else {
+ LogMessage message(LogOrigin("MSDerivedValues","parAngle"));
+ LogSink logSink;
+ message.message("unhandled mount type");
+ message.priority(LogMessage::WARN);
+ logSink.post(message);
+ }
+ return pa;
+}
+
+MRadialVelocity::Types
+MSDerivedValues::getRadialVelocityType () const
+{
+ return radialVelocityType_p;
+}
+
+MSDerivedValues& MSDerivedValues::setVelocityFrame(MRadialVelocity::Types
vType)
+{
+ radialVelocityType_p = vType;
+ cTOPOToLSR_p.setOut(vType);
+ return *this;
+}
+
+MSDerivedValues& MSDerivedValues::setVelocityReference(MDoppler::Types
dopType)
+{
+ velref_p=MDoppler::Ref(dopType);
+ return *this;
+}
+
+MSDerivedValues& MSDerivedValues::setFrequencyReference(MFrequency::Types
frqType)
+{
+ frqref_p=MFrequency::Ref(frqType);
+ return *this;
+}
+
+Double MSDerivedValues::hourAngle()
+{
+ return cRADecToHADec_p().getValue().get()(0);
+}
+
+const MDirection& MSDerivedValues::azel()
+{
+ return cRADecToAzEl_p();
+}
+
+const MEpoch& MSDerivedValues::last()
+{
+ return cUTCToLAST_p();
+}
+
+const MRadialVelocity& MSDerivedValues::obsVel()
+{
+ return cTOPOToLSR_p();
+}
+
+Quantity MSDerivedValues::toFrequency(const Quantity& vel, const Quantity&
restFreq){
+ VelocityMachine vm(frqref_p, Unit("GHz"), MVFrequency(restFreq),
+ velref_p, vel.getUnit(), fAntFrame_p);
+
+ return vm.makeFrequency(vel.getValue());
+
+
+}
+
+Quantity MSDerivedValues::toFrequency(const Quantity& vel){
+ return toFrequency(vel, restFreq_p);
+
+
+}
+
+Quantity MSDerivedValues::toVelocity(const Quantity& freq, const Quantity&
restFreq){
+ VelocityMachine vm(frqref_p, freq.getUnit(), MVFrequency(restFreq),
+ velref_p, Unit("km/s"), fAntFrame_p);
+
+ return vm.makeVelocity(freq.getValue());
+}
+
+Quantity MSDerivedValues::toVelocity(const Quantity& freq){
+ return toVelocity(freq, restFreq_p);
+
+}
+
+void MSDerivedValues::init()
+{
+ // Set up the frame for epoch and antenna position. We will
+ // adjust this to effect the coordinate transformations
+ fAntFrame_p.set(MEpoch(), MPosition(),MDirection());
+ MDirection::Ref rHADec(MDirection::HADEC,fAntFrame_p);
+ // Make the HADec pole as expressed in HADec. The pole is the default.
+ MDirection mHADecPole;
+ mHADecPole.set(rHADec);
+ // Set up the machines to convert to AzEl, HADec and LAST
+ cRADecToAzEl_p.set(MDirection(),
+ MDirection::Ref(MDirection::AZEL,fAntFrame_p));
+
cHADecToAzEl_p.set(mHADecPole,MDirection::Ref(MDirection::AZEL,fAntFrame_p));
+ cRADecToHADec_p.set(MDirection(),rHADec);
+ cUTCToLAST_p.set(MEpoch(),MEpoch::Ref(MEpoch::LAST,fAntFrame_p));
+ // set up the velocity conversion with zero velocity in the TOPO/antenna
+ // frame. We'll use this to compute the observatory velocity in another
+ // frame (often LSR).
+ cTOPOToLSR_p.set(MRadialVelocity(MVRadialVelocity(0.0),
+ MRadialVelocity::Ref(MRadialVelocity::TOPO,
+ fAntFrame_p)),
+ MRadialVelocity::Ref(MRadialVelocity::LSRK));
+ radialVelocityType_p = MRadialVelocity::LSRK;
+ frqref_p= MFrequency::Ref(MFrequency::LSRK);
+ velref_p=MDoppler::Ref(MDoppler::RADIO);
+ restFreq_p=Quantity(0.0, "Hz");
+ hasMS_p=False;
+
+}
+
+
+
+
+} //# NAMESPACE CASACORE - END
+
=======================================
--- /dev/null
+++ /branches/nov14/ms/MSOper/MSDerivedValues.h Wed Mar 25 14:33:54 2015 UTC
@@ -0,0 +1,239 @@
+//# MSDerivedValues.h: a server for values derived from a MS (e.g. P.A.)
+//# Copyright (C) 1997,1999,2000
+//# Associated Universities, Inc. Washington DC, USA.
+//#
+//# This library is free software; you can redistribute it and/or modify it
+//# under the terms of the GNU Library General Public License as published
by
+//# the Free Software Foundation; either version 2 of the License, or (at
your
+//# option) any later version.
+//#
+//# This library is distributed in the hope that it will be useful, but
WITHOUT
+//# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+//# FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
+//# License for more details.
+//#
+//# You should have received a copy of the GNU Library General Public
License
+//# along with this library; if not, write to the Free Software Foundation,
+//# Inc., 675 Massachusetts Ave, Cambridge, MA 02139, USA.
+//#
+//# Correspondence concerning AIPS++ should be addressed as follows:
+//# Internet email:
aips2-...@nrao.edu.
+//# Postal address: AIPS++ Project Office
+//# National Radio Astronomy Observatory
+//# 520 Edgemont Road
+//# Charlottesville, VA 22903-2475 USA
+//#
+//#
+//# $Id$
+
+#ifndef MS_MSDERIVEDVALUES_H
+#define MS_MSDERIVEDVALUES_H
+
+#include <casacore/casa/aips.h>
+#include <casacore/casa/Arrays/Vector.h>
+#include <casacore/measures/Measures.h>
+#include <casacore/measures/Measures/MCDirection.h>
+#include <casacore/measures/Measures/MDoppler.h>
+#include <casacore/measures/Measures/MFrequency.h>
+#include <casacore/measures/Measures/MCEpoch.h>
+#include <casacore/measures/Measures/MCRadialVelocity.h>
+#include <casacore/measures/Measures/MPosition.h>
+#include <casacore/ms/MeasurementSets/MeasurementSet.h>
+namespace casacore { //# NAMESPACE CASACORE - BEGIN
+
+//# Forward Declarations
+class ROMSAntennaColumns;
+class String;
+// <summary>
+// MSDerivedValues calculates values derived from a MS
+// </summary>
+
+// <use visibility=export>
+
+// <reviewed reviewer="" date="yyyy/mm/dd" tests="" demos="">
+// </reviewed>
+
+// <prerequisite>
+// <li> MeasurementSet
+// <li> SomeOtherClass
+// <li> some concept
+// </prerequisite>
+//
+// <etymology>
+// MSDerivedValues calculates values derived from those in a MS
+// </etymology>
+//
+// <synopsis>
+// MSDerivedValues is a class that computes values derived from those
present
+// in a MeasurementSet. E.g., calculate feed position angles on the sky
from
+// time, antenna positions and feed characteristics.
+// </synopsis>
+//
+// <example>
+// <srcblock>
+// // calculate the parallactic angle and the observatory velocity for the
+// // first time and first source in the MS.
+// // set up
+// MSDerivedValues msd;
+// MS myMS("myMS");
+// ROMSColumns msc(myMS);
+// msd.setAntennas(msc.antenna());
+// MEpoch ep=MS::epochMeasure(msc.time());
+// ep.set(MVEpoch(Quantity(msc.time()(0),"s")));
+// msd.setEpoch(ep);
+// MDirection dir=MS::directionMeasure(msc.field().phaseDir());
+// dir.set(MVDirection(Vector<Double>(msc.field().phaseDir()(0))));
+// msd.setFieldCenter(dir);
+// msd.setVelocityFrame(MRadialVelocity::LSRK);
+// // now we are ready for the calculations:
+// Double parAngle = msd.parangle();
+// MRadialVelocity observatoryVel = msd.obsVel();
+// </srcblock>
+// </example>
+//
+// <motivation>
+// Values derived from those in a MS are needed in various places, e.g.,
for
+// plotting purposes. This class combines the commonly needed calculations
+// in one place.
+// </motivation>
+//
+// <thrown>
+// <li>
+// <li>
+// </thrown>
+//
+// <todo asof="1997/05/30">
+// <li> the interface should be less cumbersome
+// <li> probably needs speeding up
+// </todo>
+
+class MSDerivedValues
+{
+ friend class VisBufferAsync; // to work around dysfunctional operator=
and
+ // thread-hostile shared pointers (Jim
Jacobs 111104)
+public:
+ MSDerivedValues();
+ ~MSDerivedValues();
+
+ // Copy constructor, this will initialize with other's MS
+ MSDerivedValues(const MSDerivedValues& other);
+
+ // Assignment, this will initialize with other's MS
+ MSDerivedValues& operator=(const MSDerivedValues& other);
+
+ // Set antenna position from an antenna table
+ // Returns the number of antennas. Also
+ // sets the observatory position to the average of the antenna positions.
+ Int setAntennas(const ROMSAntennaColumns& ac);
+
+ // Set antenna positions, index in vector is antenna number
+ // for calls below.
+ MSDerivedValues& setAntennaPositions(const Vector<MPosition>&
antPosition);
+ const Vector<MPosition> & getAntennaPositions () const;
+
+ // Set the observatory position. Note that setAntennas will reset this.
+ MSDerivedValues& setObservatoryPosition(const MPosition& obsPosition);
+
+ // Set antenna mounts, should have same number of entries as
+ // antPosition in setAntennaPosition
+ MSDerivedValues& setAntennaMount(const Vector<String>& mount);
+
+ // Set epoch
+ MSDerivedValues& setEpoch(const MEpoch& time);
+
+ // Set field center
+ MSDerivedValues& setFieldCenter(const MDirection& fieldCenter);
+
+ //If you have used setMeasurementSet then this version of
+ //setFieldCenter using field id makes sense
+ MSDerivedValues& setFieldCenter(uInt fieldid=0);
+
+ // Set antenna index, sets the position reference for the conversions.
+ // Use -1 to set the reference frame to the observatory position.
+ MSDerivedValues& setAntenna(Int antenna);
+
+ // Set the velocity frame type (e.g., MRadialVelocity::LSRK)
+ MSDerivedValues& setVelocityFrame(MRadialVelocity::Types vType);
+
+ // Set the velocity frame type (e.g., MRDoppler::RADIO)
+ MSDerivedValues& setVelocityReference(MDoppler::Types dopType);
+ MRadialVelocity::Types getRadialVelocityType () const;
+
+ // Set the frequency frame (e.g., MFrequency::LSRK)
+ MSDerivedValues& setFrequencyReference(MFrequency::Types frqType);
+
+ // get hour angle
+ Double hourAngle();
+
+ // get parallactic angle
+ Double parAngle();
+
+ // get azimuth & elevation
+ const MDirection& azel();
+
+ // get LAST for given time, antenna
+ const MEpoch& last();
+
+ // get observatory radial velocity for given epoch, position and
direction
+ const MRadialVelocity& obsVel();
+
+ //Set an ms does not need to explicity setAntennas and is necessary if
+ //setRestFreqency(fieldid, spwid) is used
+ MSDerivedValues& setMeasurementSet(const MeasurementSet& ms);
+
+
+ //Set restFrequencies...make it look for it for the fieldid, spwid and
line
+ //number defined in the SOURCE table return False if it fails to find the
+ //restFrquency
+ Bool setRestFrequency(const Int fieldid, const Int spwid,
+ const Int linenum=0);
+
+ //
+ MSDerivedValues& setRestFrequency(const Quantity& restFreq);
+
+
+ // get frequency from velocity
+
+ Quantity toFrequency(const Quantity& vel, const Quantity& restFreq);
+ Quantity toFrequency(const Quantity& vel);
+
+ // get velocity from frequency
+ Quantity toVelocity(const Quantity& freq, const Quantity& restFreq);
+ Quantity toVelocity(const Quantity& freq);
+
+protected:
+
+private:
+
+ // initialize data
+ void init();
+
+ Int antenna_p;
+ MEpoch::Convert cUTCToLAST_p;
+ Vector<MPosition> mAntPos_p;
+ MDirection::Convert cRADecToAzEl_p;
+ MDirection::Convert cHADecToAzEl_p;
+ MDirection::Convert cRADecToHADec_p;
+ MeasFrame fAntFrame_p;
+ MDirection mRADecInAzEl_p;
+ MDirection mHADecPoleInAzEl_p;
+ MDirection mFieldCenter_p;
+ MPosition mObsPos_p;
+ MRadialVelocity::Convert cTOPOToLSR_p;
+ MDoppler::Ref velref_p;
+ MFrequency::Ref frqref_p;
+ Bool hasMS_p;
+ Quantity restFreq_p;
+ Vector<Int> mount_p;
+ MeasurementSet ms_p;
+ MRadialVelocity::Types radialVelocityType_p;
+
+ // Vector<Double> receptorAngle_p;
+
+
+};
+
+
+} //# NAMESPACE CASACORE - END
+
+#endif
=======================================
--- /dev/null
+++ /branches/nov14/ms/MSOper/MSFlagger.cc Wed Mar 25 14:33:54 2015 UTC
@@ -0,0 +1,1025 @@
+//# MSFlagger.cc: selection and iteration of an MS
+//# Copyright (C) 1997,1998,1999,2000,2001,2002
+//# Associated Universities, Inc. Washington DC, USA.
+//#
+//# This library is free software; you can redistribute it and/or modify it
+//# under the terms of the GNU Library General Public License as published
by
+//# the Free Software Foundation; either version 2 of the License, or (at
your
+//# option) any later version.
+//#
+//# This library is distributed in the hope that it will be useful, but
WITHOUT
+//# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+//# FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
+//# License for more details.
+//#
+//# You should have received a copy of the GNU Library General Public
License
+//# along with this library; if not, write to the Free Software Foundation,
+//# Inc., 675 Massachusetts Ave, Cambridge, MA 02139, USA.
+//#
+//# Correspondence concerning AIPS++ should be addressed as follows:
+//# Internet email:
aips2-...@nrao.edu.
+//# Postal address: AIPS++ Project Office
+//# National Radio Astronomy Observatory
+//# 520 Edgemont Road
+//# Charlottesville, VA 22903-2475 USA
+//#
+//#
+//# $Id$
+
+#include <casacore/ms/MSOper/MSFlagger.h>
+
+#include <casacore/casa/Arrays/ArrayMath.h>
+#include <casacore/casa/Arrays/ArrayLogical.h>
+#include <casacore/casa/Arrays/ArrayUtil.h>
+#include <casacore/casa/Arrays/Matrix.h>
+#include <casacore/casa/Arrays/Cube.h>
+#include <casacore/casa/Containers/Record.h>
+#include <casacore/casa/Exceptions/Error.h>
+#include <casacore/casa/Arrays/Slice.h>
+#include <casacore/casa/Arrays/Slicer.h>
+#include <casacore/casa/Logging/LogIO.h>
+#include <casacore/tables/Tables/ArrayColumn.h>
+#include <casacore/tables/Tables/ArrColDesc.h>
+#include <casacore/tables/Tables/ScalarColumn.h>
+#include <casacore/tables/Tables/ScaColDesc.h>
+#include <casacore/tables/Tables/TableDesc.h>
+#include <casacore/tables/Tables/TableIter.h>
+#include <casacore/tables/Tables/TableRecord.h>
+#include <casacore/tables/DataMan/TiledDataStMan.h>
+#include <casacore/tables/DataMan/TiledDataStManAccessor.h>
+#include <casacore/tables/DataMan/TiledColumnStMan.h>
+#include <casacore/casa/Utilities/Assert.h>
+#include <casacore/casa/Utilities/GenSort.h>
+#include <casacore/ms/MSSel/MSSelector.h>
+#include <casacore/ms/MSSel/MSSelUtil.h>
+#include <casacore/casa/iostream.h>
+
+
+namespace casacore { //# NAMESPACE CASACORE - BEGIN
+
+MSFlagger::MSFlagger():msSel_p(0)
+{}
+
+MSFlagger::MSFlagger(MSSelector& msSel):msSel_p(&msSel)
+{}
+
+MSFlagger& MSFlagger::operator=(const MSFlagger& other)
+{
+ if (this==&other) return *this;
+ msSel_p=other.msSel_p;
+ buffer_p=other.buffer_p;
+ return *this;
+}
+
+MSFlagger::~MSFlagger()
+{
+ msSel_p=0;
+}
+
+void MSFlagger::setMSSelector(MSSelector& msSel)
+{
+ msSel_p=&msSel;
+ buffer_p=Record(RecordInterface::Variable);
+}
+
+Bool MSFlagger::fillDataBuffer(const String& item, Bool ifrAxis)
+{
+ LogIO os;
+ if (!check()) return False;
+ String itm=downcase(item);
+ Int fld=MSS::field(itm);
+ switch (fld) {
+ case MSS::AMPLITUDE:
+ case MSS::CORRECTED_AMPLITUDE:
+ case MSS::MODEL_AMPLITUDE:
+ case MSS::RESIDUAL_AMPLITUDE:
+ case MSS::OBS_RESIDUAL_AMPLITUDE:
+ case MSS::DATA:
+ case MSS::CORRECTED_DATA:
+ case MSS::MODEL_DATA:
+ case MSS::RESIDUAL_DATA:
+ case MSS::OBS_RESIDUAL_DATA:
+ case MSS::IMAGINARY:
+ case MSS::CORRECTED_IMAGINARY:
+ case MSS::MODEL_IMAGINARY:
+ case MSS::RESIDUAL_IMAGINARY:
+ case MSS::OBS_RESIDUAL_IMAGINARY:
+ case MSS::PHASE:
+ case MSS::CORRECTED_PHASE:
+ case MSS::MODEL_PHASE:
+ case MSS::RESIDUAL_PHASE:
+ case MSS::OBS_RESIDUAL_PHASE:
+ case MSS::REAL:
+ case MSS::CORRECTED_REAL:
+ case MSS::MODEL_REAL:
+ case MSS::RESIDUAL_REAL:
+ case MSS::OBS_RESIDUAL_REAL:
+ {
+ Vector<String> items(3);
+ items(0)=item;
+ items(1)="FLAG";
+ items(2)="FLAG_ROW";
+ buffer_p=msSel_p->getData(items,ifrAxis);
+ buffer_p.define("datafield",itm);
+ }
+ return True;
+ default:
+ os << LogIO::WARN <<"No DATA derived item specified, buffer unchanged"
+ << LogIO::POST;
+ }
+ return False;
+}
+
+Record MSFlagger::diffDataBuffer(const String& direction, Int window,
+ Bool doMedian)
+{
+ Record retVal(RecordInterface::Variable);
+ LogIO os;
+ String dir=downcase(direction);
+ if (dir!="time" && dir!="channel") {
+ os << LogIO::WARN << "Unrecognized direction "<<direction<<
+ ", specify TIME or CHANNEL"<< LogIO::POST;
+ return retVal;
+ }
+ Int win=max(1,window);
+ if (win!=window) os <<LogIO::WARN<<"Setting window to "<<win<<
LogIO::POST;
+ if (doMedian) win=2*(win/2)+1; // make odd to keep it symmetric
+ if (!buffer_p.isDefined("datafield")) {
+ os << LogIO::WARN<<"Buffer is empty, use fillbuffer first"
+ << LogIO::POST;
+ return retVal;
+ }
+ String item = buffer_p.asString(RecordFieldId("datafield"));
+ Array<Bool> flag = buffer_p.asArrayBool(RecordFieldId("flag"));
+ Array<Bool> flagRow = buffer_p.asArrayBool(RecordFieldId("flag_row")); ;
+ Int fld=MSS::field(item);
+ Array<Float> diff;
+ Int timeAxis=flag.ndim()-1;
+ Int chanAxis=1;
+ switch (fld) {
+ case MSS::DATA:
+ case MSS::CORRECTED_DATA:
+ case MSS::MODEL_DATA:
+ case MSS::RESIDUAL_DATA:
+ case MSS::OBS_RESIDUAL_DATA:
+ {
+ Array<Complex> data = buffer_p.asArrayComplex(RecordFieldId(item));
+ if (dir=="time") {
+ diff=MSSelUtil<Complex>::diffData(data,flag,flagRow,timeAxis,win,
+ doMedian);
+ }
+ else {
+ diff=MSSelUtil<Complex>::diffData(data,flag,flagRow,chanAxis,win,
+ doMedian);
+ }
+ // remove data field from record
+ Record gr(RecordInterface::Variable);
+ gr.define("flag",buffer_p.asArrayBool(RecordFieldId("flag")));
+
gr.define("flag_row",buffer_p.asArrayBool(RecordFieldId("flag_row")));
+ if (fld==MSS::DATA) item="amplitude";
+ if (fld==MSS::CORRECTED_DATA) item="corrected_amplitude";
+ if (fld==MSS::MODEL_DATA) item="model_amplitude";
+ if (fld==MSS::RESIDUAL_DATA) item="residual_amplitude";
+ if (fld==MSS::OBS_RESIDUAL_DATA) item="obs_residual_amplitude";
+ gr.define("datafield",item);
+ buffer_p=gr;
+ }
+ break;
+ case MSS::AMPLITUDE:
+ case MSS::CORRECTED_AMPLITUDE:
+ case MSS::MODEL_AMPLITUDE:
+ case MSS::RESIDUAL_AMPLITUDE:
+ case MSS::OBS_RESIDUAL_AMPLITUDE:
+ case MSS::IMAGINARY:
+ case MSS::CORRECTED_IMAGINARY:
+ case MSS::MODEL_IMAGINARY:
+ case MSS::RESIDUAL_IMAGINARY:
+ case MSS::OBS_RESIDUAL_IMAGINARY:
+ case MSS::PHASE:
+ case MSS::CORRECTED_PHASE:
+ case MSS::MODEL_PHASE:
+ case MSS::RESIDUAL_PHASE:
+ case MSS::OBS_RESIDUAL_PHASE:
+ case MSS::REAL:
+ case MSS::CORRECTED_REAL:
+ case MSS::MODEL_REAL:
+ case MSS::RESIDUAL_REAL:
+ case MSS::OBS_RESIDUAL_REAL:
+ {
+ Array<Float> data = buffer_p.asArrayFloat(RecordFieldId(item));
+ if (dir=="time") {
+ diff=MSSelUtil<Float>::diffData(data,flag,flagRow,timeAxis,win,
+ doMedian);
+ }
+ else {
+ diff=MSSelUtil<Float>::diffData(data,flag,flagRow,chanAxis,win,
+ doMedian);
+ }
+ }
+ break;
+ default:
+ break;
+ }
+ buffer_p.define(item,diff);
+ applyRowFlags(flag,flagRow); // need to apply row flags to flags for
stats
+ addStats(buffer_p,flag,flagRow,diff);
+ retVal.define("median",buffer_p.asArrayFloat(RecordFieldId("medTF")));
+ retVal.define("aad",buffer_p.asArrayFloat(RecordFieldId("adTF")));
+ return retVal;
+}
+
+void MSFlagger::addStats(Record& buf, const Array<Bool>& flag,
+ const Array<Bool> flagRow, const Array<Float>& data)
+{
+ // axes PFIT (Polarization, Freq, Interferometer, Time)
+ // take median along T and F axes (medT, medF)
+ // calculate median of medians along F and T (medTmedF, medFmedT) to
+ // find outlying times and channels, estimate medTF as minumum of latter
2.
+ // calculate average absolute deviations over T and F medians, and TF
planes
+ // (adT, adF and adTF).
+ Array<Float> medT, medF, medTmedF, medFmedT, medTF, adT, adF, adTF;
+ getStats(medTF, adTF, medT, medFmedT, adT,
+ medF, medTmedF, adF, data, flag, flagRow);
+ buf.define("medTF",medTF);
+ buf.define("adTF",adTF);
+ buf.define("medT",medT);
+ buf.define("medFmedT",medFmedT);
+ buf.define("adT",adT);
+ buf.define("medF",medF);
+ buf.define("medTmedF",medTmedF);
+ buf.define("adF",adF);
+}
+
+void MSFlagger::applyRowFlags(Array<Bool>& flag, Array<Bool>& flagRow)
+{
+ const Int nXY=flag.shape()(0)*flag.shape()(1);
+ Bool deleteFlag, deleteFlagRow;
+ Bool* pflagRow = flagRow.getStorage(deleteFlagRow);
+ Bool* pflag = flag.getStorage(deleteFlag);
+ const Int nEl=flagRow.nelements();
+ DebugAssert(nEl*nXY==Int(flag.nelements()),AipsError);
+ Int offset=0;
+ for (Int i=0; i<nEl; i++, offset+=nXY) {
+ if (pflagRow[i]) {
+ for (Int j=0; j<nXY; j++) pflag[offset+j]=True;
+ } else {
+ Bool ok=False;
+ for (Int j=0; j<nXY && (ok=pflag[offset+j]); j++) {}
+ if (ok) pflagRow[i]=True;
+ }
+ }
+ flag.putStorage(pflag,deleteFlag);
+ flagRow.putStorage(pflagRow,deleteFlagRow);
+}
+
+void MSFlagger::getStats(Array<Float>& medTF, Array<Float>& adTF,
+ Array<Float>& medT, Array<Float>& medFmedT,
+ Array<Float>& adT, Array<Float>& medF,
+ Array<Float>& medTmedF, Array<Float>& adF,
+ const Array<Float>& diff, const Array<Bool>& flag,
+ const Array<Bool>& flagRow)
+{
+ IPosition shape=diff.shape();
+ const Int nCorr=shape(0);
+ const Int nChan=shape(1);
+ Int nTime=shape(2);
+ Int nIfr=1;
+ const Int nXY=nCorr*nChan;
+ Array<Float> diff2(diff);
+ if (diff.ndim()==3) {
+ // make 4D reference to diff's storage so diffMedian will return
+ // correct shapes
+ Array<Float> ref(diff2.reform(IPosition(4,nCorr,nChan,nIfr,nTime)));
+ diff2.reference(ref);
+ } else {
+ nIfr=nTime;
+ nTime=shape(3);
+ }
+ const Int nXYZ=nXY*nIfr;
+ Bool deleteFlag, deleteFlagRow, deleteDiff;
+ const Bool* pflagRow = flagRow.getStorage(deleteFlagRow);
+ const Bool* pflag = flag.getStorage(deleteFlag);
+ const Float* pdiff = diff2.getStorage(deleteDiff);
+
+ medTF.resize(IPosition(2,nCorr,nIfr));
+ adTF.resize(IPosition(2,nCorr,nIfr));
+ medT.resize(IPosition(3,nCorr,nChan,nIfr));
+ medFmedT.resize(IPosition(2,nCorr,nIfr));
+ adT.resize(IPosition(2,nCorr,nIfr));
+ medF.resize(IPosition(3,nCorr,nIfr,nTime));
+ medTmedF.resize(IPosition(2,nCorr,nIfr));
+ adF.resize(IPosition(2,nCorr,nIfr));
+
+ // calculate medians over time
+ diffMedian(medT,diff2,3,flag);
+
+
+ // calculate median over channel of median over time
+ diffMedian(medFmedT,medT,1, (medT<=0.0f));
+
+ // calculate median over channel
+ diffMedian(medF,diff2,1, flag);
+
+ // calculate median over time of median over channel
+ diffMedian(medTmedF,medF,2, (medF<=0.0f));
+
+ // make a guess at the overal median (per pol and ifr)
+ min(medTF,medTmedF,medFmedT);
+
+ // calculate average absolute deviation of medians over time
+ {
+ Bool deletemedT;
+ const Float* pmedT=medT.getStorage(deletemedT);
+ Int offset=0;
+ IPosition polifr(2);
+ for (Int pol=0; pol<nCorr; pol++) {
+ polifr(0)=pol;
+ offset=pol;
+ for (Int ifr=0; ifr<nIfr; ifr++, offset+=nXY) {
+ polifr(1)=ifr;
+ Float ad=0, med=medFmedT(polifr);
+ Int count=0, offchan=offset;
+ for (Int i=0; i<nChan; i++, offchan+=nCorr) {
+ if (pmedT[offchan]>0) {
+ count++;
+ ad+=abs(pmedT[offchan]-med);
+ }
+ }
+ if (count>1) ad/=count;
+ adT(polifr)=ad;
+ }
+ }
+ medT.freeStorage(pmedT,deletemedT);
+ }
+
+ // calculate average absolute deviation of medians over channel
+ {
+ Bool deletemedF;
+ const Float* pmedF=medF.getStorage(deletemedF);
+ Int offset=0, nXZ=nCorr*nIfr;
+ IPosition polifr(2);
+ for (Int pol=0; pol<nCorr; pol++) {
+ polifr(0)=pol;
+ offset=pol;
+ for (Int ifr=0; ifr<nIfr; ifr++, offset+=nCorr) {
+ polifr(1)=ifr;
+ Float ad=0, med=medTmedF(polifr);
+ Int count=0, offtime=offset, offrow=ifr;
+ for (Int i=0; i<nTime; i++, offtime+=nXZ, offrow+=nIfr) {
+ if (!pflagRow[offrow]) {
+ count++;
+ ad+=abs(pmedF[offtime]-med);
+ }
+ }
+ if (count>1) ad/=count;
+ adF(polifr)=ad;
+ }
+ }
+ medF.freeStorage(pmedF,deletemedF);
+ }
+
+ // calculate overall average deviation (per pol and ifr)
+ {
+ IPosition polifr(2);
+ for (Int pol=0; pol<nCorr; pol++) {
+ polifr(0)=pol;
+ Int offset=pol;
+ for (Int ifr=0; ifr<nIfr; ifr++, offset+=nXY) {
+ polifr(1)=ifr;
+ Float ad=0, med=medTF(polifr);
+ Int count=0, offset2=offset, offrow=ifr;
+ for (Int i=0; i<nTime; i++, offset2+=nXYZ, offrow+=nIfr) {
+ if (!pflagRow[offrow]) {
+ for (Int j=0, offset3=offset2; j<nChan; j++,offset3+=nCorr) {
+ if (!pflag[offset3]) {
+ count++;
+ ad+=abs(pdiff[offset3]-med);
+ }
+ }
+ }
+ }
+ if (count>1) ad/=count;
+ adTF(polifr)=ad;
+ }
+ }
+ }
+
+
+ flag.freeStorage(pflag,deleteFlag);
+ flagRow.freeStorage(pflagRow,deleteFlagRow);
+ diff2.freeStorage(pdiff,deleteDiff);
+}
+
+void MSFlagger::diffMedian(Array<Float>& out, const Array<Float>& in,
+ Int axis, const Array<Bool>& flag)
+{
+ // collapse array "in" (with absolute differences)
+ // along specified axis by taking medians by profile taking into account
+ // the flags.
+ Int nDim=in.ndim();
+ DebugAssert(axis>=0 && axis<nDim && in.ndim()>0, AipsError);
+ IPosition inShape=in.shape(), outShape(max(1,Int(in.ndim())-1));
+ outShape(0)=1; // cope with 1-d input
+ Int nLess=1, nGreater=1, nAxis=inShape(axis);
+ for (Int i=0, count=0; i<nDim; i++) {
+ if (i!=axis) outShape(count++)=inShape(i);
+ if (i<axis) nLess*=inShape(i);
+ if (i>axis) nGreater*=inShape(i);
+ }
+ out.resize(outShape);
+
+ Bool deleteIn, deleteFlag, deleteOut;
+ const Float* pin=in.getStorage(deleteIn);
+ const Bool* pflag=flag.getStorage(deleteFlag);
+ Float* pout=out.getStorage(deleteOut);
+ Block<Float> values(nAxis);
+ for (Int j=0, offj=0; j<nGreater; j++, offj+=nLess) {
+ for (Int k=0, offk=offj*nAxis, offout=offj; k<nLess;
+ k++, offk++, offout++) {
+ Int count=0;
+ for (Int l=0, offin=offk; l<nAxis; l++, offin+=nLess) {
+ if (!pflag[offin]) values[count++]=pin[offin];
+ }
+ if (count>0) pout[offout]=median(Vector<Float>(values,count));
+ else pout[offout]=0;
+ }
+ }
+ in.freeStorage(pin,deleteIn);
+ flag.freeStorage(pflag,deleteFlag);
+ out.putStorage(pout,deleteOut);
+}
+
+inline String multiple(Int n) { return n!=1 ? "s" : ""; }
+
+Bool MSFlagger::clipDataBuffer(Float pixelLevel, Float timeLevel,
+ Float channelLevel)
+{
+ LogIO os;
+ if (!buffer_p.isDefined("datafield")) {
+ os << LogIO::WARN << "No data loaded into buffer yet"<<
+ ", use fillbuffer first"<< LogIO::POST;
+ return False;
+ }
+ String item = buffer_p.asString(RecordFieldId("datafield"));
+ if (item.contains("data")) {
+ os << LogIO::WARN << "Can't clip complex data,"<<
+ " use diffbuffer first or load a derived quantity"<< LogIO::POST;
+ return False;
+ }
+
+ // retrieve the data
+ Array<Bool> flag = buffer_p.asArrayBool(RecordFieldId("flag"));
+ Array<Bool> flagRow = buffer_p.asArrayBool(RecordFieldId("flag_row"));
+ Array<Float> diff = buffer_p.asArrayFloat(RecordFieldId(item));
+
+ // retrieve the stats
+ Matrix<Float> adT, adF, medTF, adTF, medFmedT, medTmedF;
+ Cube<Float> medT, medF;
+ if (!buffer_p.isDefined("medTF")) {
+ // we haven't got stats yet
+ applyRowFlags(flag,flagRow); // need to apply row flags to flags for
stats
+ addStats(buffer_p,flag,flagRow,diff);
+ }
+ medTF = buffer_p.asArrayFloat("medTF");
+ adTF = buffer_p.asArrayFloat("adTF");
+ medT = buffer_p.asArrayFloat("medT");
+ medFmedT = buffer_p.asArrayFloat("medFmedT");
+ adT = buffer_p.asArrayFloat("adT");
+ medF = buffer_p.asArrayFloat("medF");
+ medTmedF = buffer_p.asArrayFloat("medTmedF");
+ adF = buffer_p.asArrayFloat("adF");
+/*
+ GlishArray(buffer_p.get("adTF")).get(adTF);
+ GlishArray(buffer_p.get("medT")).get(medT);
+ GlishArray(buffer_p.get("medFmedT")).get(medFmedT);
+ GlishArray(buffer_p.get("adT")).get(adT);
+ GlishArray(buffer_p.get("medF")).get(medF);
+ GlishArray(buffer_p.get("medTmedF")).get(medTmedF);
+ GlishArray(buffer_p.get("adF")).get(adF);
+*/
+ Bool deleteFlag, deleteFlagRow, deleteDiff;
+ Bool* pflagRow = flagRow.getStorage(deleteFlagRow);
+ Bool* pflag = flag.getStorage(deleteFlag);
+ const Float* pdiff = diff.getStorage(deleteDiff);
+ const Int nCorr=flag.shape()(0);
+ const Int nChan=flag.shape()(1);
+ Int nTime=flag.shape()(2);
+ const Int nXY=nCorr*nChan;
+ Int nIfr=1;
+ if (flag.ndim()==4) {
+ nIfr=nTime;
+ nTime=flag.shape()(3);
+ }
+ const Int nXYZ=nXY*nIfr;
+
+ // iterate till no more pixels are flagged
+ Bool iter=True;
+ Matrix<Int> sum(nCorr,nIfr),sumChan(nCorr,nIfr),sumTime(nCorr,nIfr);
+ sum=0, sumChan=0, sumTime=0;
+ while (iter) {
+ iter=False;
+
+ for (Int ifr=0, offset=0; ifr<nIfr; ifr++, offset=ifr*nXY) {
+ for (Int pol=0; pol<nCorr; pol++, offset++) {
+
+ // keep these values around
+ Float mfmt = medFmedT(pol,ifr);
+ Float adt = adT(pol,ifr);
+ Float mtmf = medTmedF(pol,ifr);
+ Float adf = adF(pol,ifr);
+ Float mtf = medTF(pol,ifr);
+ Float adtf = adTF(pol,ifr);
+
+ Int chanCount=0, timeCount=0, count=0;
+ // flag bad channels
+ {
+ for (Int i=0, offset2=offset; i<nChan; i++, offset2+=nCorr) {
+ Float mt=medT(pol,i,ifr);
+ if ( (mt>0) && (abs(mt-mfmt) > channelLevel*adt)) {
+ chanCount++;
+ for (Int j=0, offset3=offset2; j<nTime; j++, offset3+=nXYZ) {
+ pflag[offset3]=True;
+ }
+ }
+ }
+ }
+ // flag bad times
+ {
+ Int offrow=ifr;
+ for (Int i=0, offset2=offset; i<nTime;
+ i++,offset2+=nXYZ,offrow+=nIfr) {
+ if (!pflagRow[offrow]) {
+ Float mf=medF(pol,ifr,i);
+ if (mf>0 && abs(mf-mtmf) > timeLevel*adf) {
+ timeCount++;
+ for (Int j=0, offset3=offset2; j<nChan; j++, offset3+=nCorr) {
+ pflag[offset3]=True;
+ }
+ }
+ }
+ }
+ }
+ // flag bad pixels
+ {
+ Int offrow=ifr;
+ for (Int i=0, offset2=offset; i<nTime;
+ i++, offset2+=nXYZ, offrow+=nIfr) {
+ if (!pflagRow[offrow]) {
+ for (Int j=0, offset3=offset2; j<nChan; j++, offset3+=nCorr) {
+ if (!pflag[offset3] &&
+ abs(pdiff[offset3]-mtf) > pixelLevel*adtf) {
+ pflag[offset3]=True;
+ count++;
+ }
+ }
+ }
+ }
+ }
+ iter= (iter || chanCount>0 || timeCount>0 ||count>0);
+ sumChan(pol,ifr)+=chanCount;
+ sumTime(pol,ifr)+=timeCount;
+ sum(pol,ifr)+=count;
+ }
+ }
+ if (iter) {
+ if (deleteFlag||deleteFlagRow) {
+ cerr << " arrays have to be written back "<<endl;
+ flag.putStorage(pflag,deleteFlag);
+ flagRow.putStorage(pflagRow,deleteFlagRow);
+ }
+ applyRowFlags(flag,flagRow); //need to apply row flags to flags for
stats
+ getStats(medTF,adTF,medT,medFmedT,adT,medF,medTmedF,adF,
+ diff, flag, flagRow);
+ if (deleteFlag||deleteFlagRow) {
+ cerr << " arrays have to be read back "<<endl;
+ pflag=flag.getStorage(deleteFlag);
+ pflagRow=flagRow.getStorage(deleteFlagRow);
+ }
+ }
+ }
+
+ for (Int ifr=0; ifr<nIfr; ifr++) {
+ for (Int pol=0; pol<nCorr; pol++) {
+ if ((sumChan(pol,ifr)>0 || sumTime(pol,ifr)>0 || sum(pol,ifr)>0)) {
+ if (nIfr>1) {
+ os << LogIO::NORMAL << "Polarization# = "<< pol+1 <<
+ ", Interferometer# = "<< ifr+1 << LogIO::POST;
+ } else if (nCorr>1) {
+ os << LogIO::NORMAL << "Polarization# = "<< pol+1 << LogIO::POST;
+ }
+ }
+ if (sumChan(pol,ifr)>0) {
+ os << LogIO::NORMAL << "Flagged "<<sumChan(pol,ifr)<<" channel"<<
+ multiple(sumChan(pol,ifr))<<
+ " with abs(median - " << medTmedF(pol,ifr) << ") > "<<channelLevel
+ << "*" << adF(pol,ifr) <<LogIO::POST;
+ }
+ if (sumTime(pol,ifr)>0) {
+ os << LogIO::NORMAL << "Flagged "<<sumTime(pol,ifr)<<" time"<<
+ multiple(sumTime(pol,ifr))<<
+ " with abs(median - " << medFmedT(pol,ifr) << ") > "<< timeLevel
+ << "*" <<adT(pol,ifr)<<LogIO::POST;
+ }
+ if (sum(pol,ifr)>0) {
+ os << LogIO::NORMAL << "Flagged "<<sum(pol,ifr)<<" pixel"<<
+ multiple(sum(pol,ifr))<<
+ " with abs(pixval - "<< medTF(pol,ifr) << ") > "<< pixelLevel <<
+ "*" << adTF(pol,ifr)<<LogIO::POST;
+ }
+ }
+ }
+ flag.putStorage(pflag,deleteFlag);
+ flagRow.putStorage(pflagRow,deleteFlagRow);
+ diff.freeStorage(pdiff,deleteDiff);
+ buffer_p.define("flag",flag);
+ buffer_p.define("flag_row",flagRow);
+ buffer_p.define("medTF",medTF);
+ buffer_p.define("adTF",adTF);
+ buffer_p.define("medT",medT);
+ buffer_p.define("medF",medF);
+ buffer_p.define("adT",adT);
+ buffer_p.define("adF",adF);
+ buffer_p.define("medTmedF",medTmedF);
+ buffer_p.define("medFmedT",medFmedT);
+ return True;
+}
+
+Bool MSFlagger::setDataBufferFlags(const Record& flags)
+{
+ LogIO os;
+ if (!buffer_p.isDefined("datafield")) {
+ os << LogIO::WARN <<
+ "Data buffer is empty, use filldatabuffer first"<< LogIO::POST;
+ return False;
+ }
+ buffer_p.define("flag",flags.asArrayBool(RecordFieldId("flag")));
+ buffer_p.define("flag_row",flags.asArrayBool(RecordFieldId("flag_row")));
+ return True;
+}
+
+Bool MSFlagger::writeDataBufferFlags()
+{
+ LogIO os;
+ if (!check()) return False;
+ if (!msSel_p->selectedTable().isWritable()) {
+ os << LogIO::SEVERE << "MeasurementSet is not writable"<< LogIO::POST;
+ return False;
+ }
+ if (!buffer_p.isDefined("datafield")) {
+ os << LogIO::WARN <<
+ "Data buffer is empty, use filldatabuffer first"<< LogIO::POST;
+ return False;
+ }
+ Record items(RecordInterface::Variable);
+ items.define("flag_row",buffer_p.asArrayBool(RecordFieldId("flag_row")));
+ items.define("flag",buffer_p.asArrayBool(RecordFieldId("flag")));
+ return msSel_p->putData(items);
+}
+
+Bool MSFlagger::createFlagHistory(Int nHis)
+{
+ LogIO os;
+ if (!check()) return False;
+ MeasurementSet tab=msSel_p->selectedTable();
+ if (!tab.isWritable()) {
+ os << LogIO::WARN << "MS is not writable"<< LogIO::POST;
+ return False;
+ }
+ if (nHis<2 || nHis>16) {
+ os << LogIO::WARN << "Invalid argument: 2<=nHis<=16 "<< LogIO::POST;
+ return False;
+ }
+ if (tab.isColumn(MS::FLAG_CATEGORY)) {
+ os << LogIO::WARN << "FLAG_CATEGORY column already
exists"<<LogIO::POST;
+ return False;
+ }
+ // Look for the FLAG column among the hypercolumns
+ String flagHypercubeId="";
+ Bool found=findHypercubeId(flagHypercubeId,MS::columnName(MS::FLAG),tab);
+
+ Vector<String> coordColNames(0), idColNames(1);
+ TableDesc td1;
+ if (!found) {
+ // If there's no id, assume the data is fixed shape throughout
+ ROArrayColumn<Bool> flagCol(tab,MS::columnName(MS::FLAG));
+ Int numCorr=flagCol.shape(0)(0);
+ Int numChan=flagCol.shape(0)(1);
+ IPosition shape(3,nHis,numCorr,numChan);
+ idColNames.resize(0);
+ td1.addColumn(ArrayColumnDesc<Bool>("FLAG_CATEGORY","flag
history",shape,
+ ColumnDesc::Direct));
+ td1.defineHypercolumn("TiledFlagHistory",4,
+ stringToVector("FLAG_CATEGORY"),coordColNames,
+ idColNames);
+ // fixed data shape
+ Int tileSize=numChan/10+1;
+ IPosition tileShape(4,1,numCorr,tileSize,16384/numCorr/tileSize);
+ TiledColumnStMan tiledStMan1("TiledFlagHistory",tileShape);
+ tab.addColumn(td1,tiledStMan1);
+ fillFlagHist(nHis,numCorr,numChan,tab);
+ } else {
+ {
+ ROArrayColumn<Bool> flagCol(tab,MS::columnName(MS::FLAG));
+ idColNames(0)="FLAG_CATEGORY_HYPERCUBE_ID";
+ td1.addColumn(ArrayColumnDesc<Bool>("FLAG_CATEGORY","flag
history",3));
+ td1.addColumn(ScalarColumnDesc<Int>("FLAG_CATEGORY_HYPERCUBE_ID",
+ "hypercube index"));
+ td1.defineHypercolumn("TiledFlagHistory",4,
+ stringToVector("FLAG_CATEGORY"),coordColNames,
+ idColNames);
+ // data shape may change
+ TiledDataStMan tiledStMan1("TiledFlagCategory");
+ tab.addColumn(td1,tiledStMan1);
+ TiledDataStManAccessor flagCatAccessor(tab,"TiledFlagCategory");
+
+ // get the hypercube ids, sort them, remove the duplicate values
+ ROScalarColumn<Int> hypercubeId(tab,flagHypercubeId);
+ Vector<Int> ids=hypercubeId.getColumn();
+ Int
nId=genSort(ids,Sort::Ascending,Sort::QuickSort+Sort::NoDuplicates);
+ ids.resize(nId,True); // resize and copy values
+ Vector<Bool> cubeAdded(nId,False);
+ Record values1;
+ values1.define("FLAG_CATEGORY_HYPERCUBE_ID",hypercubeId(0));
+ Int cube;
+ for (cube=0; cube<nId; cube++) if (ids(cube)==hypercubeId(0)) break;
+ Int nRow=tab.nrow();
+ for (Int i=0; i<nRow; i++) {
+ // add new hyperCube
+ if (i>0 && hypercubeId(i)!=hypercubeId(i-1)) {
+ values1.define("FLAG_CATEGORY_HYPERCUBE_ID",hypercubeId(i));
+ for (cube=0; cube<nId; cube++) if (ids(cube)==hypercubeId(i)) break;
+ }
+ if (!cubeAdded(cube)) {
+ cubeAdded(cube)=True;
+ Int numCorr=flagCol.shape(i)(0);
+ Int numChan=flagCol.shape(i)(1);
+ Int tileSize=numChan/10+1;
+ IPosition cubeShape(4,nHis,numCorr,numChan,0);
+ IPosition tileShape(4,1,numCorr,tileSize,16384/numCorr/tileSize);
+ flagCatAccessor.addHypercube(cubeShape,tileShape,values1);
+ }
+ flagCatAccessor.extendHypercube(1,values1);
+ }
+ }
+
+ TableIterator obsIter(tab,flagHypercubeId);
+ for (;!obsIter.pastEnd(); obsIter.next()) {
+ ROArrayColumn<Bool>
flagCol(obsIter.table(),MS::columnName(MS::FLAG));
+ Int numCorr=flagCol.shape(0)(0);
+ Int numChan=flagCol.shape(0)(1);
+ Table tab=obsIter.table();
+ fillFlagHist(nHis,numCorr,numChan,tab);
+ }
+ }
+ return True;
+}
+
+Bool MSFlagger::findHypercubeId(String& hypercubeId, const String& column,
+ const Table& tab)
+{
+ // to find the corresponding id column (if any)
+ TableDesc td(tab.tableDesc());
+ Vector<String> hypercolumnNames=td.hypercolumnNames();
+ Bool found=False;
+ hypercubeId="";
+ if (hypercolumnNames.nelements()>0) {
+ for (uInt i=0; i<hypercolumnNames.nelements(); i++) {
+ Vector<String> colNames,coordColNames,idColNames;
+ td.hypercolumnDesc(hypercolumnNames(i),
+ colNames,coordColNames,
+ idColNames);
+ for (uInt j=0; j<colNames.nelements(); j++) {
+ if (colNames(j)==column) {
+ found=(idColNames.nelements()>0);
+ if (found) hypercubeId=idColNames(0);
+ }
+ }
+ }
+ }
+ return found;
+}
+
+void MSFlagger::fillFlagHist(Int nHis, Int numCorr, Int numChan, Table&
tab)
+{
+ // fill the first two levels of flagging with the flags present
+ // in the MS columns FLAG and FLAG_ROW.
+ const Int maxRow=1000000/(numCorr*numChan); // of order 1 MB chunks
+ ROArrayColumn<Bool> flagCol(tab,MS::columnName(MS::FLAG));
+ ArrayColumn<Bool> flagHisCol(tab,MS::columnName(MS::FLAG_CATEGORY));
+ Array<Bool> flagHis(IPosition(4,nHis,numCorr,numChan,maxRow));
+ // flag level 0
+ Cube<Bool> ref0(flagHis(IPosition(4,0,0,0,0),
+ IPosition(4,0,numCorr-1,numChan-1,maxRow-1)).
+ reform(IPosition(3,numCorr,numChan,maxRow)));
+ // flag level 1
+ Cube<Bool> ref1(flagHis(IPosition(4,1,0,0,0),
+ IPosition(4,1,numCorr-1,numChan-1,maxRow-1)).
+ reform(IPosition(3,numCorr,numChan,maxRow)));
+ flagHis.set(False);
+ Int nRow=tab.nrow();
+ ROScalarColumn<Bool> flagRowCol(tab,MS::columnName(MS::FLAG_ROW));
+ Array<Bool> flagCube;
+ Vector<Bool> flagRowVec;
+ for (Int i=0; i<=(nRow/maxRow); i+=maxRow) {
+ Int n=min(maxRow,nRow-maxRow*i);
+ if (n<maxRow) {
+ flagHis.resize(IPosition(4,nHis,numCorr,numChan,n));
+ flagHis.set(False);
+ Array<Bool> tmp0(flagHis(IPosition(4,0,0,0,0),
+ IPosition(4,0,numCorr-1,numChan-1,n-1)).
+ reform(IPosition(3,numCorr,numChan,n)));
+ ref0.reference(tmp0);
+ Array<Bool> tmp1(flagHis(IPosition(4,1,0,0,0),
+ IPosition(4,1,numCorr-1,numChan-1,n-1)).
+ reform(IPosition(3,numCorr,numChan,n)));
+ ref1.reference(tmp1);
+ }
+ Slicer rowSlice(Slice(i*maxRow,n));
+ flagRowCol.getColumnRange(rowSlice,flagRowVec,True);
+ flagCol.getColumnRange(rowSlice,flagCube,True);
+ ref0=flagCube;
+ for (Int j=0; j<n; j++) {
+ if (flagRowVec(j)) {
+ ref0.xyPlane(j).set(True);
+ }
+ }
+ ref1=ref0;
+ flagHisCol.putColumnRange(rowSlice,flagHis);
+ }
+ // Set the FLAG_LEVEL keyword to 1, to indicate we will be
+ // using these flags (level 0 flags are those already present)
+ flagHisCol.rwKeywordSet().define("FLAG_LEVEL",1);
+}
+
+Bool MSFlagger::saveFlags(Bool newLevel)
+{
+ LogIO os;
+ if (!check()) return False;
+ MeasurementSet tab=msSel_p->selectedTable();
+ if (!tab.isColumn(MS::FLAG_CATEGORY)) {
+ os << LogIO::WARN << "FLAG_CATEGORY column does not
exist"<<LogIO::POST;
+ return False;
+ }
+ if (!tab.isWritable()) {
+ os << LogIO::WARN << "MS is not writable"<< LogIO::POST;
+ return False;
+ }
+ ArrayColumn<Bool> flagHisCol(tab,MS::columnName(MS::FLAG_CATEGORY));
+ Int level;
+ flagHisCol.keywordSet().get("FLAG_LEVEL",level);
+ if (newLevel) {
+ if (level+1>=flagHisCol.shape(0)(0)) {
+ os << LogIO::WARN << "No space for new flag level
("<<(level+1)+1<<") in "
+ << "FLAG_CATEGORY column, using current level instead"<<LogIO::POST;
+ } else {
+ level++;
+ }
+ }
+
+ String hypercubeId;
+ Bool
found=findHypercubeId(hypercubeId,MS::columnName(MS::FLAG_CATEGORY),tab);
+ if (!found) {
+ // data has fixed shape
+ saveToFlagHist(level,tab);
+ } else {
+ // data changes shape, iterate
+ TableIterator tabIter(tab,hypercubeId);
+ for (; !tabIter.pastEnd(); tabIter++) {
+ Table tab1=tabIter.table();
+ saveToFlagHist(level,tab1);
+ }
+ }
+ if (newLevel) flagHisCol.rwKeywordSet().define("FLAG_LEVEL",level);
+ return True;
+}
+
+void MSFlagger::saveToFlagHist(Int level, Table& tab)
+{
+ ROArrayColumn<Bool> flagCol(tab,MS::columnName(MS::FLAG));
+ Int numCorr=flagCol.shape(0)(0);
+ Int numChan=flagCol.shape(0)(1);
+ const Int maxRow=1000000/(numCorr*numChan); // of order 1 MB chunks
+ Array<Bool> flagHis(IPosition(4,1,numCorr,numChan,maxRow));
+ Cube<Bool> ref(flagHis.reform(IPosition(3,numCorr,numChan,maxRow)));
+ Int nRow=tab.nrow();
+ Array<Bool> flagCube;
+ Vector<Bool> flagRowVec;
+ Slicer slicer(Slice(level,1),Slice(0,numCorr),Slice(0,numChan));
+ for (Int i=0; i<=(nRow/maxRow); i+=maxRow) {
+ Int n=min(maxRow,nRow-maxRow*i);
+ if (n<maxRow) {
+ flagHis.resize(IPosition(4,1,numCorr,numChan,n));
+ Array<Bool> tmp(flagHis.reform(IPosition(3,numCorr,numChan,n)));
+ ref.reference(tmp);
+ }
+ Vector<uInt> rows(n);
+ indgen(rows,uInt(i*maxRow));
+ Table sel=tab(rows);
+ ArrayColumn<Bool> flagHisCol(sel,MS::columnName(MS::FLAG_CATEGORY));
+ ROArrayColumn<Bool> flagCol(sel,MS::columnName(MS::FLAG));
+ ROScalarColumn<Bool> flagRowCol(sel,MS::columnName(MS::FLAG_ROW));
+ flagCol.getColumn(flagCube,True);
+ flagRowCol.getColumn(flagRowVec,True);
+ ref=flagCube;
+ for (Int j=0; j<n; j++) {
+ if (flagRowVec(j)) {
+ ref.xyPlane(j).set(True);
+ }
+ }
+ flagHisCol.putColumn(slicer,flagHis);
+ }
+}
+
+Bool MSFlagger::restoreFlags(Int level)
+{
+ LogIO os;
+ if (!check()) return False;
+ MeasurementSet tab=msSel_p->selectedTable();
+ if (!tab.isColumn(MS::FLAG_CATEGORY)) {
+ os << LogIO::WARN << "FLAG_CATEGORY column does not
exist"<<LogIO::POST;
+ return False;
+ }
+ if (!tab.isWritable()) {
+ os << LogIO::WARN << "MS is not writable"<< LogIO::POST;
+ return False;
+ }
+ ArrayColumn<Bool> flagHisCol(tab,MS::columnName(MS::FLAG_CATEGORY));
+ Int flagLevel=level;
+ if (flagLevel==-1) flagHisCol.keywordSet().get("FLAG_LEVEL",flagLevel);
+ if (flagLevel<0 || flagLevel>=flagHisCol.shape(0)(0)) {
+ os << LogIO::WARN << "Invalid flag level
("<<flagLevel+1<<")"<<LogIO::POST;
+ return False;
+ }
+ String hypercubeId;
+ Bool
found=findHypercubeId(hypercubeId,MS::columnName(MS::FLAG_CATEGORY),tab);
+ if (!found) {
+ // data has fixed shape
+ applyFlagHist(flagLevel,tab);
+ } else {
+ // data changes shape, iterate
+ TableIterator tabIter(tab,hypercubeId);
+ for (; !tabIter.pastEnd(); tabIter++) {
+ Table tab=tabIter.table();
+ applyFlagHist(flagLevel,tab);
+ }
+ }
+ if (level!=-1) flagHisCol.rwKeywordSet().define("FLAG_LEVEL",level);
+ return True;
+}
+
+void MSFlagger::applyFlagHist(Int level, Table& tab)
+{
+ Int nRow=tab.nrow();
+ ROArrayColumn<Bool> flagHisCol(tab,MS::columnName(MS::FLAG_CATEGORY));
+ IPosition shape=flagHisCol.shape(0); shape(0)=1;
+ const Int maxRow=1000000/(shape(1)*shape(2)); // of order 1 MB chunks
+ Slicer slicer(Slice(level,1),Slice(0,shape(1)),Slice(0,shape(2)));
+ for (Int i=0; i<=nRow/maxRow; i++) {
+ Int n=min(maxRow,nRow-i*maxRow);
+ Vector<uInt> rows(n);
+ indgen(rows,uInt(i*maxRow));
+ Table sel=tab(rows);
+ ROArrayColumn<Bool> flagHisCol(sel,MS::columnName(MS::FLAG_CATEGORY));
+ Cube<Bool> flag(flagHisCol.getColumn(slicer).
+ reform(IPosition(3,shape(1),shape(2),n)));
+ ArrayColumn<Bool> flagCol(sel,MS::columnName(MS::FLAG));
+ ScalarColumn<Bool> flagRowCol(sel,MS::columnName(MS::FLAG_ROW));
+ flagCol.putColumn(flag);
+ for (Int j=0; j<n; j++) {
+ if (allEQ(flag.xyPlane(j),True)) {
+ flagRowCol.put(j,True);
+ } else {
+ flagRowCol.put(j,False);
+ }
+ }
+ }
+}
+
+Int MSFlagger::flagLevel()
***The diff for this file has been truncated for email.***
=======================================
--- /dev/null
+++ /branches/nov14/ms/MSOper/MSFlagger.h Wed Mar 25 14:33:54 2015 UTC
@@ -0,0 +1,232 @@
+//# MSFlagger.h: this defines MSFlagger, which implement flagging/editing
+//# Copyright (C) 1997,1998,1999,2000
+//# Associated Universities, Inc. Washington DC, USA.
+//#
+//# This library is free software; you can redistribute it and/or modify it
+//# under the terms of the GNU Library General Public License as published
by
+//# the Free Software Foundation; either version 2 of the License, or (at
your
+//# option) any later version.
+//#
+//# This library is distributed in the hope that it will be useful, but
WITHOUT
+//# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+//# FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
+//# License for more details.
+//#
+//# You should have received a copy of the GNU Library General Public
License
+//# along with this library; if not, write to the Free Software Foundation,
+//# Inc., 675 Massachusetts Ave, Cambridge, MA 02139, USA.
+//#
+//# Correspondence concerning AIPS++ should be addressed as follows:
+//# Internet email:
aips2-...@nrao.edu.
+//# Postal address: AIPS++ Project Office
+//# National Radio Astronomy Observatory
+//# 520 Edgemont Road
+//# Charlottesville, VA 22903-2475 USA
+//#
+//#
+//# $Id$
+
+#ifndef MS_MSFLAGGER_H
+#define MS_MSFLAGGER_H
+
+#include <casacore/casa/aips.h>
+#include <casacore/casa/Containers/Record.h>
+
+namespace casacore { //# NAMESPACE CASACORE - BEGIN
+
+template <class T> class Array;
+class MSSelector;
+class Table;
+class String;
+
+// <summary>
+// MSFlagger specifies selections on a MeasurementSet
+// </summary>
+
+// <use visibility=export>
+
+// <reviewed reviewer="" date="yyyy/mm/dd" tests="" demos="">
+// </reviewed>
+
+// <prerequisite>
+// <li> MeasurementSet
+// <li> SomeOtherClass
+// <li> some concept
+// </prerequisite>
+//
+// <etymology>
+// MSFlagger is a class that sets flags in an MS
+// </etymology>
+//
+// <synopsis>
+// This class is used to change the flag and flag_history columns in
+// a MeasurementSet. It provides functions for automated flagging based on
+// clipping the data that is too far from the median value.
+// The ms DO uses this class to allow flagging from glish or a GUI.
+//
+// <example> <srcblock>
+// MSFlagger msFlagger(myMS);
+// </srcblock></example>
+// </synopsis>
+//
+// <motivation>
+// Flagging/editing of data is a central requirement in data processing,
this
+// class provides some simple flagging algorithms and the code
+// that modifies & creates flag columns in the MS.
+// </motivation>
+//
+// <thrown>
+// <li>
+// <li>
+// </thrown>
+//
+// <todo asof="yyyy/mm/dd">
+// <li> add this feature
+// </todo>
+
+class MSFlagger
+{
+public:
+ MSFlagger();
+
+ // construct from an MSSelector object
+ MSFlagger(MSSelector& msSel);
+
+ // Copy constructor
+ MSFlagger(const MSFlagger& other);
+
+ // Assignment
+ MSFlagger& operator=(const MSFlagger& other);
+
+ ~MSFlagger();
+
+ // Change or Set the MS this MSFlagger refers to.
+ void setMSSelector(MSSelector& msSel);
+
+ // Fill an internal buffer with the data item requested, similar to
getData
+ // except that the data is not returned, but kept around for further
+ // processing. Only a single DATA related quantity can be requested, the
+ // corresponding FLAG and FLAG_ROW columns are read automatically.
+ // Reorder the data to 4d with ifr and time axis if ifrAxis is True.
+ Bool fillDataBuffer(const String& item, Bool ifrAxis);
+
+ // Difference the data, subtracting the average over a window of
+ // specified width and taking the absolute value. Complex quantities are
+ // turned into the corresponding amplitude after differencing.
+ // If doMedian==True the median difference is returned for window>2.
+ // For a window width of one, the previous sample is
+ // subtracted, giving a derivative like quantity.
+ // Note that the subtraction is done on row-by-row basis for TIME
+ // differencing, it is up to you to select a single baseline (if
+ // you didn't use ifrAxis=True in fillDataBuffer).
+ // Available directions are: TIME, CHANNEL
+ // Returns statistics over the buffer: median for times and channels,
+ // average absolute deviation over times, channels and all pixels.
+ Record diffDataBuffer(const String& direction, Int window=1,
+ Bool doMedian = False);
+
+ // Return the contents of the internal data buffer, including the flags
+ // as a Record
+ Record getDataBuffer()
+ { return buffer_p;}
+
+ // Clip the data buffer at a specified level by setting the corresponding
+ // flags in the buffer. The cliplevel is specified as a multiple of
+ // the average absolute deviations returned by diffDataBuffer.
+ // A value of zero or less will skip the corresponding clip operation.
+ // Clipping will be done repeatedly, recalculating the deviations, until
+ // no more points are clipped.
+ Bool clipDataBuffer(Float pixelLevel, Float timeLevel, Float
channelLevel);
+
+ // Replace the flags in the buffer with those in the supplied record.
+ // This allows interactive flagging from glish to be written back to the
+ // buffer for subsequent operations. The record should contain a
+ // flag and flag_row field.
+ Bool setDataBufferFlags(const Record& flags);
+
+ // Write the flags in the buffer back to the table
+ Bool writeDataBufferFlags();
+
+ // Clear the internal data buffer, reclaiming memory
+ Bool clearDataBuffer()
+ { buffer_p=Record(); return True;}
+
+ // Create the FLAG_HISTORY column and initialize it from the
+ // FLAG_ROW and FLAG columns. Returns False if FLAG_HISTORY already
exists.
+ // The first flagging bit is filled with the flags as found in the MS,
+ // subsequent bits can be used for user generated flags.
+ Bool createFlagHistory(Int nHis = 2);
+
+ // Apply the flags in the FLAG_HISTORY column to the FLAG and FLAG_ROW
+ // columns. Returns False if FLAG_HISTORY doesn't exist.
+ // The default argument will apply the currently active flag level
+ // (as specified by the FLAG_LEVEL column keyword).
+ // Sets the current level to the flag level restored.
+ Bool restoreFlags(Int level=-1);
+
+ // Save the current flags to the FLAG_HISTORY. Save to the currently
+ // active level or (newLevel=True) the next highest level (if available).
+ // Will reset the current level to the level saved to.
+ Bool saveFlags(Bool newLevel);
+
+ // Return the current flaglevel (value of FLAG_LEVEL keyword)
+ Int flagLevel();
+
+protected:
+ // fill the FLAG_HISTORY column from the FLAG and FLAG_ROW column
+ void fillFlagHist(Int nHis, Int numCorr, Int numChan, Table& tab);
+
+ // find the HypercubeId column for a tiled column (if any)
+ Bool findHypercubeId(String& hyperCubeId, const String& column,
+ const Table& tab);
+
+ // copy the flags to the flag history
+ void saveToFlagHist(Int level, Table& tab);
+
+ // copy the flag history back to the flags
+ void applyFlagHist(Int level, Table& tab);
+
+ // get buffer statistics - med=median, ad=average absolute deviation,
+ // T=Time, F=Frequency.
+ void getStats(Array<Float>& medTF, Array<Float>& adTF,
+ Array<Float>& medT, Array<Float>& medFmedT,
+ Array<Float>& adT, Array<Float>& medF,
+ Array<Float>& medTmedF, Array<Float>& adF,
+ const Array<Float>& diff, const Array<Bool>& flag,
+ const Array<Bool>& flagRow);
+
+ // add the statistics to a buffer
+ void addStats(Record& buf, const Array<Bool>& flag,
+ const Array<Bool> flagRow, const Array<Float>& data);
+
+ // reorder from 2d to 1d (removing ifr axis)
+ void reorderFlagRow(Array<Bool>& flagRow);
+
+ // collapse array "in" (with absolute differences)
+ // along specified axis by taking medians by profile taking into account
+ // the flags.
+ void diffMedian(Array<Float>& out, const Array<Float>& in,
+ Int axis, const Array<Bool>& flag);
+
+ // apply the row flags to the data flags and v.v.
+ void applyRowFlags(Array<Bool>& flag, Array<Bool>& flagRow);
+
+ // check if we are attached to an MSSelector
+ Bool check();
+
+private:
+ MSSelector* msSel_p;
+ Record buffer_p;
+};
+
+
+} //# NAMESPACE CASACORE - END
+
+#endif
+
+
+
+
+
+
+
=======================================
--- /dev/null
+++ /branches/nov14/ms/MSOper/MSKeys.cc Wed Mar 25 14:33:54 2015 UTC
@@ -0,0 +1,137 @@
+//# Copyright (C) 1998,1999,2000,2001
+//# Associated Universities, Inc. Washington DC, USA.
+//#
+//# This library is free software; you can redistribute it and/or modify it
+//# under the terms of the GNU Library General Public License as published
by
+//# the Free Software Foundation; either version 2 of the License, or (at
your
+//# option) any later version.
+//#
+//# This library is distributed in the hope that it will be useful, but
WITHOUT
+//# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+//# FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
+//# License for more details.
+//#
+//# You should have received a copy of the GNU Library General Public
License
+//# along with this library; if not, write to the Free Software Foundation,
+//# Inc., 675 Massachusetts Ave, Cambridge, MA 02139, USA.
+//#
+//# Correspondence concerning AIPS++ should be addressed as follows:
+//# Internet email:
aips2-...@nrao.edu.
+//# Postal address: AIPS++ Project Office
+//# National Radio Astronomy Observatory
+//# 520 Edgemont Road
+//# Charlottesville, VA 22903-2475 USA
+//#
+
+#include <casacore/ms/MSOper/MSKeys.h>
+
+#include <casacore/casa/BasicSL/String.h>
+
+namespace casacore {
+
+Bool operator<(const SubScanKey& lhs, const SubScanKey& rhs) {
+ if (lhs.obsID < rhs.obsID) {
+ return True;
+ }
+ else if (lhs.obsID == rhs.obsID) {
+ if (lhs.arrayID < rhs.arrayID) {
+ return True;
+ }
+ else if (lhs.arrayID == rhs.arrayID) {
+ if (lhs.scan < rhs.scan) {
+ return True;
+ }
+ else if (lhs.scan == rhs.scan) {
+ if (lhs.fieldID < rhs.fieldID) {
+ return True;
+ }
+ }
+ }
+ }
+ return False;
+}
+
+String toString(const SubScanKey& subScanKey) {
+ return toString(scanKey(subScanKey)) + " fieldID="
+ + String::toString(subScanKey.fieldID);
+}
+
+std::ostream& operator<<(std::ostream& os, const SubScanKey& subScanKey) {
+ os << toString(subScanKey) << endl;
+ return os;
+}
+
+
+String toString(const ScanKey& scanKey) {
+ return "observationID=" + String::toString(scanKey.obsID)
+ + " arrayID=" + String::toString(scanKey.arrayID)
+ + " scan number=" + String::toString(scanKey.scan);
+}
+
+
+Bool operator<(const ScanKey& lhs, const ScanKey& rhs) {
+ if (lhs.obsID < rhs.obsID) {
+ return True;
+ }
+ else if (lhs.obsID == rhs.obsID) {
+ if (lhs.arrayID < rhs.arrayID) {
+ return True;
+ }
+ else if (lhs.arrayID == rhs.arrayID) {
+ if (lhs.scan < rhs.scan) {
+ return True;
+ }
+ }
+ }
+ return False;
+}
+
+std::set<Int> scanNumbers(const std::set<ScanKey>& scanKeys) {
+ std::set<Int> scanNumbers;
+ std::set<ScanKey>::const_iterator iter = scanKeys.begin();
+ std::set<ScanKey>::const_iterator end = scanKeys.end();
+ while (iter != end) {
+ scanNumbers.insert(iter->scan);
+ ++iter;
+ }
+ return scanNumbers;
+}
+
+ostream& operator<<(ostream& os, const ScanKey& scanKey) {
+ os << toString(scanKey) << endl;
+ return os;
+}
+
+
+Bool operator<(const ArrayKey& lhs, const ArrayKey& rhs) {
+ if (lhs.obsID < rhs.obsID) {
+ return True;
+ }
+ else if (lhs.obsID == rhs.obsID) {
+ if (lhs.arrayID < rhs.arrayID) {
+ return True;
+ }
+ }
+ return False;
+}
+
+std::set<ScanKey> scanKeys(
+ const std::set<Int>& scans, const ArrayKey& arrayKey
+) {
+ std::set<ScanKey> scanKeys;
+ std::set<Int>::const_iterator iter = scans.begin();
+ std::set<Int>::const_iterator end = scans.end();
+ ScanKey scanKey;
+ scanKey.obsID = arrayKey.obsID;
+ scanKey.arrayID = arrayKey.arrayID;
+ while (iter != end) {
+ scanKey.scan = *iter;
+ scanKeys.insert(scanKey);
+ ++iter;
+ }
+ return scanKeys;
+}
+
+
+}
+
=======================================
--- /dev/null
+++ /branches/nov14/ms/MSOper/MSKeys.h Wed Mar 25 14:33:54 2015 UTC
@@ -0,0 +1,100 @@
+//# Copyright (C) 1998,1999,2000,2001
+//# Associated Universities, Inc. Washington DC, USA.
+//#
+//# This library is free software; you can redistribute it and/or modify it
+//# under the terms of the GNU Library General Public License as published
by
+//# the Free Software Foundation; either version 2 of the License, or (at
your
+//# option) any later version.
+//#
+//# This library is distributed in the hope that it will be useful, but
WITHOUT
+//# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+//# FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
+//# License for more details.
+//#
+//# You should have received a copy of the GNU Library General Public
License
+//# along with this library; if not, write to the Free Software Foundation,
+//# Inc., 675 Massachusetts Ave, Cambridge, MA 02139, USA.
+//#
+//# Correspondence concerning AIPS++ should be addressed as follows:
+//# Internet email:
aips2-...@nrao.edu.
+//# Postal address: AIPS++ Project Office
+//# National Radio Astronomy Observatory
+//# 520 Edgemont Road
+//# Charlottesville, VA 22903-2475 USA
+//#
+//# $Id$
+
+#ifndef MS_MSKEYS_H
+#define MS_MSKEYS_H
+
+#include <casacore/casa/aips.h>
+
+#include <set>
+#include <ostream>
+
+namespace casacore {
+
+class String;
+
+// A sub scan is a unique combination of observation ID, array ID, scan
number,
+// and field ID. Negative values are allowed to indicate all values of the
particular
+// ID are desired.
+struct SubScanKey {
+ Int obsID;
+ Int arrayID;
+ Int scan;
+ Int fieldID;
+};
+
+// define operator<() so it can be used as a key in std::map
+Bool operator<(const SubScanKey& lhs, const SubScanKey& rhs);
+
+String toString(const SubScanKey& subScanKey);
+
+std::ostream& operator<<(std::ostream& os, const SubScanKey& scanKey);
+
+// A scan is a unique combination of observation ID, array ID, and scan
number
+// Negative values are allowed to indicate all values of the particular
+// ID are desired.
+struct ScanKey {
+ Int obsID;
+ Int arrayID;
+ Int scan;
+};
+
+// create a ScanKey from a SubScanKey, just omits the SubScanKey's fieldID
+inline ScanKey scanKey(const SubScanKey& subScanKey) {
+ ScanKey key;
+ key.obsID = subScanKey.obsID;
+ key.arrayID = subScanKey.arrayID;
+ key.scan = subScanKey.scan;
+ return key;
+}
+
+String toString(const ScanKey& scanKey);
+
+// define operator<() so it can be used as a key in std::map
+Bool operator<(const ScanKey& lhs, const ScanKey& rhs);
+
+// extract all the unique scan numbers from the specified scans
+std::set<Int> scanNumbers(const std::set<ScanKey>& scanKeys);
+
+std::ostream& operator<<(std::ostream& os, const ScanKey& scanKey);
+
+// An ArrayKey is a unique combination of observation ID and array ID
+// Negative values are allowed to indicate all values of the particular
+// ID are desired.
+struct ArrayKey {
+ Int obsID;
+ Int arrayID;
+};
+
+// define operator<() so it can be used as a key in std::map
+Bool operator<(const ArrayKey& lhs, const ArrayKey& rhs);
+
+// construct scan keys given a set of scan numbers and an ArrayKey
+std::set<ScanKey> scanKeys(const std::set<Int>& scans, const ArrayKey&
arrayKey);
+
+}
+
+#endif
=======================================
--- /dev/null
+++ /branches/nov14/ms/MSOper/MSLister.cc Wed Mar 25 14:33:54 2015 UTC
@@ -0,0 +1,1353 @@
+//# mslister.cc: class for listing records from a measurementset
+//# copyright (c) 1998,1999,2000,2001
+//# Associated Universities, Inc. Washington DC, USA.
+//#
+//# This library is free software; you can redistribute it and/or modify it
+//# under the terms of the GNU Library General Public License as published
by
+//# the Free Software Foundation; either version 2 of the License, or (at
your
+//# option) any later version.
+//#
+//# This library is distributed in the hope that it will be useful, but
WITHOUT
+//# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+//# FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
+//# License for more details.
+//#
+//# You should have received a copy of the GNU Library General Public
License
+//# along with this library; if not, write to the Free Software Foundation,
+//# Inc., 675 Massachusetts Ave, Cambridge, MA 02139, USA.
+//#
+//# Correspondence concerning AIPS++ should be addressed as follows:
+//# Internet email:
aips2-...@nrao.edu.
+//# Postal address: AIPS++ Project Office
+//# National Radio Astronomy Observatory
+//# 520 Edgemont Road
+//# Charlottesville, VA 22903-2475 USA
+//#
+//# $Id$
+//#
+#include <casacore/casa/Quanta/MVTime.h>
+#include <casacore/casa/Containers/RecordFieldId.h>
+#include <casacore/measures/Measures/Stokes.h>
+#include <casacore/ms/MeasurementSets/MSColumns.h>
+#include <casacore/ms/MeasurementSets/MeasurementSet.h>
+#include <casacore/ms/MSOper/MSLister.h>
+#include <casacore/ms/MSOper/MSSummary.h>
+#include <casacore/ms/MeasurementSets/MSRange.h>
+#include <casacore/ms/MeasurementSets/MSIter.h>
+#include <casacore/casa/Arrays/ArrayLogical.h>
+#include <casacore/casa/Arrays/ArrayMath.h>
+#include <casacore/casa/Arrays/MaskedArray.h>
+#include <casacore/casa/Arrays/MaskArrMath.h>
+#include <casacore/casa/iomanip.h>
+#include <casacore/casa/iostream.h>
+#include <casacore/casa/OS/File.h>
+
+#include <fstream>
+
+#include <casacore/ms/MSSel/MSSelectionTools.h>
+
+namespace casacore { //# NAMESPACE CASACORE - BEGIN
+
+//
+// Null constructor merely sets private formatting string
+//
+MSLister::MSLister ()
+ : dashline_p(replicate('-',80)),
+ mss_p()
+{
+ pMSSel_p = 0;
+}
+
+
+//
+// Constructor assigns pointer (if MS goes out of scope you will get
rubbish),
+// initialises the output, sets string to format output, and initialises
the
+// listing.
+//
+MSLister::MSLister (const MeasurementSet& ms, LogIO& os)
+ // : pMS_p(&ms),
+ : pMS_p(const_cast<MeasurementSet*>(&ms)),
+ logStream_p(os),
+ dashline_p(replicate('-',80)),
+ mss_p()
+{
+ // Move these into initList()?
+ // default precision (in case setPrecision is not called)
+ precTime_p = 7; // hh:mm:ss.s (0.1 s)
+ precUVDist_p = 0; // 1 wavelength
+ precUVW_p = 2; // 1 centimenter
+ precAmpl_p = 3; // mJy
+ precPhase_p = 1; // 0.1 deg
+ precWeight_p = 0; // unit weight
+ // initializations
+ wFld_p = wSpW_p = wChn_p = 0;
+ is_float = False; //default datacolumn is complex
+
+ // initialize list params
+ initList();
+
+ pMSSel_p = 0;
+}
+
+
+//
+// Assignment operator
+//
+MSLister& MSLister::operator=(MSLister& other)
+{
+ if (this==&other) return *this;
+ pMS_p = other.pMS_p;
+ return *this;
+}
+
+
+//
+// Destructor does nothing
+//
+MSLister::~MSLister()
+{}
+
+//
+// Reinitialise output stream. Do this before setMS() if doing both.
+//
+Bool MSLister::setNewOS (LogIO& os)
+{
+ logStream_p = os;
+ return True;
+}
+
+
+//
+// Reassign MS pointer and reinitialise MSLister object. Do this after
+// setNewOS() if doing both.
+//
+Bool MSLister::setMS (MeasurementSet& ms)
+{
+ pMS_p = &ms;
+ initList();
+ return True;
+}
+
+
+//
+// initList() does things that need to be done once per MS: initialises
+// the pagination/formatting, lists some header information, initialises
+// the MSSelector object, and gets all the attribute ranges up front.
+//
+ void MSLister::initList()
+ {
+ // Establish the formatting
+ // setFormat(); // the # of decimal places for data
+
+ // // Initialise the MSSelector object. By default,
initSelection() takes all
+ // // polarisations and the first spectral channel.
+ // mss_p.setMS(*pMS_p);
+ //
+ // mss_p.initSelection();
+
+ // Get the ranges (into ranges_p) of the following usefully
+ // selectable attributes. range_p can be changed later to
+ // refine selection.
+ // **SPW**
+ items_p.resize(6,False);
+ items_p(0)="time"; // the range of times
+ items_p(1)="antenna1"; // the list of antenna1 id values
+ items_p(2)="antenna2"; // the list of antenna2 id values
+ items_p(3)="uvdist"; // the range of the UV-distance
(m)
+ // items_p(4)="spectral_window_id"; // the list of spwin id
values
+ items_p(4)="data_desc_id"; // the list of data desc id
values
+ items_p(5)="field_id"; // the list of field id values
+ getRanges(*pMS_p);
+
+ // Set up for selection on channel or polarisation
+ ROMSSpWindowColumns msSpWinC(pMS_p->spectralWindow());
+ ROMSPolarizationColumns msPolC(pMS_p->polarization());
+ // nchan_p = msSpWinC.numChan()(0);
+ npols_p = msPolC.corrType()(0).nelements();
+ pols_p.resize(npols_p,False);
+ for (uInt i=0; i<npols_p; i++) {
+ // Store polarization strings in pols_p
+ pols_p(i) = Stokes::name(Stokes::type
+
(msPolC.corrType()(0)(IPosition(1,i))));
+ }
+ logStream_p << LogIO::NORMAL2 << "Polarizations (correlations) in
MS: "
+ << pols_p << LogIO::POST;
+
+ // Store spwin ref freqs for later use:
+ // (should get channel freqs for multi-channel MS's)
+ // freqs_p.resize(4,False);
+ freqs_p=msSpWinC.refFrequency().getColumn();
+
+ // Create map from data_desc_id to spwid:
+ ROMSDataDescColumns msDDI(pMS_p->dataDescription());
+ spwins_p=msDDI.spectralWindowId().getColumn();
+
+ // Signal completion of initList
+ logStream_p << LogIO::NORMAL1 << "Listing initialised for this MS"
<< LogIO::POST;
+ }
+
+// This function is not currently used. However, if an output precision
+// option is added to this class, this will be useful.
+void MSLister::setFormat (const uInt ndec)
+{
+ // Set up data display precision
+ nDecimal_p = ndec;
+}
+
+void MSLister::setPrecision ( const Int precTime, const Int precUVDist,
+ const Int precAmpl, const Int precPhase,
+ const Int precWeight )
+{
+ // Set private precision vars on basis of user input:
+ precTime_p = precTime+6; // internally, time precision includes
hhmmss.
+ precUVDist_p = precUVDist;
+ precAmpl_p = precAmpl;
+ precPhase_p = precPhase;
+ precWeight_p = precWeight;
+}
+
+// CLEANUP: This function is currently not used. Remove it?
+void MSLister::listHeader()
+{
+ // Construct the MSSummary object and output the header info
+ // ALL OF THESE SHOULD BE GIVEN PRIORITY NORMAL1.
+ MSSummary header(*pMS_p);
+ header.listTitle (logStream_p);
+ header.listWhat (logStream_p,False);
+ header.listSpectralWindow (logStream_p,True);
+ header.listPolarization (logStream_p,True);
+ header.listAntenna (logStream_p,True);
+ logStream_p.post();
+}
+
+
+ // Get the ranges of a fixed set of MS key attributes
+ void MSLister::getRanges(const MeasurementSet &ms)
+ {
+ logStream_p << LogIO::DEBUG1 << "Begin: MSLister::getRanges" <<
LogIO::POST;
+ // Get the full range of columns for an MS.
+ MSRange msr(ms);
+ ranges_p = msr.range(items_p); // shapeChangesWarning OCCURRING
HERE
+ logStream_p << LogIO::DEBUG1 << "End: MSLister::getRanges" <<
LogIO::POST;
+ }
+
+ void MSLister::list (const String&,
+ const String& datacolumn,
+ const String& field,
+ const String& spw,
+ const String& antenna,
+ const String& timerange,
+ const String& correlation,
+ const String& scan,
+ const String&,
+ const String&,
+ const String& observation,
+ const String& uvrange,
+ const String&,
+ const bool ,
+ const String& msSelect,
+ const long pagerows,
+ const String& listfile)
+{
+ try{
+ logStream_p << LogIO::DEBUG1 << "Begin: MSLister::list" << LogIO::POST;
+
+ String chanmode;
+ Int nchan;
+ Int start;
+ Int step;
+ MRadialVelocity mStart;
+ MRadialVelocity mStep;
+
+ // Empty spw string means select all spws and channels. To do this in
+ // MSSelection, spw must be set to "*".
+ String newSpw = spw;
+ if(newSpw.empty()) { newSpw = "*"; }
+
+ // Choose MSSelector keywords according to the value of datacolumn
+ dataColSel.resize(2);
+ if( datacolumn.empty() || datacolumn == "data") {
+ dataColSel(0) = "amplitude";
+ dataColSel(1) = "phase";
+ } else if (datacolumn == "float_data"){
+ dataColSel(0) = "float_data";
+ dataColSel(1) = "";
+ is_float = True;
+ } else if (datacolumn == "corrected") {
+ dataColSel(0) = "corrected_amplitude";
+ dataColSel(1) = "corrected_phase";
+ } else if (datacolumn == "model") {
+ dataColSel(0) = "model_amplitude";
+ dataColSel(1) = "model_phase";
+ } else if (datacolumn == "residual") {
+ dataColSel(0) = "residual_amplitude";
+ dataColSel(1) = "residual_phase";
+ } else {
+ logStream_p << LogIO::SEVERE << "datacolumn = " << datacolumn <<
LogIO::POST;
+ throw(AipsError("Unrecognized value in parameter datacolumn"));
+ }
+ // logStream_p << "dataColSel = " << dataColSel << LogIO::POST;
+ // cout << "dataColSel = " << dataColSel << endl;
+
+ selectvis(timerange, newSpw, scan, field, antenna, uvrange, chanmode,
+ nchan, start, step, mStart, mStep, correlation,
+ // IGNORE PARAMETERS THAT ARE NOT YET IMPLEMENTED
+ // array, msSelect);
+ "", observation, msSelect);
+
+ // List the data
+ listData(pagerows, listfile);
+ }
+ catch (AipsError x) {
+ logStream_p << LogOrigin("MSLister","list",WHERE)
+ << LogIO::SEVERE << "Caught exception: " << x.getMesg()
+ << LogIO::POST;
+ throw(AipsError("Error in MSLister::list"));
+ }
+}
+
+// // Select data (using MSSelection syntax)
+//
+// Questions: Is it necessary to sort the MS? Leaving sorting code for
now.
+
+// CLEANUP: Remove parameters that are not inputs to mssSetData; they are
no
+// longer used anywhere.
+void MSLister::selectvis(const String& timerange,
+ const String& spw,
+ const String& scan,
+ const String& field,
+ const String& antenna,
+ const String& uvrange,
+ const String&, // Not inputs to
mssSetData
+ const Int&,
+ const Int&,
+ const Int&,
+ const MRadialVelocity&,
+ const MRadialVelocity&,
+ const String& correlation,
+ const String& array,
+ const String& observation,
+ const String& msSelect)
+{
+ try {
+ logStream_p << LogIO::DEBUG1 << "Begin: MSLister::selectvis" <<
LogIO::POST;
+
+ // List input parameter values.
+ logStream_p << LogIO::DEBUG1 << "timerange = " << timerange << " ,
strlen = " << timerange.length() << endl;
+ logStream_p << LogIO::DEBUG1 << "spw = " << spw << " ,
strlen = " << spw.length() << endl;
+ logStream_p << LogIO::DEBUG1 << "scan = " << scan << " ,
strlen = " << scan.length() << endl;
+ logStream_p << LogIO::DEBUG1 << "field = " << field << " ,
strlen = " << field.length() << endl;
+ logStream_p << LogIO::DEBUG1 << "antenna = " << antenna << " ,
strlen = " << antenna.length() << endl;
+ logStream_p << LogIO::DEBUG1 << "uvrange = " << uvrange << " ,
strlen = " << uvrange.length() << endl;
+ logStream_p << LogIO::DEBUG1 << "correlation = " << correlation << " ,
strlen = " << correlation.length() << endl;
+ logStream_p << LogIO::DEBUG1 << "array = " << array << " ,
strlen = " << array.length() << endl;
+ logStream_p << LogIO::DEBUG1 << "observation = " << observation << " ,
strlen = " << observation.length() << endl;
+ logStream_p << LogIO::DEBUG1 << "msSelect = " << uvrange << " ,
strlen = " << msSelect.length() << LogIO::POST;
+ // logStream_p << "feed = " << feed << " , strlen = " <<
feed.length() << endl;
+ // logStream_p << "average = " << uvrange << " , strlen = " <<
average.length() << endl;
+ // logStream_p << "showflags = " << uvrange << " , strlen = " <<
showflags.length() << endl;
+
+ // Apply selection to the original MeasurementSet
+ if (!(timerange.empty() && spw.empty() && scan.empty() &&
field.empty() &&
+ antenna.empty() && uvrange.empty() && correlation.empty() &&
+ observation.empty() && msSelect.empty()) ) {
+ logStream_p << LogIO::NORMAL1
+ << "Performing selection on MeasurementSet"
+ << LogIO::POST;
+ } else {
+ logStream_p << LogIO::NORMAL1 << "No selection requested." <<
LogIO::POST;
+ }
+
+ if (pMSSel_p) {
+ delete pMSSel_p;
+ pMSSel_p=0;
+ }
+
+ // Assume no selection, for starters
+ pMSSel_p = new MeasurementSet(*pMS_p);
+
+ logStream_p << LogIO::DEBUG1
+ << "Calling calling MSSelection constructor with selection
parameters."
+ << LogIO::POST;
+ // // mssSetData Param Names
+ MSSelection *pMSSelection = new MSSelection(*pMS_p,
+ MSSelection::PARSE_NOW,
+ timerange, // timeExpr
+ antenna, // antennaExpr
+ field, // fieldExpr
+ spw, // spwExpr
+ uvrange, // uvDistExpr
+ msSelect, // taQLExpr
+ "", // correlation, // corrExpr
+ scan, // scanExpr
+ array, // arrayExpr
+ "", // stateExpr
+ observation); // observationExpr
+
+ // Check to see if selection returned any rows.
+ Bool nonTrivial = pMSSelection->getSelectedMS(*pMSSel_p, "");
+ Vector<Int> selSPW = pMSSelection->getSpwList();
+ ROMSDataDescColumns ddCols(pMS_p->dataDescription());
+ ROScalarColumn<Int> ddpolIDs = ddCols.polarizationId();
+ ROScalarColumn<Int> spwIDs = ddCols.spectralWindowId();
+ Vector<Int> selDDIDs(selSPW.size());
+ uInt idx = 0;
+ for (uInt i=0; i<selSPW.size(); i++) {
+ for (uInt j=0; j<spwIDs.nrow(); j++) {
+ if (selSPW[i] == spwIDs(j)) {
+ selDDIDs[idx] = j;
+ idx++;
+ break;
+ }
+ }
+ }
+ Int selDDID = selDDIDs[0];
+ if (selDDIDs.size() > 1) {
+ for (uInt i=1; i<selDDIDs.size(); i++) {
+ if (ddpolIDs(selDDIDs[i]) != selDDID) {
+ throw AipsError(
+ "The selection corresponds to multiple polarization configurations.
Try reducing the number of selected spectral windows."
+ );
+ }
+ }
+ }
+ Int selPolID = ddpolIDs(selDDID);
+ /* // Write the selected MS to disk
+ // This proved to be useful for investigating strange listvis output;
+ // it's easier to snoop inside a small subset of an MS than to snoop
inside
+ // the whole thing.
+ String selectedMS = "
MSLister.selected.ms";
+ logStream_p << LogIO::NORMAL1 << "Writing selected MS to disk
(overwriting if necessary)." << LogIO::POST;
+ cout << "Writing selected MS to disk (overwriting if necessary)." <<
endl;
+ pMSSel_p->deepCopy(selectedMS, Table::New);
+ logStream_p << LogIO::NORMAL1 << selectedMS << " written." <<
LogIO::POST;
+ cout << selectedMS << " written." << endl;
+ */
+
+ // What channels are contained in the selected data?
+ chanList_p=pMSSelection->getChanList();
+ logStream_p << LogIO::DEBUG1 << "pMSSelection->getChanList() = " <<
endl
+ << pMSSelection->getChanList() << LogIO::POST;
+
+ // Do not make a list of all channels!
+ uInt nrowCL = chanList_p.nrow();
+ // Determine if more than one spw will be listed.
+ multiSpw_p = False;
+ Int t_spw = chanList_p(0,0); // 1st selected spw
+ for(uInt i=1; i<nrowCL; i++) {
+ if(chanList_p(i,0) != t_spw) {
+ multiSpw_p = True;
+ break; // break out of for loop
+ }
+ }
+ // Determine if more than one channel will be listed.
+ multiChan_p = False;
+ for(uInt i=0; i<nrowCL; i++) {
+ if(chanList_p(i,1) != chanList_p(i,2)) {
+ multiChan_p = True; // List multiple channels.
+ break; // break out of for loop
+ }
+ }
+
+ // // Gather channels to be listed into Vector channels_p
+ // for(uInt i=0; i<chanList.nrow(); i++) {
+ // Int nChanAdd = (chanList(i,2) - chanList(i,1) + 1) /
chanList(i,3) + 1;
+ // Int lenChannels;
+ // channels_p.shape(lenChannels);
+ // channels_p.resize(lenChannels + nChanAdd, True);
+ // if(chanList(i,3) > 0) {
+ // for(Int j=chanList(i,1); j<=chanList(i,2); j+=chanList(i,3)) {
+ // // push j onto end of Array channels_p
+ // channels_p(lenChannels) = j;
+ // lenChannels++;
+ // }
+ // } else { // if chanList(i,3) == 0
+ // // push chanList(i,1) onto end of Array channels_p
+ // channels_p(lenChannels) = chanList(i,2);
+ // }
+ // }
+ // if (chanList.nrow() == 0) {
+ // channels_p.resize(0,False);
+ // }
+ // channels_p.shape(nchan_p);
+
+ // If non-trivial MSSelection invoked and nrow reduced:
+ if(nonTrivial && pMSSel_p->nrow()<pMS_p->nrow()) {
+
+ // Escape if no rows selected
+ if (pMSSel_p->nrow()==0)
+ throw(AipsError("Specified selection contains zero rows (no
data)!"));
+
+ // ...otherwise report how many rows are selected
+ logStream_p << LogIO::NORMAL1 << "Selection reduces " <<
pMS_p->nrow()
+ << " rows to " << pMSSel_p->nrow() << " rows."
+ << LogIO::POST;
+ }
+ else {
+ // Selection did nothing:
+ logStream_p << LogIO::NORMAL2 << "Selection did not drop any rows."
<< LogIO::POST;
+ }
+
+ // Set up for selection on channel or polarisation
+ ROMSSpWindowColumns msSpWinC(pMSSel_p->spectralWindow());
+ /// // If no channels were specified for selection, select all by
default.
+ /// if (nchan_p== 0) {
+ /// nchan_p = msSpWinC.numChan()(0);
+ /// channels_p.resize(nchan_p);
+ /// for(Int i=0; i<nchan_p; i++) { channels_p(i)=i; }
+ /// }
+ /// // output the channels to be listed
+ /// logStream_p << LogIO::NORMAL1 << "Listing channels: " <<
channels_p << LogIO::POST;
+ /// logStream_p << LogIO::NORMAL2 << "Number of selected channels = "
+ /// << nchan_p << LogIO::POST;
+ /// logStream_p << LogIO::DEBUG1 << "nchan_p = " << nchan_p <<
LogIO::POST;
+ logStream_p << LogIO::DEBUG2 << "msSpwinC.numChan() = " << endl
+ << msSpWinC.numChan().getColumn()
+ << LogIO::POST;
+
+ _polarizationSetup(selPolID);
+ logStream_p << LogIO::DEBUG2 << "polarizationSetup done." <<
LogIO::POST;
+ // ROMSPolarizationColumns msPolC(pMSSel_p->polarization());
+ // npols_p = msPolC.corrType()(0).nelements();
+ // pols_p.resize(npols_p,False);
+ // for (uInt i=0; i<npols_p; i++) {
+ // pols_p(i) = Stokes::name(Stokes::type
+ // (msPolC.corrType()(0)(IPosition(1,i))));
+ // }
+ polarizationParse(correlation);
+
+ } // end try block
+ catch (MSSelectionError& x) {
+ // Re-initialize with the existing MS
+ logStream_p << LogOrigin("MSLister","selectvis",WHERE)
+ << LogIO::SEVERE << "Caught exception: " << x.getMesg()
+ << LogIO::POST;
+ //initialize(*pMS_p,False);
+ throw(AipsError("Error in data selection specification."));
+ }
+ catch (AipsError x) {
+ // Re-initialize with the existing MS
+ logStream_p << LogOrigin("MSLister","selectvis",WHERE)
+ << LogIO::SEVERE << "Caught exception: " << x.getMesg()
+ << LogIO::POST;
+ // initialize(*pMS_p,False);
+ throw(AipsError("Error in MSLister::selectvis()"));
+ }
+} // end selectvis
+
+void MSLister::listData(const int pageRows,
+ const String listfile)
+{
+ // Now get the data for the listing.
+ // Currently we are extracting the data through a Record
+ // to a Record to Arrays using MSSelector::getData, which requires
+ // a list of items, a reasonable default set of which is defined
+ // here as a Vector<String> passable to MSSelector::getData
+ // (eventually, user will have some choice here, e.g., to get
+ // real/imag instead of amp/ph, etc.).
+ // Eventually, it would be easier if there were public RO access to the
+ // MSSelector::selms_p member...
+ // **SPW**
+
+ try{
+ char cfill = cout.fill(' '); // fill character for terminal output
+ Bool prompt=True;
+
+ // Default myout as a synonym for cout. (iostream makes it next to
+ // impossible to declare a non-initialized ostream, or set the rdbuf of
+ // an ofstream.)
+ ostream myout(cout.rdbuf());
+
+ ofstream file; // Optional output file.
+ if(listfile != "") { // non-interactive -> redirect output to file.
+ //prompt = False;
+
+ // Guard against trampling existing file
+ File diskfile(listfile);
+ if (diskfile.exists()) {
+ String errmsg = "File: " + listfile +
+ " already exists; delete it or choose a different name.";
+ throw(AipsError(errmsg));
+ }
+ else
+ cerr << "Writing output to file: " << listfile << endl;
+
+ file.open(listfile.data());
+ myout.rdbuf(file.rdbuf()); // DON'T redirect cout to file!
+ } // The user will press Ctrl-C!
+
+ logStream_p << LogIO::DEBUG1 << "Begin: MSLister::listData" <<
LogIO::POST;
+
+ // FLOAT_DATA of single dish has only Amplitude
+ if (is_float) {items_p.resize(10,False);}
+ else {items_p.resize(11,False);}
+ items_p(0)="time";
+ items_p(1)="antenna1";
+ items_p(2)="antenna2";
+ items_p(3)="uvdist";
+ // items_p(4)="spectral_window_id";
+ items_p(4)="data_desc_id";
+ items_p(5)="field_id";
+ items_p(6)=dataColSel(0);
+ if (is_float){
+ items_p(7)="weight";
+ items_p(8)="flag";
+ items_p(9)="uvw";
+ } else {
+ items_p(7)=dataColSel(1);
+ items_p(8)="weight";
+ items_p(9)="flag";
+ items_p(10)="uvw";
+ }
+
+ // Get ranges of selected data to ranges_p for use in
field-width/precision
+ // setting
+ //getRanges(*pMSSel_p);
+
+ //myout << "pMSSel_p.nrows=" << pMSSel_p->nrow() << endl;
+
+/////////////////////////////////////////////////////
+//////read whole ms into mem is not practical, slow and waste memory
+//////so we split it into 5 mimutes chunk
+ Block<int> sort(2);
+ sort[0] = MS::ANTENNA1;
+ sort[1] = MS::ANTENNA2;
+ Double timeInterval = 300; // 5 minutes
+ if(pMSSel_p->isNull()){
+ return;
+ }
+ MSIter msIter(*pMSSel_p, sort, timeInterval);
+ for (msIter.origin(); msIter.more(); msIter++){
+ MS splitMS = msIter.table();
+ if(splitMS.isNull()){
+ break;
+ }
+ if (!splitMS.nrow())
+ break;
+ //myout << "splitMS.nrow()=" << splitMS.nrow() << endl;
+
+ getRanges(splitMS);
+
+ // UNCOMMENT TO: PRINT RECORD OF RANGES (Records can be written to
ostreams, but not to LogIO.)
+ // myout << "ranges_p = " << endl << ranges_p << endl;
+
+ // From here on, all MS access should go through mss_p.
+
+ // TURN ALL THIS DATA GATHERING INTO ITS OWN FUNCTION
+
+ // Initialise the MSSelector object. By default, initSelection()
takes all
+ // polarizations and the first spectral channel.
+ mss_p.setMS(splitMS);
+ //logStream_p << LogIO::DEBUG1 << "mss_p.setMS(*pMSSel_p) finished"
<< LogIO::POST;
+ mss_p.initSelection();
+ //logStream_p << LogIO::DEBUG1 << "mss_p.initSelection() finished"
<< LogIO::POST;
+
+ // Now extract the selected data Record. Note that mss_p is the
*selected*
+ // data, and mss_p.getData() is an implicit Record object
+ //logStream_p << LogIO::DEBUG2 << "Getting data from mss_p" <<
LogIO::POST;
+ dataRecords_p = mss_p.getData(items_p,False);
+ //logStream_p << LogIO::DEBUG2 << "Done getting data from mss_p" <<
LogIO::POST;
+
+ // Construct arrays for the Record items.
+ // The V-float declaration
+ // appears to be necessary (instead of V-double) despite the get()
+ // function's claim to do type promotion.
+ Vector <Double> rowTime,uvdist;
+ Vector <Int> ant1,ant2,spwinid,fieldid;
+ Array <Bool> flag;
+ Array <Float> ampl,phase;
+ Array <Float> weight;
+ Array <Double> uvw;
+
+ //myout << "type=" <<
dataRecords_p.type(dataRecords_p.fieldNumber("uvw")) << endl;
+ // Fill the arrays.
+ rowTime = dataRecords_p.asArrayDouble(RecordFieldId("time"));
+ // ACQUIRE ANTENNA NAME VECTORS
+ // antenna 1
+ if (dataRecords_p.isDefined("antenna1")) {
+ ant1 = dataRecords_p.asArrayInt(RecordFieldId("antenna1"));
+ } else if (dataRecords_p.isDefined("ant1")) {
+ ant1 = dataRecords_p.asArrayInt(RecordFieldId("ant1"));
+ } else {
+ logStream_p << LogIO::SEVERE << "antenna1 isn't defined" <<
LogIO::POST;
+ return;
+ }
+ // antenna 2
+ if (dataRecords_p.isDefined("antenna2")) {
+ ant2 = dataRecords_p.asArrayInt(RecordFieldId("antenna2"));
+ } else if (dataRecords_p.isDefined("ant2")) {
+ ant2 = dataRecords_p.asArrayInt(RecordFieldId("ant2"));
+ } else {
+ logStream_p << LogIO::SEVERE << "antenna2 isn't defined" <<
LogIO::POST;
+ return;
+ }
+
+ // Convert antenna ID Vectors to antenna name Vectors
+ Int ant1Length = ant1.size(); // Get length of ant1
+ Vector<String> antennaNames; // Hold name for each antenna
+ Vector<String> antNames1(ant1Length); // Antenna names for the ID's
held in ant1
+ Vector<String> antNames2(ant1Length); // Antenna names for the ID's
held in ant2
+ ROMSAntennaColumns antCol(pMS_p->antenna());
+ antennaNames = antCol.name().getColumn();
+ for (Int i=0; i<ant1Length; i++) {
+ antNames1(i) = antennaNames(ant1(i));
+ antNames2(i) = antennaNames(ant2(i));
+ }
+ // logStream_p << LogIO::DEBUG2 << "ant1 = " << ant1 << LogIO::POST;
+ // logStream_p << LogIO::DEBUG2 << "ant2 = " << ant2 << LogIO::POST;
+ // logStream_p << LogIO::DEBUG2 << "antNames " << ant1 <<
LogIO::POST;
+ // logStream_p << LogIO::DEBUG2 << "ant1 = " << ant1 << LogIO::POST;
+
+ //logStream_p << LogIO::DEBUG2 << "Ant1-Ant2" << LogIO::POST;
+ //for (Int i=0; i<10 && i<ant1Length; i++) {
+ // logStream_p << LogIO::DEBUG2 << antNames1(i) << "-"
+ // << antNames2(i) << LogIO::POST;
+ //}
+
+ // flag, uvdist, datadescid, fieldid
+ flag = dataRecords_p.asArrayBool(RecordFieldId("flag"));
+ uvdist = dataRecords_p.asArrayDouble(RecordFieldId("uvdist"));
+ Vector<Int> datadescid = dataRecords_p.asArrayInt("data_desc_id");
+ fieldid = dataRecords_p.asArrayInt(RecordFieldId("field_id"));
+ uvw = dataRecords_p.asArrayDouble(RecordFieldId("uvw"));
+ // dataColSel(0) (the data identified by this variable)
+ if (dataRecords_p.isDefined(dataColSel(0))) {
+ ampl = dataRecords_p.asArrayFloat(RecordFieldId(dataColSel(0)));
+ } else {
+ logStream_p << LogIO::SEVERE << "Column " << dataColSel(0)
+ << " (for amplitude) isn't defined." << LogIO::POST;
+ return;
+ }
+ // dataColSel(1) (the data identified by this variable)
+ if (! is_float){
+ if (dataRecords_p.isDefined(dataColSel(1))) {
+ phase = dataRecords_p.asArrayFloat(RecordFieldId(dataColSel(1)));
+ } else {
+ logStream_p << LogIO::SEVERE << "Column " << dataColSel(1)
+ << " (for phase) isn't defined." << LogIO::POST;
+ return;
+ }
+ }
+ // weight
+ weight = dataRecords_p.asArrayFloat(RecordFieldId("weight"));
+
+ // Number of rows that will be listed
+ Int nTableRows = rowTime.nelements();
+
+ spwinid.resize(nTableRows);
+
+ // Convert units of some params:
+ rowTime = rowTime/C::day; // time now in days
+ if (!is_float) {phase = phase/C::degree;} // phase now in degrees
+ // For each row: translate Data Description IDs to Spectral Window
IDs
+ // This must be done before column widths can be calculated, before
+ // data can be written.
+ for (Int tableRow=0;tableRow<nTableRows;tableRow++) {
+ // Translate data_desc_id to spwid:
+ spwinid(tableRow)=spwins_p(datadescid(tableRow));
+ // Change uvdist to wavelengths as function of spwinid:
+ // Note that uv-distance data selection uses meters as the
default unit.
+ uvdist(tableRow) =
uvdist(tableRow)/(C::c/freqs_p(spwinid(tableRow)));
+ }
+
+ /* List available units on the top of the output */
+ myout << "Units of columns are: Date/Time(YYMMDD/HH:MM:SS UT),
UVDist(wavelength), Phase(deg), UVW(m)" << endl;
+ // Add or adjust ranges_p to non-zero absolutes for non-index and/or
+ // converted values (so we can use ranges_p for field width and
+ // precision setting):
+
+ //logStream_p << LogIO::DEBUG2 << "Beginning to fill record
ranges_p" << LogIO::POST;
+ //logStream_p << LogIO::DEBUG2 << " Setting uvdist min and max
values" << LogIO::POST;
+ Vector<Double> uvminmax(2);
+ uvminmax(0)=min(uvdist);
+ uvminmax(1)=max(uvdist);
+ ranges_p.define("uvdist",uvminmax);
+
+ //logStream_p << LogIO::DEBUG2 << " Setting data amplitude min and
max values" << LogIO::POST;
+ Vector<Float> amplminmax(2);
+ amplminmax(0)=min(ampl(ampl>=0.0f));
+ amplminmax(1)=max(ampl);
+ if(amplminmax(0) == amplminmax(1))
+ { myout << "All selected data has AMPLITUDE = " << amplminmax(0) <<
endl; }
+
+ ranges_p.define(dataColSel(0),amplminmax);
+
+ // Find the range of phase. Take care to avoid creating a 0-element
+ // MaskedArray, if all elements of phase are 0.0f. A 0-element
+ // array will crash function min.
+ //logStream_p << LogIO::DEBUG2 << " Setting data phase min and max
values" << LogIO::POST;
+ if (! is_float){
+ Vector<Float> phminmax(2);
+ phminmax(0) = min(abs(phase));
+ phminmax(1) = max(abs(phase));
+ if(phminmax(0) == phminmax(1))
+ { myout << "All selected data has PHASE = " << phminmax(0) << endl; }
+
+ ranges_p.define(dataColSel(1),phminmax);
+ }
+
+ // HERE LIES CODE THAT I THINK IS NO LONGER NEEDED! For some
reason, when the mins and maxs
+ // were originally computed, the author looked only at the data not
equal to 0.0. I don't think
+ // this is necessary. We shall see!..
+ //
+ // MaskedArray<float> maPhase(phase, (phase!=0.0f));
+ // myout << "phase = " << endl << phase << endl;
+ // myout << "maPhase.nelements() = " << maPhase.nelements() <<
endl;
+ // myout << "phase(phase!=0.0f).nelements() = " <<
phase(phase!=0.0f).nelements() << endl;
+ // myout << "abs(phase(phase!=0.0f)).nelements() = " <<
abs(phase(phase!=0.0f)).nelements() << endl;
+ // myout << "min(abs(phase(phase!=0.0f))) = " <<
min(abs(phase(phase!=0.0f))) << endl;
+ // myout << "min(phase(phase!=0.0f)) = " <<
min(phase(phase!=0.0f)) << endl;
+ // if (maPhase.nelementsValid() != 0) {
+ // logStream_p << LogIO::DEBUG2 << "maPhase contains at least 1
element" << LogIO::POST;
+ // // logStream_p << LogIO::DEBUG2 << "phase = " << phase <<
LogIO::POST;
+ // // CANNOT BE DONE myout << "phase(phase !=0.0f) = " <<
phase(phase!=0.0f);
+ // // CANNOT BE DONE myout << "maPhase = " << maPhase << endl;
+ // phminmax(0)=min(abs(phase(phase!=0.0f)));
+ // myout << "phminmax(0) = " << phminmax(0) << endl;
+ // phminmax(1)=max(phase);
+ // myout << "phminmax(1) = " << phminmax(1) << endl;
+ // } else {
+ // phminmax(0) = 0.0f;
+ // phminmax(1) = 0.0f;
+ // logStream_p << LogIO::NORMAL1 << "All selected data has
phase = 0.0" << LogIO::POST;
+ // myout << "All selected data has phase = 0.0" << endl;
+ // }
+// if (!is_float) {ranges_p.define(dataColSel(1),phminmax);}
+
+ //logStream_p << LogIO::DEBUG2 << "Setting the weight min and max."
<< LogIO::POST;
+ Vector<Float> wtminmax(2);
+ wtminmax(0)=min(abs(weight));
+ wtminmax(1)=max(abs(weight));
+ if(wtminmax(0) == wtminmax(1))
+ myout << "WEIGHT: " << wtminmax[0] << endl;
+ ranges_p.define("weight",wtminmax);
+
+ //logStream_p << LogIO::DEBUG2 << "Setting the uvw min and max." <<
LogIO::POST;
+ Vector<Float> uvwminmax(2);
+ uvwminmax(0)=min(abs(uvw));
+ uvwminmax(1)=max(abs(uvw));
+ //if(uvwminmax(0) == uvwminmax(1))
+ // { myout << "All selected data has UVW = " << uvwminmax(0) <<
endl; }
+ ranges_p.define("uvw",uvwminmax);
+
+ // Records currently only support output to stdio, not to LogIO!
+ //myout << "Printing out the Record ranges_p:" << endl
+ // << ranges_p << endl;
+ //logStream_p << LogIO::DEBUG2 << "Setting flags for output:" <<
LogIO::POST;
+
+ // TURN THIS FLAG SETTING INTO A NEW FUNCTION
+ // Make flags for showing index columns.
+ // Test to see if more than one value is present
+ // in the data column.
+ // If the array consists of only 1 value, ranges_p will have only 1
+ // element, and the boolean value will be set to false!
+ if (ranges_p.asArrayInt(RecordFieldId("field_id")).nelements() > 1) {
+ doFld_p = True;
+ } else {
+ doFld_p = False;
+ //logStream_p << LogIO::NORMAL << "All selected data has FIELD = "
+ // << fieldid(0) << LogIO::POST;
+ myout << "FIELD: " << fieldid[0] << endl;
+ }
+ // doSpW_p =
(ranges_p.asArrayInt(RecordFieldId("data_desc_id")).nelements() > 1);
+ if (ranges_p.asArrayInt(RecordFieldId("data_desc_id")).nelements() >
1) {
+ doSpW_p = True;
+ } else {
+ doSpW_p = False;
+ //logStream_p << LogIO::NORMAL << "All selected data has SPW = "
+ // << datadescid(0) << LogIO::POST;
+ myout << "SPW: " << datadescid[0] << endl;
+ }
+ if (multiChan_p) {
+ doChn_p = True; // Output a CHANNEL column
+ } else {
+ doChn_p = False;
+ //logStream_p << LogIO::NORMAL << "All selected data has CHANNEL
= "
+ // << chanList_p(0,1) << LogIO::POST;
+ myout << "CHANNEL: " << chanList_p(0, 1) << endl;
+ }
+
+ // logStream_p << LogIO::DEBUG2 << "Fld id : " <<
ranges_p.get("field_id") << endl
+ // << "SpW id : " << ranges_p.get("spectral_window_id") <<
LogIO::POST;
+
+ // From this point on, don't change scaling in list arrays, since the
+ // field sizes are determined directly from the data.
+// logStream_p << LogIO::DEBUG1
+// << "(Min, max) uvdist: " << uvminmax[0] << ", " <<
uvminmax[1] << endl
+// << "(Min, max) uvw: " << uvwminmax[0] << ", " <<
uvwminmax[1] << endl
+// << "(Min, max) amp: " << amplminmax[0] << ", " <<
amplminmax[1] << endl
+// << "(Min, max) phase: " << phminmax[0] << ", " <<
phminmax[1] << endl
+// << "(Min, max) weight: " << wtminmax[0] << ", " <<
wtminmax[1]
+// << LogIO::POST;
+
+ // Set order of magnitude and precision (for field width setting):
+ // If prec*_p < 0, then enforce >=0 (detect minimum decimal places
to show is NYI)
+ // If prec*_p > 0, then increment o*_p to provide space for decimal
+
+ oTime_p = 2; // this is space for 2 :'s in time
+ if ( precTime_p < 0 ) precTime_p = 7; // hh:mm:ss.s
+ if ( precTime_p > 0 ) oTime_p++; // add space for decimal
+
+ oUVDist_p = (uInt)max(1,(Int)rint(log10(max(uvdist))+0.5)); // order
+ if ( precUVDist_p < 0 ) precUVDist_p = 0;
+ if ( precUVDist_p > 0 ) oUVDist_p++; // add space for decimal
+
+ oUVW_p = (uInt)max(1,(Int)rint(log10(max(uvw))+0.5)); // order
+ if ( precUVW_p < 0 ) precUVW_p = 2;
+ if ( precUVW_p > 0 ) oUVW_p++; // add space for decimal
+ oUVW_p++; // add space for sign
+
+ oAmpl_p = (uInt)max(1,(Int)rint(log10(max(ampl))+0.5));
+ if ( precAmpl_p < 0 ) precAmpl_p = 3; // mJy
+ if ( precAmpl_p > 0 ) oAmpl_p++; // add space for decimal
+
+ if (!is_float){
+ oPhase_p = (uInt)max(1,(Int)rint(abs(log10(max(phase)+0.5))));
+ if(min(phase) < 0) { oPhase_p+=3; } // add space for sign and column
border
+ else { oPhase_p++; } // add space for column border
+ //oPhase_p = 3; // 100s of degs
+ if ( precPhase_p < 0 ) precPhase_p = 1;
+ if ( precPhase_p > 0 ) oPhase_p+=2; // add space for decimal
+ }
+
+ oWeight_p = (uInt)max(1,(Int)rint(log10(max(weight))+0.5)); // order
+ if ( precWeight_p < 0 ) precWeight_p = 0;
+ if ( precWeight_p > 0 ) oWeight_p++; // add space for decimal
+
+ // Set field widths.
+
+ // Use function to set width of baseline column: Ant1-Ant2
+ wAnt1_p = columnWidth(antNames1);
+ wAnt2_p = columnWidth(antNames2);
+
+ wFlag_p = 2; // the flag is always 1 character
+ if (doFld_p) wFld_p = (uInt)rint(log10((float)max(fieldid))+0.5);
+ if (doSpW_p) wSpW_p = (uInt)rint(log10((float)max(spwinid))+0.5);
+ if (doChn_p) wChn_p = 3;
+
+
+ // The field width for non-index columns is given by the
+ // sum of the order and precision:
+ wTime_p = oTime_p + precTime_p;
+ wUVDist_p = oUVDist_p + precUVDist_p;
+ wUVW_p = oUVW_p + precUVW_p;
+ wAmpl_p = oAmpl_p + precAmpl_p;
+ if (!is_float) {wPhase_p = oPhase_p + precPhase_p;}
+ wWeight_p = oWeight_p + precWeight_p;
+
+ // Enforce minimum field widths,
+ // add leading space so columns nicely separate,
+ // and accumulate wTotal_p:
+ wTotal_p = 0; // initialize
+ // wAnt_p = max(wAnt_p, (uInt)2);
+ wAnt1_p++; // add leading space to separate from previous column
+ wIntrf_p = wAnt1_p+1+wAnt2_p;
wTotal_p+=wIntrf_p;
+ if (doFld_p) { wFld_p = max(wFld_p,(uInt)3); wFld_p++;
wTotal_p+=wFld_p; }
+ if (doSpW_p) { wSpW_p = max(wSpW_p,(uInt)3); wSpW_p++;
wTotal_p+=wSpW_p;}
+ if (doChn_p) { wChn_p = max(wChn_p,(uInt)4); wChn_p++;
wTotal_p+=wChn_p;}
+
+ wTime_p = max(wTime_p, (uInt)12);
+ wUVDist_p = max(wUVDist_p,(uInt)6); wUVDist_p++;
wTotal_p+=wUVDist_p;
+ wAmpl_p = max(wAmpl_p, (uInt)4); wAmpl_p++;
+ if (!is_float) {wPhase_p = max(wPhase_p, (uInt)4); }
+ wWeight_p = max(wWeight_p,(uInt)3); wWeight_p++;
+
+ if (!is_float) {wVis_p = wAmpl_p+wPhase_p+wWeight_p+wFlag_p;}
+ else {wVis_p = wAmpl_p+wWeight_p+wFlag_p;}
+ wTotal_p+=wTime_p+nIndexPols_p*wVis_p+1;
+ wUVW_p = max(wUVW_p, (uInt)9); wUVW_p++;
wTotal_p+=3*wUVW_p;
+
+ // Make column-ated header rule according to total and field widths
+
+ // replicate does not work if the first parameter is "-", but it
does for '-'.
+ // Bug report here:
https://bugs.aoc.nrao.edu/browse/CAS-511
+ String hSeparator=replicate('-',wTotal_p+1);
+ //myout << "wTotal_p=" << wTotal_p << endl;
+ //myout << "hSeparator.length=" << hSeparator.size() << endl;
+ uInt colPos=0;
+ colPos+=wTime_p; hSeparator[colPos]='|';
+ colPos+=wIntrf_p; hSeparator[colPos]='|';
+ colPos+=wUVDist_p; hSeparator[colPos]='|';
+ if (doFld_p) {colPos+=wFld_p;hSeparator[colPos]='|';}
+ if (doSpW_p) {colPos+=wSpW_p;hSeparator[colPos]='|';}
+ if (doChn_p) {colPos+=wChn_p;hSeparator[colPos]='|';}
+ colPos++;
+ for (uInt ipol=0; ipol<nIndexPols_p; ipol++) {
+ colPos+=wVis_p;
+ hSeparator[colPos]='|';
+ }
+ colPos+=wUVW_p; hSeparator[colPos]='|';
+ colPos+=wUVW_p; hSeparator[colPos]='|';
+ colPos+=wUVW_p; hSeparator[colPos]='|';
+ //myout << "wTotal_p=" << wTotal_p << " colPos=" << colPos << endl;
+ //myout << "hSeparator.length=" << hSeparator.size() << endl;
+ //hSeparator.resize(colPos, True);
+
+
+ Vector<String> flagSym(2);
+ flagSym(0) = " ";
+ flagSym(1) = "F";
+
+ // Finally print the records out, one per line.
+
+ // Output something about the number of channels being listed.
+ // But what exactly to say, since number of channels can vary between
+ // spws?
+ //logStream_p << LogIO::NORMAL << "Listing " << rowTime.nelements()
+ // << " data records satisfying selection criteria, " <<
endl
+ // << "for each of " << npols_p << " polarisation(s) and "
<< (chanList_p(0,2)+1)
***The diff for this file has been truncated for email.***
=======================================
--- /dev/null
+++ /branches/nov14/ms/MSOper/MSLister.h Wed Mar 25 14:33:54 2015 UTC
@@ -0,0 +1,320 @@
+//# MSLister.h: Helper class for applications listing records from an MS
+//# Copyright (C) 1998,1999,2000
+//# Associated Universities, Inc. Washington DC, USA.
+//#
+//# This library is free software; you can redistribute it and/or modify it
+//# under the terms of the GNU Library General Public License as published
by
+//# the Free Software Foundation; either version 2 of the License, or (at
your
+//# option) any later version.
+//#
+//# This library is distributed in the hope that it will be useful, but
WITHOUT
+//# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+//# FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
+//# License for more details.
+//#
+//# You should have received a copy of the GNU Library General Public
License
+//# along with this library; if not, write to the Free Software Foundation,
+//# Inc., 675 Massachusetts Ave, Cambridge, MA 02139, USA.
+//#
+//# Correspondence concerning AIPS++ should be addressed as follows:
+//# Internet email:
aips2-...@nrao.edu.
+//# Postal address: AIPS++ Project Office
+//# National Radio Astronomy Observatory
+//# 520 Edgemont Road
+//# Charlottesville, VA 22903-2475 USA
+//#
+//# $Id$
+//#
+#ifndef MS_MSLISTER_H
+#define MS_MSLISTER_H
+
+
+#include <casacore/casa/aips.h>
+#include <casacore/casa/Logging/LogIO.h>
+//#include <casacore/casa/Logging/LogSink.h>
+#include <casacore/casa/BasicSL/String.h>
+#include <casacore/casa/Arrays/Vector.h>
+#include <casacore/casa/Containers/Record.h>
+#include <casacore/ms/MSSel/MSSelector.h>
+namespace casacore { //# NAMESPACE CASACORE - BEGIN
+
+class MeasurementSet;
+
+// <summary> List visibility records from a Measurement Set </summary>
+// <use visibility=export>
+//
+// <reviewed reviewer="" date="yyyy/mm/dd" tests="" demos="">
+// </reviewed>
+//
+// <prerequisite>
+// <li> <linkto class=MSSelector>MSSelector</linkto>
+// <li> <linkto class=MSSummary>MSSummary</linkto>
+// </prerequisite>
+//
+// <etymology>
+// The name comes from being a Lister for a MS.
+// </etymology>
+//
+// <synopsis>
+// MSs containing (u,v) data consist of amplitudes and phases for each
+// baseline and sample time, typically sorted in TB order. These
+// visibilities sometimes need to be examined one record at a time in
+// a text-based format, giving the user access to their raw data.
+// This class provides that access in a choice of several formats.
+// </synopsis>
+//
+// <example>
+// <srcBlock>
+// // Define an MS
+// MeasurementSet myMS(fileName);
+// // Define an output stream
+// LogIO myLog;
+// // Construct the Lister object
+// MSLister myList(myMS,myLog);
+// // List all data
+// myList.list();
+//
+// // Send the next output to a new location
+// LogIO newLog;
+// setNewOS(newLog);
+// // List all the data, with default output options
+// myList.list();
+// // List only selected data, with specified output options
+// datacolumn = 'corrected'; spw = '3:5~10'; timerange = '<13:34:25.1';
+// scan = '5'; pagerows = 10; listfile = 'myList.list.out';
+// // ... define any other parameters, then call function ...
+// myList.list(options, datacolumn, field, spw, antenna, timerange,
+// correlation, scan, feed, array, uvrange, average,
+// showflags, msselect, pagerows, listfile);
+// </srcBlock>
+// An <src>MSLister</src> object is constructed from a <src>MS</src>
+// object, and then logged to the supplied <src>LogIO</src> object.
+// A new <src>LogIO</src> object is defined for a more restricted
+// listing.
+// </example>
+//
+// <note role=caution>
+// Note that if the <src>MS</src> goes out of scope, this class will
+// retrieve rubbish (probably giving runtime errors) as it just
+// maintains a pointer to the image.
+// </note>
+//
+// <motivation>
+// The viewing of the raw data is a basic capability that is
+// commonly required.
+// </motivation>
+//
+// <todo asof="2008/02/08">
+// <li> Several of the input parameters to <src>MSLister::list</src> are
not
+// funcational presently.
+// <li> The (pointer to the) MS is declared and used as non-const
throughout
+// MSLister, because MSSelector requires it. MSSelector should be
+// changed to require a const MS since it claims not to change the MS
+// anyway. Then the pointer/MS should be made const here too.
+// <li> Add more sanity checks.
+// <li> Actually do something with the nDecimal_p number.
+// <li> There are more formatting options planned.
+// </todo>
+
+
+class MSLister
+{
+public:
+ // Null constructor
+ MSLister();
+
+ // Construct from a MeasurementSet (set pointer), set formatting string,
+ // and initialise listing with os.
+ // <todo> os is currently not used as the primary steam for log messages.
+ // This should be corrected, or os removed completely from the class.
+ // </todo>
+ MSLister (const MeasurementSet& ms, LogIO& os);
+
+ // Copy constructor, this will initialise the MSLister's MS with other's
MS
+ MSLister (MSLister& other);
+
+ // Assignment, this will initialise the MSLister's MS with other's MS
+ MSLister& operator=(MSLister& other);
+
+ // Destructor
+ ~MSLister();
+
+ // Change or set the OS this MSLister uses. Do this before setMS()
+ // if doing both. This method avoids having to reconstruct the MSLister
+ // object if you change your mind about the output destination.
+ // <todo> os is currently not used as the primary steam for log messages.
+ // This should be corrected, or os removed completely from the class.
+ // </todo>
+ Bool setNewOS (LogIO& os);
+
+ // Change or set the MS this MSLister refers to, and reinitialise the
+ // MSLister object. Do this after setNewOS() if doing both.
+ Bool setMS (MeasurementSet& ms);
+
+ // Page size for various formats, output devices (default for landscape
+ // printing).
+ void setPage (const uInt width=120, const uInt height=20);
+
+ // Format for output, ie data display precision.
+ void setFormat (const uInt ndec=2);
+
+ // User choices for list precision (sensible defaults):
+ // (time precision for user interface is fraction of sec)
+ void setPrecision ( const Int precTime=1, const Int precUVDist=0,
+ const Int precAmpl=3, const int precPhase=1,
+ const Int precWeight=0 );
+
+ // List the visibilities, with optional data selection and output
+ // specification.
+ void list (const String& options="",
+ const String& datacolumn="",
+ const String& field="",
+ const String& spw="",
+ const String& antenna="",
+ const String& timerange="",
+ const String& correlation="",
+ const String& scan="",
+ const String& feed="",
+ const String& array="",
+ const String& observation="",
+ const String& uvrange="",
+ const String& average="",
+ const bool showflags=False,
+ const String& msSelect="",
+ const long pagerows=50,
+ const String& listfile="");
+
+ // Set uv-data selection via MSSelection
+ void selectvis(const String& timerange="",
+ const String& spw="",
+ const String& scan="",
+ const String& field="",
+ const String& baseline="",
+ const String& uvrange="",
+ const String& chanmode="none",
+ const Int& nchan=1,
+ const Int& start=0,
+ const Int& step=1,
+ const MRadialVelocity& mStart=MRadialVelocity(),
+ const MRadialVelocity& mStep=MRadialVelocity(),
+ const String& correlation="",
+ const String& array="",
+ const String& observation="",
+ const String& msSelect="");
+
+private:
+
+ // Initialise the listing. initList() does things that need to be done
+ // once per MS: declares and initialises the private MSSelector object,
+ // and gets all the attribute ranges up front.
+ void initList();
+
+ // A preamble of abbreviated MSSummary information.
+ void listHeader();
+
+ // Get the ranges of a fixed set of MS key attributes.
+ void getRanges(const MeasurementSet &ms);
+
+ // Most of the heavy lifting is in here. Get the data records and list
+ // them.
+ void listData(const int pageRows=50, const String listfile="");
+
+ // Column header line for pagination of output.
+ void listColumnHeader(ostream& myout);
+
+ // Setup class polarization information for specified MS.
+ // pols_p holds the polarization names contained in the MS
+ // in the same order that the polarization data are listed in the
+ // main table.
+ void _polarizationSetup(const uInt selPolID);
+
+ // Parse the correlation parameter value; fill indexPols_p to output
+ // selected polarizations. If correlation is empty, all polarizations
+ // are selected.
+ void polarizationParse(String correlation);
+
+ // Calculate column width for a Vector<String>
+ Int columnWidth(const Vector<String> antNames);
+
+ // Pointer to the MS
+ MeasurementSet* pMS_p;
+ MeasurementSet* pMSSel_p;
+
+ // Output stream
+ LogIO logStream_p;
+
+ // A formatting string for convenience
+ const String dashline_p;
+
+ // The MSSelector object used in list() etc.
+ MSSelector mss_p;
+
+ // List of channels
+ Matrix<Int> chanList_p;
+ // True if listing multiple channels.
+ Bool multiChan_p;
+
+ // Pol counters
+ uInt npols_p;
+
+ // SpW/Pol info from subtables
+ Vector<String> pols_p;
+ Vector<Double> freqs_p;
+
+ // SpWId map from DDIs:
+ Vector<Int> spwins_p;
+ // True if listing multiple spws
+ Bool multiSpw_p;
+
+ // Polarization indexing variables; for polarization (correlation)
selection.
+ Vector<Int> indexPols_p;
+ uInt nIndexPols_p;
+
+ // Field width variables
+ uInt wTime_p, wAnt1_p, wAnt2_p, wIntrf_p, wUVDist_p, wUVW_p;
+ uInt wFld_p, wSpW_p, wChn_p;
+ uInt wAmpl_p, wPhase_p, wWeight_p, wVis_p, wFlag_p;
+ uInt wTotal_p;
+
+ // Order of magnitude control (digits to left of decimal, including sign)
+ uInt oTime_p, oUVDist_p, oUVW_p;
+ uInt oAmpl_p, oPhase_p;
+ uInt oWeight_p;
+
+ // Precision control (digits to right of decimal point)
+ // (precTime_p includes hhmmss, so 7 yields hh:mm:ss.s)
+ Int precTime_p, precUVDist_p, precUVW_p;
+ Int precAmpl_p, precPhase_p;
+ Int precWeight_p;
+
+ // Page params
+ Int pageWidth_p, pageHeight_p, nDecimal_p;
+ String date_p, lastdate_p;
+
+ // for assigning desired columns from the ms
+ Vector <String> items_p;
+
+ // Bools for column showing and to identify FLOAT_DATA column of single
dish
+ Bool doFld_p, doSpW_p, doChn_p, is_float;
+
+ // Data selections
+ // data --> "amplitude", "phase"
+ // corrected --> "corrected_amplitude", "corrected_phase"
+ // model --> "model_amplitude", "model_phase"
+ // residual --> "residual_amplitude", "residual_phase"
+ Vector <String> dataColSel;
+
+ // The Record object containing the MSSelector ranges
+ Record ranges_p;
+
+ // The conversion of the above to a regular Record object
+ Record dataRecords_p;
+
+ // Clear the formatting flags
+ void clearFlags();
+};
+
+
+} //# NAMESPACE CASACORE - END
+
+#endif
=======================================
--- /dev/null
+++ /branches/nov14/ms/MSOper/MSMetaData.cc Wed Mar 25 14:33:54 2015 UTC
@@ -0,0 +1,3792 @@
+//# MSMetaData.cc
+//# Copyright (C) 1998,1999,2000,2001
+//# Associated Universities, Inc. Washington DC, USA.
+//#
+//# This library is free software; you can redistribute it and/or modify it
+//# under the terms of the GNU Library General Public License as published
by
+//# the Free Software Foundation; either version 2 of the License, or (at
your
+//# option) any later version.
+//#
+//# This library is distributed in the hope that it will be useful, but
WITHOUT
+//# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+//# FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
+//# License for more details.
+//#
+//# You should have received a copy of the GNU Library General Public
License
+//# along with this library; if not, write to the Free Software Foundation,
+//# Inc., 675 Massachusetts Ave, Cambridge, MA 02139, USA.
+//#
+//# Correspondence concerning AIPS++ should be addressed as follows:
+//# Internet email:
aips2-...@nrao.edu.
+//# Postal address: AIPS++ Project Office
+//# National Radio Astronomy Observatory
+//# 520 Edgemont Road
+//# Charlottesville, VA 22903-2475 USA
+//#
+//# $Id$
+
+#include <casacore/ms/MSOper/MSMetaData.h>
+
+#include <casacore/casa/Arrays/MaskArrMath.h>
+#include <casacore/casa/OS/File.h>
+#include <casacore/measures/Measures/MeasTable.h>
+#include <casacore/ms/MSOper/MSKeys.h>
+#include <casacore/ms/MeasurementSets/MSSpWindowColumns.h>
+#include <casacore/tables/Tables/ArrayColumn.h>
+#include <casacore/tables/Tables/ScalarColumn.h>
+#include <casacore/tables/TaQL/TableParse.h>
+#include <casacore/tables/Tables/TableProxy.h>
+
+#define _ORIGIN "MSMetaData::" + String(__FUNCTION__) + ": "
+
+namespace casacore {
+
+MSMetaData::MSMetaData(const MeasurementSet *const &ms, const Float
maxCacheSizeMB)
+ : _ms(ms), _cacheMB(0), _maxCacheMB(maxCacheSizeMB), _nStates(0),
+ _nACRows(0), _nXCRows(0), _nSpw(0), _nFields(0),
+ _nAntennas(0), _nObservations(0), _nScans(0), _nArrays(0),
+ _nrows(0), _nPol(0), _nDataDescIDs(0),
+ _scanToSpwsMap(),
+ _scanToDDIDsMap(),
+ _dataDescIDToSpwMap(),
+ _dataDescIDToPolIDMap(),
+ _fieldToSpwMap(),
+ _scanToStatesMap(), _scanToFieldsMap(),
+ _fieldToStatesMap(), _stateToFieldsMap(),
+ _sourceToFieldsMap(),
+ _antennaNameToIDMap(),
+ _intentToFieldIDMap(),
+ _intentToScansMap(),
+ _scanToTimeRangeMap(),
+ _scanSpwToIntervalMap(),
+ _uniqueIntents(),
+ _uniqueFieldIDs(), _uniqueStateIDs(),
+ _avgSpw(), _tdmSpw(),
+ _fdmSpw(), _wvrSpw(), _sqldSpw(), _antenna1(), _antenna2(),
+ _scans(), _fieldIDs(), _stateIDs(), _dataDescIDs(),
+ _observationIDs(),
+ _subScanToNACRowsMap(), _subScanToNXCRowsMap(),
+ _fieldToNACRowsMap(), _fieldToNXCRowsMap(),
+ _scanToIntentsMap(), _stateToIntentsMap(),
+ _spwToIntentsMap(),
+ _spwInfo(0),
+ _spwToFieldIDsMap(), _obsToArraysMap(), _spwToScansMap(),
+ _fieldToScansMap(),
+ _fieldNames(0),
+ _antennaNames(0), _observatoryNames(0),
+ _times(),
+ _scanToTimesMap(),
+ _fieldToTimesMap(), _observatoryPositions(0),
+ _antennaOffsets(0), _uniqueBaselines(0, 0),
+ _exposureTime(0), _nUnflaggedACRows(0),
+ _nUnflaggedXCRows(0), _unflaggedFieldNACRows(),
+ _unflaggedFieldNXCRows(), _unflaggedSubScanNACRows(),
+ _unflaggedSubScanNXCRows(),
+ _taqlTableName(
+ File(ms->tableName()).exists() ? ms->tableName() : "$1"
+ ),
+ _taqlTempTable(
+ File(ms->tableName()).exists() ? 0 : 1, ms
+ ), _flagsColumn(),
+ _spwInfoStored(False) {}
+
+MSMetaData::~MSMetaData() {}
+
+uInt MSMetaData::nStates() const {
+ if (_nStates == 0) {
+ _nStates = _ms->state().nrow();
+ }
+ return _nStates;
+}
+
+std::set<String> MSMetaData::getIntents() const {
+ if (! _uniqueIntents.empty()) {
+ return _uniqueIntents;
+ }
+ vector<std::set<String> > statesToIntentsMap;
+ std::set<String> uniqueIntents;
+ _getStateToIntentsMap(
+ statesToIntentsMap,
+ uniqueIntents
+ );
+ return uniqueIntents;
+}
+
+void MSMetaData::_getStateToIntentsMap(
+ vector<std::set<String> >& stateToIntentsMap,
+ std::set<String>& uniqueIntents
+) const {
+ if (
+ ! _uniqueIntents.empty() && ! _stateToIntentsMap.empty()
+ ) {
+ uniqueIntents = _uniqueIntents;
+ stateToIntentsMap = _stateToIntentsMap;
+ return;
+ }
+ uniqueIntents.clear();
+ String intentsColName = MSState::columnName(MSStateEnums::OBS_MODE);
+ ROScalarColumn<String> intentsCol(_ms->state(), intentsColName);
+ Vector<String> intentSets = intentsCol.getColumn();
+ stateToIntentsMap.resize(nStates());
+
+ Vector<String>::const_iterator end = intentSets.end();
+ vector<std::set<String> >::iterator sIter = stateToIntentsMap.begin();
+ for(
+ Vector<String>::const_iterator curIntentSet=intentSets.begin();
+ curIntentSet!=end; ++curIntentSet, ++sIter
+ ) {
+ Vector<String> intents = stringToVector(*curIntentSet, ',');
+ *sIter = std::set <String>(intents.begin(), intents.end());
+ uniqueIntents.insert(intents.begin(), intents.end());
+ }
+
+ std::set<String>::const_iterator lastIntent = uniqueIntents.end();
+ uInt mysize = 0;
+
+ vector<std::set<String> >::const_iterator lastState =
stateToIntentsMap.end();
+ uInt count = 0;
+ for (
+ vector<std::set<String> >::const_iterator iter=stateToIntentsMap.begin();
+ iter!=lastState; ++iter, ++count
+ ) {
+ std::set<String>::const_iterator lastIntent=iter->end();
+ for (
+ std::set<String>::const_iterator intent=iter->begin();
+ intent!=lastIntent; ++intent
+ ) {
+ mysize += intent->size();
+ }
+ }
+ for (
+ std::set<String>::const_iterator intent=uniqueIntents.begin();
+ intent!=lastIntent; ++intent
+ ) {
+ mysize += intent->size();
+ }
+ if (_cacheUpdated(mysize)) {
+ _uniqueIntents = uniqueIntents;
+ _stateToIntentsMap = stateToIntentsMap;
+ }
+}
+
+std::set<Int> MSMetaData::getScanNumbers(Int obsID, Int arrayID) const {
+ ArrayKey arrayKey;
+ arrayKey.obsID = obsID;
+ arrayKey.arrayID = arrayID;
+ return _getScanNumbers(arrayKey);
+}
+
+uInt MSMetaData::nScans() {
+ if (_nScans == 0) {
+ _nScans = _getScanKeys().size();
+ }
+ return _nScans;
+}
+
+uInt MSMetaData::nObservations() const {
+ if (_nObservations == 0) {
+ _nObservations = _ms->observation().nrow();
+ }
+ return _nObservations;
+}
+
+uInt MSMetaData::nArrays() {
+ if (_nArrays == 0) {
+ // because the ARRAY table apparently is optional
+ _nArrays = max(*_getArrayIDs()) + 1;
+ }
+ return _nArrays;
+}
+
+uInt MSMetaData::nRows() const {
+ return _ms->nrow();
+}
+uInt MSMetaData::nRows(CorrelationType cType) {
+ if (cType == BOTH) {
+ return nRows();
+ }
+ uInt nACRows, nXCRows;
+ CountedPtr<std::map<SubScanKey, uInt> > subScanToNACRowsMap,
subScanToNXCRowsMap;
+ CountedPtr<vector<uInt> > fieldToNACRowsMap, fieldToNXCRowsMap;
+ _getRowStats(
+ nACRows, nXCRows, subScanToNACRowsMap,
+ subScanToNXCRowsMap, fieldToNACRowsMap,
+ fieldToNXCRowsMap
+ );
+ if (cType == AUTO) {
+ return nACRows;
+ }
+ else {
+ return nXCRows;
+ }
+}
+
+uInt MSMetaData::nRows(
+ CorrelationType cType, Int arrayID, Int observationID,
+ Int scanNumber, Int fieldID
+) const {
+ SubScanKey subScanKey;
+ subScanKey.obsID = observationID;
+ subScanKey.arrayID = arrayID;
+ subScanKey.scan = scanNumber;
+ subScanKey.fieldID = fieldID;
+ _checkSubScan(subScanKey);
+ uInt nACRows, nXCRows;
+ CountedPtr<std::map<SubScanKey, uInt> > subScanToNACRowsMap,
subScanToNXCRowsMap;
+ CountedPtr<vector<uInt> > fieldToNACRowsMap, fieldToNXCRowsMap;
+ _getRowStats(
+ nACRows, nXCRows, subScanToNACRowsMap,
+ subScanToNXCRowsMap, fieldToNACRowsMap,
+ fieldToNXCRowsMap
+ );
+ if (cType == AUTO) {
+ return (*subScanToNACRowsMap)[subScanKey];
+ }
+ else if (cType == CROSS) {
+ return (*subScanToNXCRowsMap)[subScanKey];
+ }
+ else {
+ return (*subScanToNACRowsMap)[subScanKey]
+ + (*subScanToNXCRowsMap)[subScanKey];
+ }
+}
+
+uInt MSMetaData::nRows(CorrelationType cType, uInt fieldID) const {
+ _checkField(fieldID);
+ uInt nACRows, nXCRows;
+ CountedPtr<std::map<SubScanKey, uInt> > subScanToNACRowsMap,
subScanToNXCRowsMap;
+ CountedPtr<vector<uInt> > fieldToNACRowsMap, fieldToNXCRowsMap;
+ _getRowStats(
+ nACRows, nXCRows, subScanToNACRowsMap,
+ subScanToNXCRowsMap, fieldToNACRowsMap,
+ fieldToNXCRowsMap
+ );
+ if (cType == AUTO) {
+ return (*fieldToNACRowsMap)[fieldID];
+ }
+ else if (cType == CROSS) {
+ return (*fieldToNXCRowsMap)[fieldID];
+ }
+ else {
+ return (*fieldToNACRowsMap)[fieldID] + (*fieldToNXCRowsMap)[fieldID];
+ }
+}
+
+Double MSMetaData::nUnflaggedRows() const {
+ Double nACRows, nXCRows;
+ CountedPtr<std::map<SubScanKey, Double> > subScanToNACRowsMap,
subScanToNXCRowsMap;
+ CountedPtr<vector<Double> > fieldToNACRowsMap, fieldToNXCRowsMap;
+ _getUnflaggedRowStats(
+ nACRows, nXCRows, subScanToNACRowsMap,
+ subScanToNXCRowsMap, fieldToNACRowsMap,
+ fieldToNXCRowsMap
+ );
+ return nACRows + nXCRows;
+}
+Double MSMetaData::nUnflaggedRows(CorrelationType cType) const {
+ if (cType == BOTH) {
+ return nUnflaggedRows();
+ }
+ Double nACRows, nXCRows;
+ CountedPtr<std::map<SubScanKey, Double> > subScanToNACRowsMap,
subScanToNXCRowsMap;
+ CountedPtr<vector<Double> > fieldToNACRowsMap, fieldToNXCRowsMap;
+ _getUnflaggedRowStats(
+ nACRows, nXCRows, subScanToNACRowsMap,
+ subScanToNXCRowsMap, fieldToNACRowsMap,
+ fieldToNXCRowsMap
+ );
+ if (cType == AUTO) {
+ return nACRows;
+ }
+ else {
+ return nXCRows;
+ }
+}
+
+Double MSMetaData::nUnflaggedRows(
+ CorrelationType cType, Int arrayID, uInt observationID,
+ Int scanNumber, uInt fieldID
+) const {
+ SubScanKey subScanKey;
+ subScanKey.obsID = observationID;
+ subScanKey.arrayID = arrayID;
+ subScanKey.scan = scanNumber;
+ subScanKey.fieldID = fieldID;
+ _checkSubScan(subScanKey);
+ Double nACRows, nXCRows;
+ CountedPtr<std::map<SubScanKey, Double> > subScanToNACRowsMap,
subScanToNXCRowsMap;
+ CountedPtr<vector<Double> > fieldToNACRowsMap, fieldToNXCRowsMap;
+ _getUnflaggedRowStats(
+ nACRows, nXCRows, subScanToNACRowsMap,
+ subScanToNXCRowsMap, fieldToNACRowsMap,
+ fieldToNXCRowsMap
+ );
+ if (cType == AUTO) {
+ return (*subScanToNACRowsMap)[subScanKey];
+ }
+ else if (cType == CROSS) {
+ return (*subScanToNXCRowsMap)[subScanKey];
+ }
+ else {
+ return (*subScanToNACRowsMap)[subScanKey]
+ + (*subScanToNXCRowsMap)[subScanKey];
+ }
+}
+
+Double MSMetaData::nUnflaggedRows(CorrelationType cType, Int fieldID)
const {
+ Double nACRows, nXCRows;
+ CountedPtr<std::map<SubScanKey, Double> > subScanToNACRowsMap,
subScanToNXCRowsMap;
+ CountedPtr<vector<Double> > fieldToNACRowsMap, fieldToNXCRowsMap;
+ _getUnflaggedRowStats(
+ nACRows, nXCRows, subScanToNACRowsMap,
+ subScanToNXCRowsMap, fieldToNACRowsMap,
+ fieldToNXCRowsMap
+ );
+ if (cType == AUTO) {
+ return (*fieldToNACRowsMap)[fieldID];
+ }
+ else if (cType == CROSS) {
+ return (*fieldToNXCRowsMap)[fieldID];
+ }
+ else {
+ return (*fieldToNACRowsMap)[fieldID] + (*fieldToNXCRowsMap)[fieldID];
+ }
+}
+
+void MSMetaData::_getRowStats(
+ uInt& nACRows, uInt& nXCRows,
+ std::map<SubScanKey, uInt>*& subScanToNACRowsMap,
+ std::map<SubScanKey, uInt>*& subScanToNXCRowsMap,
+ vector<uInt>*& fieldToNACRowsMap,
+ vector<uInt>*& fieldToNXCRowsMap
+) const {
+ nACRows = 0;
+ nXCRows = 0;
+ subScanToNACRowsMap = new std::map<SubScanKey, uInt>();
+ subScanToNXCRowsMap = new std::map<SubScanKey, uInt>();
+ uInt myNFields = nFields();
+ fieldToNACRowsMap = new vector<uInt>(myNFields, 0);
+ fieldToNXCRowsMap = new vector<uInt>(myNFields, 0);
+ std::set<SubScanKey> subScanKeys = _getSubScanKeys();
+ std::set<SubScanKey>::const_iterator subIter = subScanKeys.begin();
+ std::set<SubScanKey>::const_iterator subEnd = subScanKeys.end();
+ while (subIter != subEnd) {
+ (*subScanToNACRowsMap)[*subIter] = 0;
+ (*subScanToNXCRowsMap)[*subIter] = 0;
+ ++subIter;
+ }
+ CountedPtr<Vector<Int> > ant1, ant2;
+ _getAntennas(ant1, ant2);
+ CountedPtr<Vector<Int> > scans = _getScans();
+ CountedPtr<Vector<Int> > fieldIDs = _getFieldIDs();
+ CountedPtr<Vector<Int> > obsIDs = _getObservationIDs();
+ CountedPtr<Vector<Int> > arrIDs = _getArrayIDs();
+ Vector<Int>::const_iterator aEnd = ant1->end();
+ Vector<Int>::const_iterator a1Iter = ant1->begin();
+ Vector<Int>::const_iterator a2Iter = ant2->begin();
+ Vector<Int>::const_iterator sIter = scans->begin();
+ Vector<Int>::const_iterator fIter = fieldIDs->begin();
+ Vector<Int>::const_iterator oIter = obsIDs->begin();
+ Vector<Int>::const_iterator arIter = arrIDs->begin();
+ SubScanKey subScanKey;
+ while (a1Iter!=aEnd) {
+ subScanKey.obsID = *oIter;
+ subScanKey.arrayID = *arIter;
+ subScanKey.scan = *sIter;
+ subScanKey.fieldID = *fIter;
+ if (*a1Iter == *a2Iter) {
+ ++nACRows;
+ ++(*subScanToNACRowsMap)[subScanKey];
+ ++(*fieldToNACRowsMap)[*fIter];
+ }
+ else {
+ ++nXCRows;
+ ++(*subScanToNXCRowsMap)[subScanKey];
+ ++(*fieldToNXCRowsMap)[*fIter];
+ }
+ ++a1Iter;
+ ++a2Iter;
+ ++sIter;
+ ++fIter;
+ ++arIter;
+ ++oIter;
+ }
+}
+
+void MSMetaData::_getRowStats(
+ uInt& nACRows, uInt& nXCRows,
+ CountedPtr<std::map<SubScanKey, uInt> >& scanToNACRowsMap,
+ CountedPtr<std::map<SubScanKey, uInt> >& scanToNXCRowsMap,
+ CountedPtr<vector<uInt> >& fieldToNACRowsMap,
+ CountedPtr<vector<uInt> >& fieldToNXCRowsMap
+) const {
+ // this method is responsible for setting _nACRows, _nXCRows,
_subScanToNACRowsMap,
+ // _subScanToNXCRowsMap, _fieldToNACRowsMap, _fieldToNXCRowsMap
+ if (_nACRows > 0 || _nXCRows > 0) {
+ nACRows = _nACRows;
+ nXCRows = _nXCRows;
+ scanToNACRowsMap = _subScanToNACRowsMap;
+ scanToNXCRowsMap = _subScanToNXCRowsMap;
+ fieldToNACRowsMap = _fieldToNACRowsMap;
+ fieldToNXCRowsMap = _fieldToNXCRowsMap;
+ return;
+ }
+
+ std::map<SubScanKey, uInt> *myScanToNACRowsMap, *myScanToNXCRowsMap;
+ vector<uInt> *myFieldToNACRowsMap, *myFieldToNXCRowsMap;
+ _getRowStats(
+ nACRows, nXCRows, myScanToNACRowsMap,
+ myScanToNXCRowsMap, myFieldToNACRowsMap,
+ myFieldToNXCRowsMap
+ );
+ scanToNACRowsMap = myScanToNACRowsMap;
+ scanToNXCRowsMap = myScanToNXCRowsMap;
+ fieldToNACRowsMap = myFieldToNACRowsMap;
+ fieldToNXCRowsMap = myFieldToNXCRowsMap;
+ uInt size = 2*(
+ sizeof(uInt) + _sizeof(*scanToNACRowsMap)
+ + _sizeof(*fieldToNACRowsMap)
+ );
+ if (_cacheUpdated(size)) {
+ _nACRows = nACRows;
+ _nXCRows = nXCRows;
+ _subScanToNACRowsMap = scanToNACRowsMap;
+ _subScanToNXCRowsMap = scanToNXCRowsMap;
+ _fieldToNACRowsMap = fieldToNACRowsMap;
+ _fieldToNXCRowsMap = fieldToNXCRowsMap;
+ }
+}
+
+void MSMetaData::_getAntennas(
+ CountedPtr<Vector<Int> >& ant1,
+ CountedPtr<Vector<Int> >& ant2
+) const {
+ if (
+ _antenna1 && _antenna1->size() > 0
+ && _antenna2 && _antenna2->size() > 0
+ ) {
+ ant1 = _antenna1;
+ ant2 = _antenna2;
+ }
+ String ant1ColName = MeasurementSet::columnName(MSMainEnums::ANTENNA1);
+ ROScalarColumn<Int> ant1Col(*_ms, ant1ColName);
+ Vector<Int> a1 = ant1Col.getColumn();
+ String ant2ColName = MeasurementSet::columnName(MSMainEnums::ANTENNA2);
+ ROScalarColumn<Int> ant2Col(*_ms, ant2ColName);
+ Vector<Int> a2 = ant2Col.getColumn();
+
+ ant1.reset(new Vector<Int>(a1));
+ ant2.reset(new Vector<Int>(a2));
+
+ if (_cacheUpdated(2*sizeof(Int)*ant1->size())) {
+ _antenna1 = ant1;
+ _antenna2 = ant2;
+ }
+}
+
+CountedPtr<Vector<Int> > MSMetaData::_getScans() const {
+ if (_scans && _scans->size() > 0) {
+ return _scans;
+ }
+ String scanColName = MeasurementSet::columnName(MSMainEnums::SCAN_NUMBER);
+ CountedPtr<Vector<Int> > scans(new Vector<Int>(ROScalarColumn<Int>(*_ms,
scanColName).getColumn()));
+ if (_cacheUpdated(sizeof(Int)*scans->size())) {
+ _scans = scans;
+ }
+ return scans;
+}
+
+CountedPtr<Vector<Int> > MSMetaData::_getObservationIDs() const {
+ if (_observationIDs && _observationIDs->size() > 0) {
+ return _observationIDs;
+ }
+ static const String obsColName =
MeasurementSet::columnName(MSMainEnums::OBSERVATION_ID);
+ CountedPtr<Vector<Int> > obsIDs(
+ new Vector<Int>(ROScalarColumn<Int>(*_ms, obsColName).getColumn())
+ );
+ if (_cacheUpdated(sizeof(Int)*obsIDs->size())) {
+ _observationIDs = obsIDs;
+ }
+ return obsIDs;
+}
+
+CountedPtr<Vector<Int> > MSMetaData::_getArrayIDs() const {
+ if (_arrayIDs && _arrayIDs->size() > 0) {
+ return _arrayIDs;
+ }
+ static const String arrColName =
MeasurementSet::columnName(MSMainEnums::ARRAY_ID);
+ CountedPtr<Vector<Int> > arrIDs(
+ new Vector<Int>(ROScalarColumn<Int>(*_ms, arrColName).getColumn())
+ );
+ if (_cacheUpdated(sizeof(Int)*arrIDs->size())) {
+ _arrayIDs = arrIDs;
+ }
+ return arrIDs;
+}
+
+CountedPtr<Vector<Int> > MSMetaData::_getFieldIDs() const {
+ if (_fieldIDs && ! _fieldIDs->empty()) {
+ return _fieldIDs;
+ }
+ String fieldIdColName = MeasurementSet::columnName(MSMainEnums::FIELD_ID);
+ CountedPtr<Vector<Int> > fields(
+ new Vector<Int>(ROScalarColumn<Int>(*_ms, fieldIdColName).getColumn())
+ );
+ if (_cacheUpdated(sizeof(Int)*fields->size())) {
+ _fieldIDs = fields;
+ }
+ return fields;
+}
+
+CountedPtr<Vector<Int> > MSMetaData::_getStateIDs() const {
+ if (_stateIDs && _stateIDs->size() > 0) {
+ return _stateIDs;
+ }
+ static const String stateColName =
MeasurementSet::columnName(MSMainEnums::STATE_ID);
+ CountedPtr<Vector<Int> > states(
+ new Vector<Int>(ROScalarColumn<Int>(*_ms, stateColName).getColumn())
+ );
+ Int maxState = max(*states);
+ Int nstates = (Int)nStates();
+ ThrowIf(
+ maxState >= nstates,
+ "MS only has " + String::toString(nstates)
+ + " rows in its STATE table, but references STATE_ID "
+ + String::toString(maxState) + " in its main table."
+ );
+ if (_cacheUpdated(sizeof(Int)*states->size())) {
+ _stateIDs = states;
+ }
+ return states;
+}
+
+CountedPtr<Vector<Int> > MSMetaData::_getDataDescIDs() const {
+ if (_dataDescIDs && ! _dataDescIDs->empty()) {
+ return _dataDescIDs;
+ }
+ static const String ddColName =
MeasurementSet::columnName(MSMainEnums::DATA_DESC_ID);
+ ROScalarColumn<Int> ddCol(*_ms, ddColName);
+ CountedPtr<Vector<Int> > dataDescIDs(
+ new Vector<Int>(ddCol.getColumn())
+ );
+ if (_cacheUpdated(sizeof(Int)*dataDescIDs->size())) {
+ _dataDescIDs = dataDescIDs;
+ }
+ return dataDescIDs;
+}
+
+std::set<Int> MSMetaData::getScansForState(
+ Int stateID, Int obsID, Int arrayID
+) {
+ if (! _hasStateID(stateID)) {
+ return std::set<Int>();
+ }
+ std::map<ScanKey, std::set<Int> > myScanToStatesMap =
_getScanToStatesMap();
+ ArrayKey arrayKey;
+ arrayKey.obsID = obsID;
+ arrayKey.arrayID = arrayID;
+ std::set<ScanKey> scanKeys = _getScanKeys(arrayKey);
+ //CountedPtr<Vector<Int> > scans = _getScans();
+ std::set<ScanKey>::const_iterator iter = scanKeys.begin();
+ std::set<ScanKey>::const_iterator end = scanKeys.end();
+ std::set<Int> stateIDs, scansForState;
+ while (iter != end) {
+ stateIDs = myScanToStatesMap[*iter];
+ if (stateIDs.find(stateID) != stateIDs.end()) {
+ scansForState.insert(iter->scan);
+ }
+ ++iter;
+ }
+ return scansForState;
+}
+
+std::map<ScanKey, std::set<Int> > MSMetaData::_getScanToStatesMap() const {
+ if (! _scanToStatesMap.empty()) {
+ return _scanToStatesMap;
+ }
+ std::map<ScanKey, std::set<Int> > myScanToStatesMap;
+ if (nStates() == 0) {
+ std::set<Int> empty;
+ std::set<ScanKey> scanKeys = this->_getScanKeys();
+ //std::set<SubScanKey> subScanKeys;
+ //_getSubScanKeys(subScanKeys, scanKeys);
+ std::set<ScanKey>::const_iterator end = scanKeys.end();
+ for (
+ std::set<ScanKey>::const_iterator scanKey=scanKeys.begin();
+ scanKey!=end; ++scanKey
+ ) {
+ myScanToStatesMap[*scanKey] = empty;
+ }
+ }
+ else {
+ map<SubScanKey, SubScanProperties> subScanProps =
_getSubScanProperties();
+ //map<ScanKey, ScanProperties> scanProps;
+ //map<ArrayKey, ArrayProperties> arrayProps;
+
+ //_getSubScanProperties(subScanProps, scanProps, arrayProps);
+ map<SubScanKey, SubScanProperties>::const_iterator iter =
subScanProps.begin();
+ map<SubScanKey, SubScanProperties>::const_iterator end =
subScanProps.end();
+ ScanKey key;
+ while (iter != end) {
+ SubScanKey subKey = iter->first;
+ key.obsID = subKey.obsID;
+ key.arrayID = subKey.arrayID;
+ key.scan = subKey.scan;
+ SubScanProperties subProps = iter->second;
+ myScanToStatesMap[scanKey(subKey)].insert(subProps.stateIDs.begin(),
subProps.stateIDs.end());
+ ++iter;
+ }
+ }
+ std::map<ScanKey, std::set<Int> >::const_iterator end =
myScanToStatesMap.end();
+ uInt mySize = sizeof(ScanKey)*myScanToStatesMap.size();
+ for (
+ std::map<ScanKey, std::set<Int> >::const_iterator
iter=myScanToStatesMap.begin();
+ iter!=end; ++iter
+ ) {
+ mySize += sizeof(Int)*iter->second.size();
+ }
+ if (_cacheUpdated(mySize)) {
+ _scanToStatesMap = myScanToStatesMap;
+ }
+ return myScanToStatesMap;
+}
+
+void MSMetaData::_getScansAndIntentsMaps(
+ std::map<ScanKey, std::set<String> >& scanToIntentsMap,
+ std::map<String, std::set<ScanKey> >& intentToScansMap
+) const {
+ // This method is responsible for setting _scanToIntentsMap and
_intentToScansMap
+ if (! _scanToIntentsMap.empty() && ! _intentToScansMap.empty()) {
+ scanToIntentsMap = _scanToIntentsMap;
+ intentToScansMap = _intentToScansMap;
+ return;
+ }
+ vector<std::set<String> > stateToIntentsMap;
+ std::set<String> uniqueIntents;
+ _getStateToIntentsMap(
+ stateToIntentsMap, uniqueIntents
+ );
+ std::map<ScanKey, std::set<Int> > scanToStatesMap = _getScanToStatesMap();
+ std::map<ScanKey, std::set<Int> >::const_iterator end =
scanToStatesMap.end();
+ std::set<Int> states;
+ std::set<String> intents;
+ for (
+ std::map<ScanKey, std::set<Int> >::const_iterator
iter=scanToStatesMap.begin();
+ iter!=end; ++iter
+ ) {
+ ScanKey scan = iter->first;
+ states = iter->second;
+ std::set<Int>::const_iterator endState = states.end();
+ for (
+ std::set<Int>::const_iterator myState=states.begin();
+ myState!=endState; ++myState
+ ) {
+ intents = stateToIntentsMap[*myState];
+ scanToIntentsMap[scan].insert(intents.begin(), intents.end());
+ std::set<String>::const_iterator endIntent = intents.end();
+ for (
+ std::set<String>::const_iterator myIntent=intents.begin();
+ myIntent!=endIntent; ++myIntent
+ ) {
+ intentToScansMap[*myIntent].insert(scan);
+ }
+ }
+ }
+ if (_cacheUpdated(_sizeof(scanToIntentsMap) + _sizeof(intentToScansMap)))
{
+ _scanToIntentsMap = scanToIntentsMap;
+ _intentToScansMap = intentToScansMap;
+ }
+}
+
+uInt MSMetaData::_sizeof(
+ const std::map<Double, MSMetaData::TimeStampProperties> & m
+) {
+ uInt sizeInt = sizeof(Int);
+ uInt size = m.size()*(sizeof(Double) + sizeInt);
+ std::map<Double, MSMetaData::TimeStampProperties>::const_iterator iter =
m.begin();
+ std::map<Double, MSMetaData::TimeStampProperties>::const_iterator end =
m.end();
+ uInt n = 0;
+ while (iter != end) {
+ n += iter->second.ddIDs.size();
+ ++iter;
+ }
+ return size + n*sizeInt;
+}
+
+template <class T>
+uInt MSMetaData::_sizeof(const std::map<T, std::set<String> >& m) {
+ uInt size = sizeof(T) * m.size();
+ typename std::map<T, std::set<String> >::const_iterator iter = m.begin();
+ typename std::map<T, std::set<String> >::const_iterator end = m.end();
+ while (iter != end) {
+ std::set<String>::const_iterator end2 = iter->second.end();
+ for (
+ std::set<String>::const_iterator iter2=iter->second.begin();
+ iter2!=end2; ++iter2
+ ) {
+ size += iter2->size();
+ }
+ ++iter;
+ }
+ return size;
+}
+
+template <class T, class U>
+uInt MSMetaData::_sizeof(const std::map<T, std::set<U> >& m) {
+ uInt size = sizeof(T)*m.size();
+ typename std::map<T, std::set<U> >::const_iterator iter = m.begin();
+ typename std::map<T, std::set<U> >::const_iterator end = m.end();
+ uInt nElements = 0;
+ while (iter != end) {
+ nElements += iter->second.size();
+ ++iter;
+ }
+ size += sizeof(U)*nElements;
+ return size;
+}
+
+template <class T, class U>
+uInt MSMetaData::_sizeof(const std::map<T, U>& m) {
+ return m.size()*(sizeof(T) + sizeof(U));
+}
+
+uInt MSMetaData::_sizeof(const vector<std::set<String> >& m) {
+ uInt size = sizeof(Int) * m.size();
+ vector<std::set<String> >::const_iterator end = m.end();
+ for (
+ vector<std::set<String> >::const_iterator iter=m.begin();
+ iter!=end; ++iter
+ ) {
+ std::set<String>::const_iterator end2 = iter->end();
+ for (
+ std::set<String>::const_iterator iter2=iter->begin();
+ iter2!=end2; ++iter2
+ ) {
+ size += iter2->size();
+ }
+ }
+ return size;
+}
+
+uInt MSMetaData::_sizeof(const vector<String>& m) {
+ vector<String>::const_iterator end = m.end();
+ uInt size = 0;
+ for (
+ vector<String>::const_iterator iter=m.begin();
+ iter!=end; ++iter
+ ) {
+ size += iter->length();
+ }
+ return size;
+}
+
+template <class T>
+uInt MSMetaData::_sizeof(const vector<T>& v) {
+ return v.size()*sizeof(T);
+}
+
+uInt MSMetaData::_sizeof(const Quantum<Vector<Double> >& m) {
+ return (sizeof(Double)+10)*m.getValue().size();
+}
+
+template <class T> uInt MSMetaData::_sizeof(const std::map<String,
std::set<T> >& m) {
+ uInt setssize = 0;
+ uInt size = 0;
+ typename std::map<String, std::set<T> >::const_iterator end = m.end();
+ for (
+ typename std::map<String, std::set<T> >::const_iterator iter=m.begin();
+ iter!=end; ++iter
+ ) {
+ size += iter->first.size();
+ setssize += iter->second.size();
+ }
+ size += sizeof(T) * setssize;
+ return size;
+}
+
+uInt MSMetaData::_sizeof(const vector<std::map<Int, Quantity> >& m) {
+ uInt size = 0;
+ vector<std::map<Int, Quantity> >::const_iterator end = m.end();
+ uInt intsize = sizeof(Int);
+ uInt qsize = 20;
+ for (
+ vector<std::map<Int, Quantity> >::const_iterator iter = m.begin();
+ iter!=end; ++iter
+ ) {
+ size += iter->size()*(2*intsize + qsize);
+ }
+ return size;
+}
+
+std::set<String> MSMetaData::getIntentsForScan(const ScanKey& scan) const {
+ _checkScan(scan);
+ std::map<ScanKey, std::set<String> > scanToIntentsMap;
+ std::map<String, std::set<ScanKey> > intentToScansMap;
+ _getScansAndIntentsMaps(
+ scanToIntentsMap,
+ intentToScansMap
+ );
+ return scanToIntentsMap[scan];
+}
+
+Bool MSMetaData::_cacheUpdated(const Float incrementInBytes) const {
+ Float newSize = _cacheMB + incrementInBytes/1e6;
+ if (newSize <= _maxCacheMB) {
+ _cacheMB = newSize;
+ return True;
+ }
+ return False;
+}
+
+std::set<uInt> MSMetaData::getSpwsForIntent(const String& intent) {
+ if (! _hasIntent(intent)) {
+ return std::set<uInt>();
+ }
+ vector<std::set<String> > spwToIntentsMap = _getSpwToIntentsMap();
+ std::set<uInt> spws;
+ for (uInt i=0; i<spwToIntentsMap.size(); ++i) {
+ if (
+ spwToIntentsMap[i].find(intent) != spwToIntentsMap[i].end()
+ ) {
+ spws.insert(i);
+ }
+ }
+ return spws;
+}
+
+std::vector<std::set<uInt> > MSMetaData::getSpwToDataDescriptionIDMap()
const {
+ // TODO perhaps cache the result, but atm doesn't seem worth doing
+ std::map<std::pair<uInt, uInt>, uInt> spwPolToDDID =
getSpwIDPolIDToDataDescIDMap();
+ std::vector<std::set<uInt> > mymap(nSpw(True));
+ std::map<std::pair<uInt, uInt>, uInt>::const_iterator iter =
spwPolToDDID.begin();
+ std::map<std::pair<uInt, uInt>, uInt>::const_iterator end =
spwPolToDDID.end();
+ while (iter != end) {
+ mymap[iter->first.first].insert(iter->second);
+ ++iter;
+ }
+ return mymap;
+}
+
+uInt MSMetaData::nSpw(Bool includewvr) const {
+ if (_nSpw > 0) {
+ return includewvr ? _nSpw : _nSpw - getWVRSpw().size();
+ }
+ uInt nSpw = _ms->spectralWindow().nrow();
+ _nSpw = nSpw;
+ return includewvr ? nSpw : nSpw - getWVRSpw().size();
+}
+
+uInt MSMetaData::nPol() {
+ if (_nPol == 0) {
+ _nPol = _ms->polarization().nrow();
+ }
+ return _nPol;
+}
+
+std::set<String> MSMetaData::getIntentsForSpw(const uInt spw) {
+ if (spw >= nSpw(True)) {
+ throw AipsError(
+ _ORIGIN + "spectral window out of range"
+ );
+ }
+ return _getSpwToIntentsMap()[spw];
+}
+
+std::set<String> MSMetaData::getIntentsForField(Int fieldID) {
+ if (! _hasFieldID(fieldID)) {
+ return std::set<String>();
+ }
+ vector<std::set<String> > fieldToIntentsMap;
+ std::map<String, std::set<Int> > intentToFieldsMap;
+ _getFieldsAndIntentsMaps(
+ fieldToIntentsMap, intentToFieldsMap
+ );
+ return fieldToIntentsMap[fieldID];
+}
+
+
+uInt MSMetaData::nFields() const {
+ if (_nFields > 0) {
+ return _nFields;
+ }
+ uInt nFields = _ms->field().nrow();
+ _nFields = nFields;
+ return nFields;
+}
+
+void MSMetaData::_getFieldsAndSpwMaps(
+ std::map<Int, std::set<uInt> >& fieldToSpwMap,
+ vector<std::set<Int> >& spwToFieldMap
+) {
+ // This method has the responsibility of setting _fieldToSpwMap and
_spwToFieldIDMap
+ if (! _fieldToSpwMap.empty() && ! _spwToFieldIDsMap.empty()) {
+ fieldToSpwMap = _fieldToSpwMap;
+ spwToFieldMap = _spwToFieldIDsMap;
+ return;
+ }
+ CountedPtr<Vector<Int> > allDDIDs = _getDataDescIDs();
+ CountedPtr<Vector<Int> > allFieldIDs = _getFieldIDs();
+ Vector<Int>::const_iterator endDDID = allDDIDs->end();
+ Vector<Int>::const_iterator curField = allFieldIDs->begin();
+ fieldToSpwMap.clear();
+ spwToFieldMap.resize(nSpw(True));
+ vector<uInt> ddidToSpwMap = _getDataDescIDToSpwMap();
+ for (
+ Vector<Int>::const_iterator curDDID=allDDIDs->begin();
+ curDDID!=endDDID; ++curDDID, ++curField
+ ) {
+ uInt spw = ddidToSpwMap[*curDDID];
+ fieldToSpwMap[*curField].insert(spw);
+ spwToFieldMap[spw].insert(*curField);
+ }
+ std::map<Int, std::set<uInt> >::const_iterator mapEnd =
fieldToSpwMap.end();
+ uInt mySize = 0;
+ for (
+ std::map<Int, std::set<uInt> >::const_iterator curMap =
fieldToSpwMap.begin();
+ curMap != mapEnd; ++curMap
+ ) {
+ mySize += curMap->second.size();
+ }
+ mySize *= sizeof(uInt);
+ mySize += sizeof(Int) * fieldToSpwMap.size() +
sizeof(uInt)*spwToFieldMap.size();
+ vector<std::set<Int> >::const_iterator map2End = spwToFieldMap.end();
+ uInt count = 0;
+ for (
+ vector<std::set<Int> >::const_iterator curMap = spwToFieldMap.begin();
+ curMap != map2End; ++curMap
+ ) {
+ count += curMap->size();
+ }
+ mySize += sizeof(Int)*count;
+ if (_cacheUpdated(mySize)) {
+ _fieldToSpwMap = fieldToSpwMap;
+ _spwToFieldIDsMap = spwToFieldMap;
+ }
+}
+
+std::set<uInt> MSMetaData::getSpwsForField(Int fieldID) {
+ if (! _hasFieldID(fieldID)) {
+ return std::set<uInt>();
+ }
+ std::map<Int, std::set<uInt> > myFieldToSpwMap;
+ vector<std::set<Int> > mySpwToFieldMap;
+ _getFieldsAndSpwMaps(myFieldToSpwMap, mySpwToFieldMap);
+ return myFieldToSpwMap[fieldID];
+}
+
+std::set<uInt> MSMetaData::getSpwsForField(const String& fieldName) {
+ uInt myNFields = nFields();
+ vector<String> fieldNames = _getFieldNames();
+ std::set<uInt> spws;
+ for (uInt i=0; i<myNFields; ++i) {
+ if (fieldNames[i] == fieldName) {
+ std::set<uInt> myspws = getSpwsForField(i);
+ spws.insert(myspws.begin(), myspws.end());
+ }
+ }
+ ThrowIf(
+ spws.empty(),
+ _ORIGIN + "field (" + fieldName + " does not exist."
+ );
+ return spws;
+}
+
+vector<String> MSMetaData::_getFieldNames() const {
+ if (! _fieldNames.empty()) {
+ return _fieldNames;
+ }
+
***The diff for this file has been truncated for email.***
=======================================
--- /dev/null
+++ /branches/nov14/ms/MSOper/MSMetaData.h Wed Mar 25 14:33:54 2015 UTC
@@ -0,0 +1,774 @@
+//# MSMetaData.h
+//# Copyright (C) 1998,1999,2000,2001
+//# Associated Universities, Inc. Washington DC, USA.
+//#
+//# This library is free software; you can redistribute it and/or modify it
+//# under the terms of the GNU Library General Public License as published
by
+//# the Free Software Foundation; either version 2 of the License, or (at
your
+//# option) any later version.
+//#
+//# This library is distributed in the hope that it will be useful, but
WITHOUT
+//# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+//# FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
+//# License for more details.
+//#
+//# You should have received a copy of the GNU Library General Public
License
+//# along with this library; if not, write to the Free Software Foundation,
+//# Inc., 675 Massachusetts Ave, Cambridge, MA 02139, USA.
+//#
+//# Correspondence concerning AIPS++ should be addressed as follows:
+//# Internet email:
aips2-...@nrao.edu.
+//# Postal address: AIPS++ Project Office
+//# National Radio Astronomy Observatory
+//# 520 Edgemont Road
+//# Charlottesville, VA 22903-2475 USA
+//#
+//# $Id$
+
+#ifndef MS_MSMETADATA_H
+#define MS_MSMETADATA_H
+
+#include <casacore/casa/aips.h>
+#include <casacore/casa/Quanta/QVector.h>
+#include <casacore/measures/Measures/MPosition.h>
+#include <casacore/ms/MeasurementSets/MeasurementSet.h>
+#include <casacore/ms/MeasurementSets/MSPointingColumns.h>
+#include <casacore/casa/Utilities/CountedPtr.h>
+#include <map>
+
+namespace casacore {
+
+template <class T> class ArrayColumn;
+struct ArrayKey;
+struct ScanKey;
+struct SubScanKey;
+
+// <summary>
+// Class to interrogate an MS for metadata. Interrogation happens on
demand
+// and resulting metadata are stored for use by subsequent queries if the
+// cache has not exceeded the specified limit.
+// </summary>
+
+class MSMetaData {
+
+public:
+
+ // for retrieving stats
+ enum CorrelationType {
+ AUTO,
+ CROSS,
+ BOTH
+ };
+
+ enum SQLDSwitch {
+ SQLD_INCLUDE,
+ SQLD_EXCLUDE,
+ SQLD_ONLY
+ };
+
+ // construct an object which stores a pointer to the MS and queries the MS
+ // only as necessary. The MeasurementSet pointer passed in should not go
out
+ // of scope in the calling code until the caller has finished with this
object,
+ // or else subsequent method calls on this object will result in a
segmentation
+ // fault; the pointer is not copied.
+ // <src>maxCacheSizeMB</src> is the maximum cache size in megabytes. <=0
means
+ // do not use a cache, in which case, each method call will have to
(re)query
+ // the MS. It is highly recommended to use a cache of reasonable size for
the
+ // specified MS if multiple methods are going to be called.
+ MSMetaData(const MeasurementSet *const &ms, const Float maxCacheSizeMB);
+
+ virtual ~MSMetaData();
+
+ // get the antenna diameters
+ Quantum<Vector<Double> > getAntennaDiameters();
+
+ // get the antenna ID for the antenna with the specified name.
+ vector<uInt> getAntennaIDs( const vector<String>& antennaNames);
+
+ // get the name of the antenna for the specified antenna ID
+ vector<String> getAntennaNames(
+ std::map<String, uInt>& namesToIDsMap,
+ const vector<uInt>& antennaIDs=vector<uInt>(0)
+ );
+
+ // get the antenna stations for the specified antenna IDs
+ vector<String> getAntennaStations(const vector<uInt>& antennaIDs);
+
+ // get the antenna stations for the specified antenna names
+ vector<String> getAntennaStations(const vector<String>& antennaNames);
+
+ vector<uInt> getDataDescIDToPolIDMap() const;
+
+ std::map<String, std::set<Int> > getIntentToFieldsMap();
+
+ std::map<String, std::set<ScanKey> > getIntentToScansMap();
+
+ std::map<String, std::set<uInt> > getIntentToSpwsMap();
+
+ std::set<String> getIntentsForScan(const ScanKey& scan) const;
+
+ // get all intents, in no particular (nor guaranteed) order.
+ std::set<String> getIntents() const;
+
+ // get a set of intents corresponding to a specified field
+ std::set<String> getIntentsForField(Int fieldID);
+
+ // get a set of intents corresponding to the specified spectral window
+ std::set<String> getIntentsForSpw(const uInt spw);
+ // get unique scan numbers
+
+ std::set<Int> getScanNumbers(Int obsID, Int arrayID) const;
+
+ std::set<Int> getScansForState(
+ Int stateID, Int obsID, Int arrayID
+ );
+
+ // get a set of spectral windows for which the specified <src>intent</src>
+ // applies.
+ virtual std::set<uInt> getSpwsForIntent(const String& intent);
+
+ // get the number of visibilities
+ uInt nRows() const;
+
+ uInt nRows(CorrelationType cType);
+
+ uInt nRows(
+ CorrelationType cType, Int arrayID, Int observationID,
+ Int scanNumber, Int fieldID
+ ) const;
+
+ uInt nRows(CorrelationType cType, uInt fieldID) const;
+
+ // get number of spectral windows
+ uInt nSpw(Bool includewvr) const;
+
+ // number of unique states (number of rows from the STATE table)
+ uInt nStates() const;
+
+ // get the number of fields.
+ uInt nFields() const;
+
+ // get a mapping of spectral window ID to data descrption IDs
+ std::vector<std::set<uInt> > getSpwToDataDescriptionIDMap() const;
+
+ // get a set of spectral windows corresponding to the specified fieldID
+ std::set<uInt> getSpwsForField(const Int fieldID);
+
+ // get a set of spectral windows corresponding to the specified field name
+ std::set<uInt> getSpwsForField(const String& fieldName);
+
+ // get the set of field IDs corresponding to the specified spectral
window.
+ std::set<Int> getFieldIDsForSpw(const uInt spw);
+
+ // get the set of field names corresponding to the specified spectral
window.
+ std::set<String> getFieldNamesForSpw(const uInt spw);
+
+
+ // get the set of spectral windows for the specified scan number.
+ std::set<uInt> getSpwsForScan(const ScanKey& scan) const;
+
+ // get the set of scan numbers for the specified spectral window.
+ std::set<Int> getScansForSpw(uInt spw, Int obsID, Int arrayID) const;
+
+ // get the number of antennas in the ANTENNA table
+ uInt nAntennas() const;
+
+ // ALMA-specific. get set of spectral windows used for TDM. These are
windows that have
+ // 64, 128, or 256 channels
+ std::set<uInt> getTDMSpw();
+
+ // ALMA-specific. get set of spectral windows used for FDM. These are
windows that do not
+ // have 1, 4, 64, 128, or 256 channels.
+ std::set<uInt> getFDMSpw();
+
+ // ALMA-specific. get spectral windows that have been averaged. These are
windows with 1 channel.
+ std::set<uInt> getChannelAvgSpw();
+
+ // ALMA-specific. Get the spectral window set used for WVR measurements.
These have 4 channels each.
+ std::set<uInt> getWVRSpw() const;
+
+ // ALMA-specific. Get the square law detector (total power) spectral
windows.
+ std::set<uInt> getSQLDSpw();
+
+ // Get the scans which fail into the specified time range (center-tol to
center+tol)
+ std::set<Int> getScansForTimes(
+ Double center, Double tol,
+ Int obsID, Int arrayID
+ ) const;
+
+ // Get the times for the specified scans
+ std::set<Double> getTimesForScans(std::set<ScanKey> scans) const;
+
+ // get the times for the specified scan.
+ // The return values come from the TIME column.
+ std::set<Double> getTimesForScan(const ScanKey& scan) const;
+
+ // get the time range for the specified scan. The pair will contain
+ // the start and stop time of the scan, determined from
min(TIME(x)-0.5*INTERVAL(x)) and
+ // max(TIME(x)-0.5*INTERVAL(x))
+ std::pair<Double, Double> getTimeRangeForScan(const ScanKey& scanKey)
const;
+
+ // get the times for the specified scan
+ // std::set<Double> getTimesForScan(const uInt scan) const;
+
+ // get the stateIDs associated with the specified scan.
+ std::set<Int> getStatesForScan(uInt obsID, uInt arrayID, Int scan) const;
+
+ // get the position of the specified antenna relative to the observatory
position.
+ // the three vector returned represents the longitudinal, latitudinal,
and elevation
+ // offsets (elements 0, 1, and 2 respectively). The longitude and
latitude offsets are
+ // measured along the surface of a sphere centered at the earth's center
and whose surface
+ // intersects the position of the observatory.
+ Quantum<Vector<Double> > getAntennaOffset(uInt which);
+
+ Quantum<Vector<Double> > getAntennaOffset(const String& name);
+
+ vector<Quantum<Vector<Double> > > getAntennaOffsets() const;
+ // get the positions of the specified antennas. If <src>which</src> is
empty, return
+ // all antenna positions.
+
+ vector<MPosition> getAntennaPositions(
+ const vector<uInt>& which=std::vector<uInt>(0)
+ ) const;
+
+ // <src>names</src> cannot be empty.
+ vector<MPosition> getAntennaPositions(const vector<String>& names);
+
+ std::map<uInt, Double> getAverageIntervalsForScan(const ScanKey& scan)
const;
+
+ vector<uInt> getBBCNos() const;
+
+ std::map<uInt, std::set<uInt> > getBBCNosToSpwMap(SQLDSwitch sqldSwitch);
+
+ vector<vector<Double> > getEdgeChans();
+
+ // get the field IDs for the specified field name. Case insensitive.
+ std::set<Int> getFieldIDsForField(const String& field) const;
+
+ // get field IDs associated with the specified scan number.
+ std::set<Int> getFieldsForScan(const ScanKey& scan) const;
+
+ // get the field IDs associated with the specified scans
+ std::set<Int> getFieldsForScans(
+ const std::set<Int>& scans, Int obsID, Int arrayID
+ ) const;
+
+ // get the field IDs associated with the specified intent.
+ std::set<Int> getFieldsForIntent(const String& intent);
+
+ // get the field IDs associated with the specified source.
+ std::set<Int> getFieldsForIntent(uInt sourceID) const;
+
+ std::map<Int, std::set<Int> > getFieldsForSourceMap() const;
+
+ std::map<Int, std::set<String> > getFieldNamesForSourceMap() const;
+
+ // get the field names associated with the specified field IDs. If
<src>fieldIDs</src>
+ // is empty, a vector of all the field names is returned.
+ vector<String> getFieldNamesForFieldIDs(const vector<uInt>& fieldIDs);
+
+ // Get the fields which fail into the specified time range (center-tol to
center+tol)
+ std::set<Int> getFieldsForTimes(Double center, Double tol);
+
+ // get telescope names in the order they are listed in the OBSERVATION
table. These are
+ // the telescopes (observatories), not the antenna names.
+ vector<String> getObservatoryNames();
+
+ // get the position of the specified telescope (observatory).
+ MPosition getObservatoryPosition(uInt which) const;
+
+ // get the scans associated with the specified intent
+ std::set<Int> getScansForIntent(
+ const String& intent, Int obsID, Int arrayID
+ ) const;
+
+ // get the scan numbers associated with the specified field ID.
+ std::set<Int> getScansForFieldID(Int fieldID, Int obsID, Int arrayID)
const;
+
+ // get the scan numbers associated with the specified field. Subclasses
should not implement or override.
+ std::set<Int> getScansForField(const String& field, Int obsID, Int
arrayID) const;
+
+ // The first value of the pair is spw, the second is polarization ID.
+ std::map<std::pair<uInt, uInt>, uInt> getSpwIDPolIDToDataDescIDMap()
const;
+
+ vector<String> getSpwNames() const;
+
+ // get a data structure, consumable by users, representing a summary of
the dataset
+ Record getSummary() const;
+
+ // get the times for which the specified field was observed
+ std::set<Double> getTimesForField(Int fieldID);
+
+ // get the time stamps associated with the specified intent
+ std::set<Double> getTimesForIntent(const String& intent) const;
+ Bool hasBBCNo() const;
+
+ //std::map<Double, Double> getExposuresForTimes() const;
+
+ // get the unique baselines in the MS. These are not necessarily every
combination of the
+ // n(n-1)/2 possible antenna pairs, but rather the number of unique
baselines represented in
+ // the main MS table, which in theory can be less than n(n-1)/2 (for
example if samples for
+ // certain antenna pairs are not recorded. The returned Matrix is nAnts x
nAnts in size. Pairs
+ // that are true represent baselines represented in the main MS table.
+ Matrix<Bool> getUniqueBaselines();
+
+ // get the number of unique baselines represented in the main MS table
which in theory can be
+ // less than n*(n-1)/2
+ virtual uInt nBaselines();
+
+ // get the effective total exposure time. This is the effective time
spent collecting unflagged data.
+ Quantity getEffectiveTotalExposureTime();
+
+ // get the number of scans in the dataset
+ uInt nScans();
+
+ // get the number of observations (from the OBSERVATIONS table) in the
dataset
+ uInt nObservations() const;
+
+ // get the number of arrays (from the ARRAY table) in the dataset
+ uInt nArrays();
+
+ // get the number of data description IDs (from the DATA_DESCRIPTION
table)
+ uInt nDataDescriptions() const;
+
+ // get the number of unflagged rows
+ Double nUnflaggedRows() const;
+
+ Double nUnflaggedRows(CorrelationType cType) const;
+
+ Double nUnflaggedRows(
+ CorrelationType cType, Int arrayID, uInt observationID,
+ Int scanNumber, uInt fieldID
+ ) const;
+
+ Double nUnflaggedRows(CorrelationType cType, Int fieldID) const;
+
+ inline Float getCache() const { return _cacheMB;}
+
+ vector<Double> getBandWidths() const;
+
+ vector<QVD> getChanFreqs() const;
+
+ vector<QVD> getChanWidths() const;
+
+ vector<Int> getNetSidebands();
+
+ vector<Quantity> getMeanFreqs();
+
+ vector<Quantity> getCenterFreqs() const;
+
+ vector<uInt> nChans() const;
+
+ uInt nPol();
+
+ // get a map of data desc ID, scan number pair to exposure time for the
first time
+ // for that data desc ID, scan number pair
+ vector<std::map<Int, Quantity> > getFirstExposureTimeMap();
+
+ // get polarization IDs for the specified scan and spwid
+ std::set<uInt> getPolarizationIDs(uInt obsID, Int arrayID, Int scan, uInt
spwid) const;
+
+ // get unique field IDs that exist in the main table.
+ std::set<Int> getUniqueFiedIDs() const;
+
+ // get the pointing directions associated with antenna1 and antenna2 for
+ // the specified row of the main MS table
+ std::pair<MDirection, MDirection> getPointingDirection(
+ Int& ant1, Int& ant2, Double& time, uInt row,
+ Bool interpolate=false, Int initialguess=0
+ ) const;
+
+ // get the time range for the entire dataset. min(TIME(x) -
0.5*INTERVAL(x)) to
+ // max(TIME(x) + 0.5*INTERVAL(x))
+ std::pair<Double, Double> getTimeRange() const;
+
+private:
+
+ struct SpwProperties {
+ Double bandwidth;
+ QVD chanfreqs;
+ QVD chanwidths;
+ Int netsideband;
+ // The sum of all channel frequencies divided by the number of channels
+ Quantity meanfreq;
+ // The mean of the low frequency extent of the lowest frequency channel
and
+ // the high frequency extend of the highest frequency channel. Often,
but not
+ // necessarily, the same as meanfreq
+ Quantity centerfreq;
+ uInt nchans;
+ // The center frequencies of the two channels at the edges of the window
+ vector<Double> edgechans;
+ uInt bbcno;
+ String name;
+ };
+
+ struct TimeStampProperties {
+ std::set<Int> ddIDs;
+ uInt nrows;
+ };
+
+ struct SubScanProperties {
+ std::set<Int> antennas;
+ Double beginTime;
+ std::set<uInt> ddIDs;
+ Double endTime;
+ uInt nrows;
+ std::set<Int> stateIDs;
+ std::map<Double, TimeStampProperties> timeProps;
+ };
+
+ // The general pattern is that a mutable gets set only once, on demand,
when its
+ // setter is called for the first time. If this pattern is broken,
defective behavior
+ // will occur.
+
+ const MeasurementSet* _ms;
+ mutable Float _cacheMB;
+ const Float _maxCacheMB;
+ mutable uInt _nStates, _nACRows, _nXCRows, _nSpw, _nFields, _nAntennas,
+ _nObservations, _nScans, _nArrays, _nrows, _nPol, _nDataDescIDs;
+ mutable std::map<ScanKey, std::set<uInt> > _scanToSpwsMap,
_scanToDDIDsMap;
+ mutable vector<uInt> _dataDescIDToSpwMap, _dataDescIDToPolIDMap /*,
_scanToNRowsMap */;
+ std::map<Int, std::set<uInt> > _fieldToSpwMap;
+ mutable std::map<ScanKey, std::set<Int> > _scanToStatesMap,
_scanToFieldsMap;
+ mutable std::map<Int, std::set<Int> > _fieldToStatesMap,
_stateToFieldsMap, _sourceToFieldsMap /*,
+ _arrayToScansMap, _scanToAntennasMap */;
+ mutable std::map<std::pair<uInt, uInt>, uInt> _spwPolIDToDataDescIDMap;
+ std::map<String, uInt> _antennaNameToIDMap;
+ //mutable std::map<ArrayKey, ArrayProperties> _arrayProperties;
+ //mutable std::map<ScanKey, ScanProperties> _scanProperties;
+ mutable std::map<SubScanKey, SubScanProperties> _subScanProperties;
+
+ mutable std::map<String, std::set<Int> > _intentToFieldIDMap;
+ mutable std::map<String, std::set<ScanKey> > _intentToScansMap;
+ mutable std::map<ScanKey, std::pair<Double, Double> > _scanToTimeRangeMap;
+ mutable std::map<ScanKey, std::map<uInt, Double> > _scanSpwToIntervalMap;
+ mutable std::map<std::pair<ScanKey, uInt>, std::set<uInt> >
_scanSpwToPolIDMap;
+ mutable std::set<String> _uniqueIntents;
+ mutable std::set<Int> /*_uniqueScanNumbers, */ _uniqueFieldIDs,
_uniqueStateIDs;
+ mutable std::set<uInt> _avgSpw, _tdmSpw, _fdmSpw, _wvrSpw, _sqldSpw;
+ mutable CountedPtr<Vector<Int> > _antenna1, _antenna2, _scans, _fieldIDs,
+ _stateIDs, _dataDescIDs, _observationIDs, _arrayIDs;
+ //mutable CountedPtr<AOSFMapI> _scanToNACRowsMap, _scanToNXCRowsMap;
+ mutable CountedPtr<std::map<SubScanKey, uInt> > _subScanToNACRowsMap,
_subScanToNXCRowsMap;
+ //mutable CountedPtr<std::map<Int, uInt> > _fieldToNACRowsMap,
_fieldToNXCRowsMap;
+
+ mutable CountedPtr<vector<uInt> > _fieldToNACRowsMap, _fieldToNXCRowsMap;
+ mutable std::map<ScanKey, std::set<String> > _scanToIntentsMap;
+ mutable vector<std::set<String> > _stateToIntentsMap, _spwToIntentsMap,
_fieldToIntentsMap;
+ mutable vector<SpwProperties> _spwInfo;
+ mutable vector<std::set<Int> > _spwToFieldIDsMap, _obsToArraysMap;
+ mutable vector<std::set<ScanKey> > _spwToScansMap, _ddidToScansMap,
_fieldToScansMap;
+
+ mutable vector<String> _fieldNames, _antennaNames, _observatoryNames,
_stationNames;
+ mutable CountedPtr<Vector<Double> > _times;
+ CountedPtr<Quantum<Vector<Double> > > _exposures;
+ mutable CountedPtr<std::map<ScanKey, std::set<Double> > > _scanToTimesMap;
+ std::map<String, std::set<uInt> > _intentToSpwsMap;
+ mutable std::map<String, std::set<Double> > _intentToTimesMap;
+
+ CountedPtr<std::map<Int, std::set<Double> > > _fieldToTimesMap;
+ CountedPtr<std::map<Double, std::set<Int> > > _timeToFieldsMap;
+
+ mutable vector<MPosition> _observatoryPositions, _antennaPositions;
+ mutable vector<Quantum<Vector<Double> > > _antennaOffsets;
+ Quantum<Vector<Double> > _antennaDiameters;
+ Matrix<Bool> _uniqueBaselines;
+ Quantity _exposureTime;
+ mutable Double _nUnflaggedACRows, _nUnflaggedXCRows;
+ mutable CountedPtr<vector<Double> > _unflaggedFieldNACRows,
_unflaggedFieldNXCRows;
+ mutable CountedPtr<std::map<SubScanKey, Double> >
_unflaggedSubScanNACRows, _unflaggedSubScanNXCRows;
+ // mutable CountedPtr<AOSFMapD> _unflaggedScanNACRows,
_unflaggedScanNXCRows;
+ const String _taqlTableName;
+ const vector<const Table*> _taqlTempTable;
+ mutable CountedPtr<ArrayColumn<Bool> > _flagsColumn;
+
+ mutable Bool _spwInfoStored;
+ vector<std::map<Int, Quantity> > _firstExposureTimeMap;
+ mutable vector<Int> _numCorrs;
+
+ mutable std::set<ArrayKey> _arrayKeys;
+ mutable std::set<ScanKey> _scanKeys;
+ mutable std::set<SubScanKey> _subscans;
+ mutable std::map<ScanKey, std::set<SubScanKey> > _scanToSubScans;
+
+ //mutable CountedPtr<std::map<Double, TimeStampProperties> >
_timeStampPropsMap;
+
+ // disallow copy constructor and = operator
+ MSMetaData(const MSMetaData&);
+ MSMetaData operator =(const MSMetaData&);
+
+ // This comment from thunter in the original ValueMapping python class
+ // # Determine the number of polarizations for the first OBSERVE_TARGET
intent.
+ // # Used by plotbandpass for BPOLY plots since the number of pols
cannot be inferred
+ // # correctly from the caltable alone. You cannot not simply use the
first row, because
+ // # it may be a pointing scan which may have different number of
polarizations than what
+ // # the TARGET and BANDPASS calibrator will have.
+ // # -- T. Hunter
+ // uInt _getNumberOfPolarizations();
+
+ void _setSpwInfo(const MeasurementSet& ms);
+
+ // set metadata from OBSERVATION table
+ void _setObservation(const MeasurementSet& ms);
+
+ Bool _cacheUpdated(const Float incrementInBytes) const;
+
+ void _checkField(uInt fieldID) const;
+
+ //static void _checkScan(const Int scan, const std::set<Int> allScans);
+
+ void _checkScan(const ScanKey& key) const;
+
+ void _checkScans(const std::set<ScanKey>& scanKeys) const;
+
+ void _checkSubScan(const SubScanKey& key) const;
+
+ static void _checkTolerance(const Double tol);
+
+ void _createScanRecords(
+ Record& parent, const ArrayKey& arrayKey,
+ const std::map<SubScanKey, SubScanProperties>& subScanProps
+ ) const;
+
+ void _createSubScanRecords(
+ Record& parent, uInt& scanNRows, std::set<Int>& antennasForScan,
+ const ScanKey& scanKey, const std::map<SubScanKey, SubScanProperties>&
subScanProps
+ ) const;
+
+ static void _createTimeStampRecords(
+ Record& parent,
+ const SubScanProperties& subScanProps
+ );
+
+ vector<String> _getAntennaNames(
+ std::map<String, uInt>& namesToIDsMap
+ );
+
+ vector<MPosition> _getAntennaPositions() const;
+
+ void _getAntennas(
+ CountedPtr<Vector<Int> >& ant1,
+ CountedPtr<Vector<Int> >& ant2
+ ) const;
+ CountedPtr<Vector<Int> > _getArrayIDs() const;
+
+ CountedPtr<Vector<Int> > _getDataDescIDs() const;
+
+ vector<uInt> _getDataDescIDToSpwMap() const;
+
+ CountedPtr<Quantum<Vector<Double> > > _getExposureTimes();
+
+ void _getFieldsAndIntentsMaps(
+ vector<std::set<String> >& fieldToIntentsMap,
+ std::map<String, std::set<Int> >& intentToFieldsMap
+ );
+
+ void _getFieldsAndScansMaps(
+ vector<std::set<ScanKey> >& fieldToScansMap,
+ std::map<ScanKey, std::set<Int> >& scanToFieldsMap
+ ) const;
+
+ void _getFieldsAndSpwMaps(
+ std::map<Int, std::set<uInt> >& fieldToSpwMap,
+ vector<std::set<Int> >& spwToFieldMap
+ );
+
+ void _getFieldsAndStatesMaps(
+ std::map<Int, std::set<Int> >& fieldToStatesMap,
+ std::map<Int, std::set<Int> >& stateToFieldsMap
+ );
+
+ void _getFieldsAndTimesMaps(
+ CountedPtr<std::map<Int, std::set<Double> > >& fieldToTimesMap,
+ CountedPtr<std::map<Double, std::set<Int> > >& timesToFieldMap
+ );
+
+ CountedPtr<Vector<Int> > _getFieldIDs() const;
+
+ vector<String> _getFieldNames() const;
+
+ CountedPtr<ArrayColumn<Bool> > _getFlags() const;
+
+ std::map<String, std::set<Double> > _getIntentsToTimesMap() const;
+
+ CountedPtr<Vector<Int> > _getObservationIDs() const;
+
+ CountedPtr<Vector<Int> > _getScans() const;
+
+ vector<std::set<String> > _getSpwToIntentsMap();
+
+ CountedPtr<Vector<Int> > _getStateIDs() const;
+
+ CountedPtr<Vector<Double> > _getTimes() const;
+
+ //CountedPtr<std::map<Double, TimeStampProperties> >
_getTimeStampProperties() const;
+
+ Bool _hasIntent(const String& intent) const;
+
+ Bool _hasFieldID(Int fieldID) const;
+
+ Bool _hasStateID(Int stateID);
+
+ void _hasAntennaID(Int antennaID);
+
+ std::map<Double, Double> _getTimeToTotalBWMap(
+ const Vector<Double>& times, const Vector<Int>& ddIDs
+ );
+
+ MDirection _getInterpolatedDirection(
+ const ROMSPointingColumns& pCols, const Int& index,
+ const Double& time
+ ) const;
+
+ // number of correlations from the polarzation table.
+ vector<Int> _getNumCorrs() const;
+
+ vector<std::set<Int> > _getObservationIDToArrayIDsMap() const;
+
+ vector<MPosition> _getObservatoryPositions();
+
+ void _getRowStats(
+ uInt& nACRows, uInt& nXCRows,
+ std::map<SubScanKey, uInt>*& subScanToNACRowsMap,
+ std::map<SubScanKey, uInt>*& subScanToNXCRowsMap,
+ vector<uInt>*& fieldToNACRowsMap,
+ vector<uInt>*& fieldToNXCRowsMap
+ ) const;
+
+ void _getRowStats(
+ uInt& nACRows, uInt& nXCRows,
+ CountedPtr<std::map<SubScanKey, uInt> >& scanToNACRowsMap,
+ CountedPtr<std::map<SubScanKey, uInt> >& scanToNXCRowsMap,
+ CountedPtr<vector<uInt> >& fieldToNACRowsMap,
+ CountedPtr<vector<uInt> >& fieldToNXCRowsMap
+ ) const;
+
+ // get all ScanKeys in the dataset
+ std::set<ScanKey> _getScanKeys() const;
+
+ // get all ScanKeys in the dataset that have the specified arrayKey
+ std::set<ScanKey> _getScanKeys(const ArrayKey& arrayKey) const;
+
+ // get the scan keys in the specified set that have the associated
arrayKey
+ std::set<ScanKey> _getScanKeys(
+ const std::set<ScanKey>& scanKeys, const ArrayKey& arrayKey
+ ) const;
+
+ // get all valid scan numbers associated with the specified arrayKey
+ std::set<Int> _getScanNumbers(const ArrayKey& arrayKey) const;
+
+ // get the scan numbers associated with the scanKeys. The members of
+ // scanKeys do not have to have the same ArrayKey, and no warning is
+ // given if they are not.
+ std::set<Int> _getScanNumbers(const std::set<ScanKey>& scanKeys) const;
+
+ void _getScansAndDDIDMaps(
+ std::map<ScanKey, std::set<uInt> >& scanToDDIDMap,
+ vector<std::set<ScanKey> >& ddIDToScanMap
+ ) const;
+
+ void _getScansAndIntentsMaps(
+ std::map<ScanKey, std::set<String> >& scanToIntentsMap,
+ std::map<String, std::set<ScanKey> >& intentToScansMap
+ ) const;
+
+ void _getScansAndSpwMaps(
+ std::map<ScanKey, std::set<uInt> >& scanToSpwMap,
+ vector<std::set<ScanKey> >& spwToScanMap
+ ) const;
+
+ std::map<ScanKey, std::set<Int> > _getScanToStatesMap() const;
+
+ std::map<ScanKey, std::set<SubScanKey> > _getScanToSubScansMap() const;
+
+ CountedPtr<std::map<ScanKey, std::set<Double> > > _getScanToTimesMap()
const;
+
+ vector<SpwProperties> _getSpwInfo(
+ std::set<uInt>& avgSpw, std::set<uInt>& tdmSpw,
+ std::set<uInt>& fdmSpw, std::set<uInt>& wvrSpw,
+ std::set<uInt>& sqldSpw
+ ) const;
+
+ void _getSpwsAndIntentsMaps(
+ vector<std::set<String> >& spwToIntentsMap,
+ std::map<String, std::set<uInt> >& intentToSpwsMap
+ );
+
+ vector<SpwProperties> _getSpwInfo2(
+ std::set<uInt>& avgSpw, std::set<uInt>& tdmSpw, std::set<uInt>& fdmSpw,
+ std::set<uInt>& wvrSpw, std::set<uInt>& sqldSpw
+ ) const;
+
+ void _getStateToIntentsMap(
+ vector<std::set<String> >& statesToIntentsMap,
+ std::set<String>& uniqueIntents
+ ) const;
+
+ vector<String> _getStationNames();
+
+ std::map<SubScanKey, SubScanProperties> _getSubScanProperties() const;
+
+ std::set<SubScanKey> _getSubScanKeys() const;
+
+ // get subscans related to the given scan
+ std::set<SubScanKey> _getSubScanKeys(const ScanKey& scanKey) const;
+
+ //In scanSpwToIntervalMap, the key is a scan, spw pair.
+ void _getTimesAndInvervals(
+ std::map<ScanKey, std::pair<Double, Double> >& scanToTimeRangeMap,
+ std::map<ScanKey, std::map<uInt, Double> >& scanSpwToIntervalMap
+ ) const;
+
+ void _getUnflaggedRowStats(
+ Double& nACRows, Double& nXCRows,
+ CountedPtr<std::map<SubScanKey, Double> >& subScanToNACRowsMap,
+ CountedPtr<std::map<SubScanKey, Double> >& subScanToNXCRowsMap,
+ CountedPtr<vector<Double> >& fieldToNACRowsMap,
+ CountedPtr<vector<Double> >& fieldToNXCRowsMap
+ ) const;
+
+ void _getUnflaggedRowStats(
+ Double& nACRows, Double& nXCRows,
+ vector<Double>*& fieldNACRows, vector<Double>*& fieldNXCRows,
+ std::map<SubScanKey, Double>*& scanNACRows,
+ std::map<SubScanKey, Double>*& scanNXCRows
+ ) const;
+
+ static uInt _sizeof(const std::map<Double,
MSMetaData::TimeStampProperties> & m);
+
+ template <class T>
+ static uInt _sizeof(const std::map<T, std::set<String> >& m);
+
+ template <class T, class U>
+ static uInt _sizeof(const std::map<T, std::set<U> >& m);
+
+ template <class T, class U>
+ static uInt _sizeof(const std::map<T, U>& m);
+
+ static uInt _sizeof(const vector<std::set<String> >& m);
+
+ static uInt _sizeof(const vector<String>& m);
+
+ template <class T>
+ static uInt _sizeof(const vector<T>& v);
+
+ static uInt _sizeof(const Quantum<Vector<Double> >& m);
+
+ template <class T>
+ static uInt _sizeof(const vector<std::set<T> >& v);
+
+ template <class T> static uInt _sizeof(const std::map<String, std::set<T>
>& map);
+
+ static uInt _sizeof(const vector<std::map<Int, Quantity> >& map);
+
+ static uInt _sizeof(const std::map<std::pair<Int, uInt>, std::set<uInt>
>& map);
+
+ static std::map<Int, uInt> _toUIntMap(const Vector<Int>& v);
+
+};
+
+
+
+}
+
+#endif
=======================================
--- /dev/null
+++ /branches/nov14/ms/MSOper/MSReader.cc Wed Mar 25 14:33:54 2015 UTC
@@ -0,0 +1,543 @@
+//# MSReader.cc: read from an MS, coordinating all of the subtables
+//# Copyright (C) 2000,2002
+//# Associated Universities, Inc. Washington DC, USA.
+//#
+//# This library is free software; you can redistribute it and/or modify it
+//# under the terms of the GNU Library General Public License as published
by
+//# the Free Software Foundation; either version 2 of the License, or (at
your
+//# option) any later version.
+//#
+//# This library is distributed in the hope that it will be useful, but
WITHOUT
+//# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+//# FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
+//# License for more details.
+//#
+//# You should have received a copy of the GNU Library General Public
License
+//# along with this library; if not, write to the Free Software Foundation,
+//# Inc., 675 Massachusetts Ave, Cambridge, MA 02139, USA.
+//#
+//# Correspondence concerning AIPS++ should be addressed as follows:
+//# Internet email:
aips2-...@nrao.edu.
+//# Postal address: AIPS++ Project Office
+//# National Radio Astronomy Observatory
+//# 520 Edgemont Road
+//# Charlottesville, VA 22903-2475 USA
+//#
+//# $Id$
+
+#include <casacore/ms/MSOper/MSReader.h>
+
+#include <casacore/casa/Arrays/ArrayLogical.h>
+#include <casacore/casa/Arrays/ArrayMath.h>
+#include <casacore/casa/Exceptions/Error.h>
+#include <casacore/casa/Logging/LogIO.h>
+#include <casacore/measures/Measures/MEpoch.h>
+#include <casacore/casa/Quanta/Quantum.h>
+#include <casacore/tables/Tables/TableDesc.h>
+#include <casacore/tables/Tables/TableRecord.h>
+#include <casacore/casa/Utilities/Assert.h>
+
+namespace casacore { //# NAMESPACE CASACORE - BEGIN
+
+MSReader::MSReader(const MeasurementSet &ms)
+ : itsMS(ms), itsMSCols(ms), itsSecUnit("s"), itsIds(ms), itsTabId(-1),
+ itsMainId(-1), itsAnt1Id(-1), itsAnt2Id(-1), itsDDId(-1),
itsDopplerId(-1),
+ itsFeed1Id(-1), itsFeed2Id(-1), itsFieldId(-1), itsFlagCmdId(-1),
+ itsFreqOffsetId(-1), itsObsId(-1), itsPointing1Id(-1),
itsPointing2Id(-1),
+ itsPolId(-1), itsProcId(-1), itsSourceId(-1), itsSpwId(-1),
itsStateId(-1),
+ itsSyscal1Id(-1), itsSyscal2Id(-1), itsWeather1Id(-1),
itsWeather2Id(-1)
+{
+ // assign indexes to every table to start with
+ TableRecord kwSet(itsMS.keywordSet());
+ uInt idCount = 0;
+ for (uInt i=0;i<kwSet.nfields();i++) {
+ if (kwSet.type(i) == TpTable) {
+ itsTabId.define(kwSet.name(i),idCount);
+ idCount++;
+ } // ignore all other keywords
+ }
+
+ // need independent rows for antenna1 and antenna2 and feed1 and feed2
+
+ // ANTENNA1 == ANTENNA
+ // ANTENNA is required
+ itsAnt1Id = itsTabId("ANTENNA");
+ DebugAssert(itsAnt1Id>=0, AipsError);
+ itsTabId.define("ANTENNA1", itsAnt1Id);
+ // ANTENNA2 gets a new number
+ itsTabId.define("ANTENNA2", idCount++);
+ itsAnt2Id = itsTabId("ANTENNA2");
+
+ // FEED1 == FEED
+ // FEED is required
+ itsFeed1Id = itsTabId("FEED");
+ DebugAssert(itsFeed1Id>=0, AipsError);
+ itsTabId.define("FEED1", itsFeed1Id);
+ // FEED2 gets a new number
+ itsTabId.define("FEED2", idCount++);
+ itsFeed2Id = itsTabId("FEED2");
+
+ // there are two POINTING lookups, one for each possible antenna
+ // POINTING is a required table
+ itsPointing1Id = itsTabId("POINTING");
+ DebugAssert(itsPointing1Id>=0, AipsError);
+ itsTabId.define("POINTING1", itsPointing1Id);
+
+ // POINTING2 gets a new number
+ itsTabId.define("POINTING2", idCount++);
+ itsPointing2Id = itsTabId("POINTING2");
+
+ // there are two SYSCAL lookups, one for each possible antenna
+ // SYSCAL is an optional table
+ itsSyscal1Id = itsTabId("SYSCAL");
+ if (itsSyscal1Id >= 0) {
+ itsTabId.define("SYSCAL1", itsSyscal1Id);
+ // SYSCAL2 gets a new number
+ itsTabId.define("SYSCAL2", idCount++);
+ itsSyscal2Id = itsTabId("SYSCAL2");
+ }
+
+ // there are two WEATHER lookups, one for each possible antenna
+ // WEATHER is an optional table
+ itsWeather1Id = itsTabId("WEATHER");
+ if (itsWeather1Id >= 0) {
+ itsTabId.define("WEATHER1", itsWeather1Id);
+ // WEATHER2 gets a new number
+ itsTabId.define("WEATHER2", idCount++);
+ itsWeather2Id = itsTabId("WEATHER2");
+ }
+
+ // And the MAIN table needs a presence in the various blocks
+ itsTabId.define("MAIN", idCount++);
+ itsMainId = itsTabId("MAIN");
+
+ // at this point, we know the size of the things we need == idCount
+ Vector<Bool> handledTab(idCount, False);
+
+ itsIndexes.resize(idCount);
+ itsTabRows.resize(idCount);
+ itsRowNumbers.resize(idCount);
+ itsTableNames.resize(idCount);
+ itsRowNumbers = -1;
+
+ // MAIN table, no index, just the table row
+ itsTabRows[itsMainId] = ROTableRow(itsMS);
+ handledTab(itsMainId) = True;
+
+ // ANTENNA1 - no index, indexed simply via ANTENNA1 value
+ itsTabRows[itsAnt1Id] = ROTableRow(itsMS.antenna());
+ handledTab(itsAnt1Id) = True;
+
+ // ANTENNA2 - no index, indexed simply via ANTENNA2 value
+ itsTabRows[itsAnt2Id] = ROTableRow(itsMS.antenna());
+ handledTab(itsAnt2Id) = True;
+
+ // DATA_DESCRIPTION - no index, indexed simply via DATA_DESC_ID value
+ // This table is required.
+ itsDDId = itsTabId("DATA_DESCRIPTION");
+ DebugAssert(itsDDId>=0, AipsError);
+ itsTabRows[itsDDId] = ROTableRow(itsMS.dataDescription());
+ handledTab(itsDDId) = True;
+
+ // DOPPLER - has a special index. This table is OPTIONAL
+ itsDopplerId = itsTabId("DOPPLER");
+ if (itsDopplerId >= 0) {
+ itsDopplerIndex.attach(itsMS.doppler());
+ itsTabRows[itsDopplerId] = ROTableRow(itsMS.doppler());
+ handledTab(itsDopplerId) = True;
+ }
+
+ // FEED1 - indexed
+ itsFeed1Index.attach(itsMS.feed());
+ itsTabRows[itsFeed1Id] = ROTableRow(itsMS.feed());
+ handledTab(itsFeed1Id) = True;
+
+
+ // FEED2 - indexed
+ itsFeed2Index.attach(itsMS.feed());
+ itsTabRows[itsFeed2Id] = ROTableRow(itsMS.feed());
+ handledTab(itsFeed2Id) = True;
+
+ // FIELD - no index, indexed simply via FIELD_ID value
+ // This table is required.
+ itsFieldId = itsTabId("FIELD");
+ DebugAssert(itsFieldId>=0, AipsError);
+ itsTabRows[itsFieldId] = ROTableRow(itsMS.field());
+ handledTab(itsFieldId) = True;
+
+ // FLAG_CMD, simple time and interval MSTableIndex
+ // This table is required
+ itsFlagCmdId = itsTabId("FLAG_CMD");
+ DebugAssert(itsFlagCmdId>=0, AipsError);
+ itsIndexes[itsFlagCmdId] =
MSTableIndex(itsMS.flagCmd(),Vector<String>());
+ itsTabRows[itsFlagCmdId] = ROTableRow(itsMS.flagCmd());
+ handledTab(itsFlagCmdId) = True;
+
+ // FREQ_OFFSET - indexed
+ // This table is optional
+ itsFreqOffsetId = itsTabId("FREQ_OFFSET");
+ if (itsFreqOffsetId >= 0) {
+ itsFreqOffIndex.attach(itsMS.freqOffset());
+ itsTabRows[itsFreqOffsetId] = ROTableRow(itsMS.freqOffset());
+ handledTab(itsFreqOffsetId) = True;
+ }
+
+ // HISTORY - not handled here, this is a required table
+ // make sure its marked as undefined in the ID map and mark it as
handled here
+ Int histId = itsTabId("HISTORY");
+ if (histId >= 0) {
+ itsTabId.define("HISTORY",-1);
+ handledTab(histId) = True;
+ }
+
+ // OBSERVATION - not indexed, this is a required table
+ itsObsId = itsTabId("OBSERVATION");
+ DebugAssert(itsObsId>=0, AipsError);
+ itsTabRows[itsObsId] = ROTableRow(itsMS.observation());
+ handledTab(itsObsId) = True;
+
+ // POINTING1 and POINTING2 - indexed, this is a required table
+ // Allready have itsPointing1Id and itsPointing2Id
+ itsPointing1Index.attach(itsMS.pointing());
+ itsTabRows[itsPointing1Id] = ROTableRow(itsMS.pointing());
+ handledTab(itsPointing1Id) = True;
+ itsPointing2Index.attach(itsMS.pointing());
+ itsTabRows[itsPointing2Id] = ROTableRow(itsMS.pointing());
+ handledTab(itsPointing2Id) = True;
+
+ // POLARIZATION - not indexed, this is a required table
+ itsPolId = itsTabId("POLARIZATION");
+ DebugAssert(itsPolId>=0, AipsError);
+ itsTabRows[itsPolId] = ROTableRow(itsMS.polarization());
+ handledTab(itsPolId) = True;
+
+ // PROCESSOR - not indexed, this is a required table
+ itsProcId = itsTabId("PROCESSOR");
+ DebugAssert(itsProcId>=0, AipsError);
+ itsTabRows[itsProcId] = ROTableRow(itsMS.processor());
+ handledTab(itsProcId) = True;
+
+ // SOURCE - indexed, this is an optional table
+ itsSourceId = itsTabId("SOURCE");
+ if (itsSourceId >= 0) {
+ itsSourceIndex.attach(itsMS.source());
+ itsTabRows[itsSourceId] = ROTableRow(itsMS.source());
+ handledTab(itsSourceId) = True;
+ }
+
+ // SPECTRAL_WINDOW - not indexed, this is a required table
+ itsSpwId = itsTabId("SPECTRAL_WINDOW");
+ DebugAssert(itsSpwId>=0, AipsError);
+ itsTabRows[itsSpwId] = ROTableRow(itsMS.spectralWindow());
+ handledTab(itsSpwId) = True;
+
+ // STATE - not indexed, this is an optional table
+ itsStateId = itsTabId("STATE");
+ if (itsStateId >= 0) {
+ itsTabRows[itsStateId] = ROTableRow(itsMS.state());
+ handledTab(itsStateId) = True;
+ }
+
+ // SYSCAL1 and SYSCAL2 - indexed, this is an optional table
+ // already know itsSyscal1Id and itsSyscal2Id
+ if (itsSyscal1Id >= 0) {
+ itsSyscal1Index.attach(itsMS.sysCal());
+ itsTabRows[itsSyscal1Id] = ROTableRow(itsMS.sysCal());
+ handledTab(itsSyscal1Id) = True;
+ // SYSCAL2 must exist if SYSCAL1 exists
+ itsSyscal2Index.attach(itsMS.sysCal());
+ itsTabRows[itsSyscal2Id] = ROTableRow(itsMS.sysCal());
+ handledTab(itsSyscal2Id) = True;
+ }
+
+ // WEATHER1 and WEATHER2 - indexed, this is an optional table
+ // already know itsWeather1Id and itsWeather2Id
+ if (itsWeather1Id >= 0) {
+ itsWeather1Index.attach(itsMS.weather());
+ itsTabRows[itsWeather1Id] = ROTableRow(itsMS.weather());
+ handledTab(itsWeather1Id) = True;
+ // WEATHER2 must exist if WEATHER1 exists
+ itsWeather2Index.attach(itsMS.weather());
+ itsTabRows[itsWeather2Id] = ROTableRow(itsMS.weather());
+ handledTab(itsWeather2Id) = True;
+ }
+
+ // and now, for everything not handled above, also fill in
itsTableNames
+ Vector<String> tableNames(idCount);
+ for (uInt i=0; i<itsTabId.ndefined(); i++) {
+ Int tabId = itsTabId.getVal(i);
+ if (tabId >= 0) {
+ String tabName = itsTabId.getKey(i);
+ tableNames(tabId) = tabName;
+ if (!handledTab(tabId)) {
+ itsIndexes[tabId].attach(kwSet.asTable(tabName), Vector<String>());
+ itsTabRows[tabId] = ROTableRow(kwSet.asTable(tabName));
+ handledTab(tabId) = True;
+ }
+ }
+ }
+ // copy the non-empty values in tableNames to itsTableNames
+ uInt nameCount = 0;
+ for (uInt i=0;i<tableNames.nelements();i++) {
+ if (tableNames(i).length() > 0) {
+ itsTableNames(nameCount++) = tableNames(i);
+ }
+ }
+ itsTableNames.resize(nameCount, True);
+}
+
+
+void MSReader::gotoRow(uInt which)
+{
+ // give up if this isn't a valid row. Perhaps this should do
something more
+ // obnoxious, like make this a boolean fn and return False?
+ if (which >= itsMS.nrow()) return;
+
+ // don't do anything if which is the same as the previous call.
+ // This will have problems is the MS has been written to in the
meantime.
+ if (itsRowNumbers[itsMainId] >= 0 && uInt(itsRowNumbers[itsMainId]) ==
which) return;
+
+ itsRowNumbers = -1;
+
+ itsTabRows[itsMainId].get(which);
+ itsRowNumbers[itsMainId] = which;
+
+ // simple indexes first
+ Int ant1Id = itsIds.antenna1(which);
+ if (ant1Id >= 0) {
+ itsTabRows[itsAnt1Id].get(ant1Id);
+ itsRowNumbers[itsAnt1Id] = ant1Id;
+ }
+ Int ant2Id = itsIds.antenna1(which);
+ if (ant2Id >= 0) {
+ itsTabRows[itsAnt2Id].get(ant2Id);
+ itsRowNumbers[itsAnt2Id] = ant2Id;
+ }
+ Int ddId = itsIds.dataDescId(which);
+ if (ddId >= 0) {
+ itsTabRows[itsDDId].get(ddId);
+ itsRowNumbers[itsDDId] = ddId;
+ }
+ Int obsId = itsIds.observationId(which);
+ if (obsId >= 0) {
+ itsTabRows[itsObsId].get(obsId);
+ itsRowNumbers[itsObsId] = obsId;
+ }
+ Int polId = itsIds.polarizationId(which);
+ if (polId >= 0) {
+ itsTabRows[itsPolId].get(polId);
+ itsRowNumbers[itsPolId] = polId;
+ }
+ Int spwId = itsIds.spectralWindowId(which);
+ if (spwId >= 0) {
+ itsTabRows[itsSpwId].get(spwId);
+ itsRowNumbers[itsSpwId] = spwId;
+ }
+ Int fieldId = itsIds.fieldId(which);
+ if (fieldId >= 0) {
+ itsTabRows[itsFieldId].get(fieldId);
+ itsRowNumbers[itsFieldId] = fieldId;
+ }
+ Int procId = itsIds.processorId(which);
+ if (procId >= 0) {
+ itsTabRows[itsProcId].get(procId);
+ itsRowNumbers[itsProcId] = procId;
+ }
+ Int stateId = itsIds.stateId(which);
+ if (stateId >= 0) {
+ itsTabRows[itsStateId].get(stateId);
+ itsRowNumbers[itsStateId] = stateId;
+ }
+
+ // and the ones with specific indexes
+ // these all need the time and interval
+ const MEpoch time = itsMSCols.timeMeas()(which);
+ const Quantity interval = itsMSCols.intervalQuant()(which);
+ Double stime = time.getValue().getTime().getValue(itsSecUnit);
+ Double sint = interval.getValue(itsSecUnit);
+
+ // DOPPLER - optional
+ Bool found;
+ if (itsDopplerId >= 0) {
+ itsDopplerIndex.dopplerId() = itsIds.dopplerId(which);
+ itsDopplerIndex.sourceId() = itsIds.sourceId(which);
+ // doppler does not use time or interval as keys
+ Int dopRow = itsDopplerIndex.getNearestRow(found);
+ if (found) {
+ itsTabRows[itsDopplerId].get(dopRow);
+ itsRowNumbers[itsDopplerId] = dopRow;
+ }
+ }
+
+ // FEED1, with ANTENNA1
+ itsFeed1Index.antennaId() = ant1Id;
+ Int feed1 = itsMSCols.feed1()(which);
+ Int feed2 = itsMSCols.feed2()(which);
+ itsFeed1Index.feedId() = feed1;
+ itsFeed1Index.spectralWindowId() = spwId;
+ itsFeed1Index.time() = stime;
+ itsFeed1Index.interval() = sint;
+ Int feedRow = itsFeed1Index.getNearestRow(found);
+ if (found) {
+ itsTabRows[itsFeed1Id].get(feedRow);
+ itsRowNumbers[itsFeed1Id] = feedRow;
+ }
+ // can this just be reused
+ if (ant1Id != ant2Id || feed1 != feed2) {
+ itsFeed2Index.antennaId() = ant2Id;
+ itsFeed2Index.feedId() = feed2;
+ itsFeed2Index.spectralWindowId() = spwId;
+ itsFeed2Index.time() = stime;
+ itsFeed2Index.interval() = sint;
+ feedRow = itsFeed2Index.getNearestRow(found);
+ }
+ if (found) {
+ itsTabRows[itsFeed2Id].get(feedRow);
+ itsRowNumbers[itsFeed2Id] = feedRow;
+ }
+
+ // FLAG_CMD - handled generically in the itsIndexes block
+
+ // FREQ_OFFSET - optional
+ if (itsFreqOffsetId >= 0) {
+ itsFreqOffIndex.antenna1Id() = ant1Id;
+ itsFreqOffIndex.antenna2Id() = ant2Id;
+ // I don't really understand why there is only one FEED_ID here
+ itsFreqOffIndex.feedId() = feed1;
+ itsFreqOffIndex.time() = stime;
+ itsFreqOffIndex.interval() = sint;
+ Int foffRow = itsFreqOffIndex.getNearestRow(found);
+ if (found) {
+ itsTabRows[itsFreqOffsetId].get(foffRow);
+ itsRowNumbers[itsFreqOffsetId] = foffRow;
+ }
+ }
+
+ // POINTING1 - required, this depends on ANTENNA1
+ itsPointing1Index.antennaId() = ant1Id;
+ itsPointing1Index.time() = stime;
+ itsPointing1Index.interval() = sint;
+ Int pointRow = itsPointing1Index.getNearestRow(found);
+ if (found) {
+ itsTabRows[itsPointing1Id].get(pointRow);
+ itsRowNumbers[itsPointing1Id] = pointRow;
+ }
+ // can we reuse this for POINTING2?
+ if (ant1Id != ant2Id) {
+ itsPointing2Index.antennaId() = ant2Id;
+ itsPointing2Index.time() = stime;
+ itsPointing2Index.interval() = sint;
+ pointRow = itsPointing2Index.getNearestRow(found);
+ }
+ if (found) {
+ itsTabRows[itsPointing2Id].get(pointRow);
+ itsRowNumbers[itsPointing2Id] = pointRow;
+ }
+
+ // SOURCE - optional
+ if (itsSourceId >= 0) {
+ itsSourceIndex.sourceId() = itsIds.sourceId(which);
+ itsSourceIndex.spectralWindowId() = itsIds.spectralWindowId(which);
+ itsSourceIndex.time() = stime;
+ itsSourceIndex.interval() = sint;
+ Int sourceRow = itsSourceIndex.getNearestRow(found);
+ if (found) {
+ itsTabRows[itsSourceId].get(sourceRow);
+ itsRowNumbers[itsSourceId] = sourceRow;
+ }
+ }
+
+ // SYSCAL1 - optional
+ if (itsSyscal1Id >= 0) {
+ itsSyscal1Index.antennaId() = ant1Id;
+ itsSyscal1Index.feedId() = feed1;
+ itsSyscal1Index.spectralWindowId() = spwId;
+ itsSyscal1Index.time() = stime;
+ itsSyscal1Index.interval() = sint;
+ Int syscalRow = itsSyscal1Index.getNearestRow(found);
+ if (found) {
+ itsTabRows[itsSyscal1Id].get(syscalRow);
+ itsRowNumbers[itsSyscal1Id] = syscalRow;
+ }
+
+ // if SYSCAL1 exists, SYSCAL2 must exist and SYSCAL2 can't
+ // exist unless SYSCAL1 exists
+ // Can we re-use that row
+ if (ant1Id != ant2Id || feed1 != feed2) {
+ itsSyscal2Index.antennaId() = ant2Id;
+ itsSyscal2Index.feedId() = feed2;
+ itsSyscal2Index.spectralWindowId() = spwId;
+ itsSyscal2Index.time() = stime;
+ itsSyscal2Index.interval() = sint;
+ syscalRow = itsSyscal2Index.getNearestRow(found);
+ }
+ if (found) {
+ itsTabRows[itsSyscal2Id].get(syscalRow);
+ itsRowNumbers[itsSyscal2Id] = syscalRow;
+ }
+ }
+
+ // WEATHER1- optional
+ if (itsWeather1Id >= 0) {
+ itsWeather1Index.antennaId() = ant1Id;
+ itsWeather1Index.time() = stime;
+ itsWeather1Index.interval() = sint;
+ Int weatherRow = itsWeather1Index.getNearestRow(found);
+ if (found) {
+ itsTabRows[itsWeather1Id].get(weatherRow);
+ itsRowNumbers[itsWeather1Id] = weatherRow;
+ }
+
+ // if WEATHER1 exists, WEATHER2 must exist and WEATHER2 can't
+ // exist unless WEATHER1 exists
+ // Can we re-use that row
+ if (ant1Id != ant2Id) {
+ itsWeather2Index.antennaId() = ant2Id;
+ itsWeather2Index.time() = stime;
+ itsWeather2Index.interval() = sint;
+ weatherRow = itsWeather2Index.getNearestRow(found);
+ }
+ if (found) {
+ itsTabRows[itsWeather2Id].get(weatherRow);
+ itsRowNumbers[itsWeather2Id] = weatherRow;
+ }
+ }
+
+ // any think in itsIndexes
+ for (uInt i=0;i<itsIndexes.nelements();i++) {
+ if (!itsIndexes[i].isNull()) {
+ itsIndexes[i].time() = stime;
+ itsIndexes[i].interval() = sint;
+ Int thisRow = itsIndexes[i].getNearestRow(found);
+ if (found) {
+ itsTabRows[i].get(thisRow);
+ itsRowNumbers[i] = thisRow;
+ }
+ }
+ }
+}
+
+const RecordInterface &MSReader::tableRow(const String &name) const
+{
+ if (!itsTabId.isDefined(name)) return emptyRecord;
+ Int tabId = itsTabId(name);
+ return itsTabRows[tabId].record();
+}
+
+Int MSReader::rowNumber(const String &name) const
+{
+ if (!itsTabId.isDefined(name)) return -1;
+ Int tabId = itsTabId(name);
+ return itsRowNumbers[tabId];
+}
+
+// Return a reference to the named subtable
+const Table &MSReader::table(const String &name) const
+{
+ if (!itsTabId.isDefined(name)) return emptyTable;
+ Int tabId = itsTabId(name);
+ return itsTabRows[tabId].table();
+}
+
+} //# NAMESPACE CASACORE - END
+
=======================================
--- /dev/null
+++ /branches/nov14/ms/MSOper/MSReader.h Wed Mar 25 14:33:54 2015 UTC
@@ -0,0 +1,151 @@
+//# MSReader.h: read from a MS, coordinating all of the subtables
+//# Copyright (C) 2000
+//# Associated Universities, Inc. Washington DC, USA.
+//#
+//# This library is free software; you can redistribute it and/or modify it
+//# under the terms of the GNU Library General Public License as published
by
+//# the Free Software Foundation; either version 2 of the License, or (at
your
+//# option) any later version.
+//#
+//# This library is distributed in the hope that it will be useful, but
WITHOUT
+//# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+//# FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
+//# License for more details.
+//#
+//# You should have received a copy of the GNU Library General Public
License
+//# along with this library; if not, write to the Free Software Foundation,
+//# Inc., 675 Massachusetts Ave, Cambridge, MA 02139, USA.
+//#
+//# Correspondence concerning AIPS++ should be addressed as follows:
+//# Internet email:
aips2-...@nrao.edu.
+//# Postal address: AIPS++ Project Office
+//# National Radio Astronomy Observatory
+//# 520 Edgemont Road
+//# Charlottesville, VA 22903-2475 USA
+//#
+//#
+//# $Id$
+
+#ifndef MS_MSREADER_H
+#define MS_MSREADER_H
+
+#include <casacore/casa/aips.h>
+#include <casacore/casa/Arrays/Vector.h>
+#include <casacore/casa/Containers/Block.h>
+#include <casacore/casa/Containers/Record.h>
+#include <casacore/casa/Containers/SimOrdMap.h>
+#include <casacore/ms/MeasurementSets/MeasurementSet.h>
+#include <casacore/ms/MeasurementSets/MSColumns.h>
+#include <casacore/ms/MSSel/MSDopplerIndex.h>
+#include <casacore/ms/MSSel/MSFeedIndex.h>
+#include <casacore/ms/MSSel/MSFreqOffIndex.h>
+#include <casacore/ms/MSSel/MSPointingIndex.h>
+#include <casacore/ms/MSSel/MSSourceIndex.h>
+#include <casacore/ms/MSSel/MSSysCalIndex.h>
+#include <casacore/ms/MSSel/MSTableIndex.h>
+#include <casacore/ms/MSSel/MSWeatherIndex.h>
+#include <casacore/ms/MSOper/MSValidIds.h>
+#include <casacore/tables/Tables/TableRow.h>
+#include <casacore/casa/Quanta/Unit.h>
+#include <casacore/casa/BasicSL/String.h>
+
+namespace casacore { //# NAMESPACE CASACORE - BEGIN
+
+// <summary>
+// Read from an MS, coordinating all of the subtables in the process
+// </summary>
+
+// <use visibility=local>
+
+// <reviewed reviewer="" date="yyyy/mm/dd" tests="" demos="">
+// </reviewed>
+class MSReader
+{
+public:
+ // Attach to the indicated MeasurementSet
+ MSReader(const MeasurementSet &ms);
+
+ ~MSReader() {;}
+
+ // Go to the indicated row in the MAIN table of the MS and point
+ // at all of the appropriate rows in each of the subtables as
+ // a result of going to this row.
+ void gotoRow(uInt which);
+
+ const Vector<String> &tables() const {return itsTableNames;}
+
+ // Return the current row in the named table. Use rowNumber to
+ // check to see that the most recent gotoRow actually found a matching
+ // row.
+ const RecordInterface &tableRow(const String &name) const;
+
+ // Return the current row number in the named table. This returns
+ // -1 if that table has no row as a result of the most recent gotoRow.
+ Int rowNumber(const String &name) const;
+
+ // Return a reference to the MS
+ const MeasurementSet &ms() const {return itsMS;}
+
+ // Return a reference to the named subtable
+ const Table &table(const String &name) const;
+
+ // this isn't what we need, right now just return an empty record
+ const Record &units(const String &) const { return emptyRecord;}
+private:
+ MeasurementSet itsMS;
+ ROMSColumns itsMSCols;
+
+ // This possibly saves some time, Units of seconds
+ Unit itsSecUnit;
+
+ MSValidIds itsIds;
+
+ // this maps table name to an index used throughout this class
+ SimpleOrderedMap<String, Int> itsTabId;
+
+ // the indexes for the NS subtables
+ Block<MSTableIndex> itsIndexes;
+
+ // specific indexes
+ MSDopplerIndex itsDopplerIndex;
+ MSFeedIndex itsFeed1Index;
+ MSFeedIndex itsFeed2Index;
+ MSFreqOffIndex itsFreqOffIndex;
+ MSPointingIndex itsPointing1Index;
+ MSPointingIndex itsPointing2Index;
+ MSSourceIndex itsSourceIndex;
+ MSSysCalIndex itsSyscal1Index;
+ MSSysCalIndex itsSyscal2Index;
+ MSWeatherIndex itsWeather1Index;
+ MSWeatherIndex itsWeather2Index;
+
+ // table IDs for the standard tables
+ Int itsMainId, itsAnt1Id, itsAnt2Id, itsDDId, itsDopplerId,
itsFeed1Id, itsFeed2Id, itsFieldId,
+ itsFlagCmdId, itsFreqOffsetId, itsObsId, itsPointing1Id, itsPointing2Id,
itsPolId, itsProcId,
+ itsSourceId, itsSpwId, itsStateId, itsSyscal1Id, itsSyscal2Id,
itsWeather1Id, itsWeather2Id;
+ // the table rows
+ Block<ROTableRow> itsTabRows;
+
+ // What row number for each table is the most recent gotoRow call.
Set to
+ // -1 if there was no matching row as a result of that call.
+ Block<Int> itsRowNumbers;
+
+ // this empty record is returned by tableRow when the name argument
does not exist
+ Record emptyRecord;
+
+ // this empty table is returned by table when the name argument does
not exist
+ Table emptyTable;
+
+ Vector<String> itsTableNames;
+
+ // undefined and unavailable
+ MSReader();
+ MSReader(const MSReader &);
+ MSReader& operator=(const MSReader &);
+};
+
+
+} //# NAMESPACE CASACORE - END
+
+#endif
+
=======================================
--- /dev/null
+++ /branches/nov14/ms/MSOper/MSSummary.cc Wed Mar 25 14:33:54 2015 UTC
@@ -0,0 +1,2080 @@
+//# MSSummary.cc: Helper class for applications listing a MeasurementSet
+//# Copyright (C) 1998,1999,2000,2001,2002,2003
+//# Associated Universities, Inc. Washington DC, USA.
+//#
+//# This library is free software; you can redistribute it and/or modify it
+//# under the terms of the GNU Library General Public License as published
by
+//# the Free Software Foundation; either version 2 of the License, or (at
your
+//# option) any later version.
+//#
+//# This library is distributed in the hope that it will be useful, but
WITHOUT
+//# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+//# FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
+//# License for more details.
+//#
+//# You should have received a copy of the GNU Library General Public
License
+//# along with this library; if not, write to the Free Software Foundation,
+//# Inc., 675 Massachusetts Ave, Cambridge, MA 02139, USA.
+//#
+//# Correspondence concerning AIPS++ should be addressed as follows:
+//# Internet email:
aips2-...@nrao.edu.
+//# Postal address: AIPS++ Project Office
+//# National Radio Astronomy Observatory
+//# 520 Edgemont Road
+//# Charlottesville, VA 22903-2475 USA
+//#
+//# $Id$
+//#
+
+#include <casacore/casa/aips.h>
+#include <casacore/casa/Arrays.h>
+#include <casacore/casa/Arrays/ArrayMath.h>
+#include <casacore/casa/Arrays/ArrayLogical.h>
+#include <casacore/casa/BasicSL/Constants.h>
+#include <casacore/casa/Arrays/IPosition.h>
+#include <casacore/casa/Arrays/IPosition.h>
+#include <casacore/casa/Containers/Record.h>
+#include <casacore/casa/Logging/LogIO.h>
+#include <casacore/casa/Quanta/Unit.h>
+#include <casacore/measures/Measures/MDirection.h>
+#include <casacore/casa/Quanta.h>
+#include <casacore/casa/Quanta/MVAngle.h>
+#include <casacore/casa/Quanta/MVTime.h>
+#include <casacore/measures/Measures/Stokes.h>
+#include <casacore/tables/Tables/TableRecord.h>
+#include <casacore/tables/Tables/RefRows.h>
+#include <casacore/casa/Utilities/GenSort.h>
+#include <casacore/casa/BasicSL/STLIO.h>
+#include <casacore/tables/Tables/Table.h>
+#include <casacore/tables/Tables/TableIter.h>
+#include <casacore/tables/Tables/TableVector.h>
+#include <casacore/ms/MeasurementSets.h>
+#include <casacore/ms/MeasurementSets/MeasurementSet.h>
+#include <casacore/ms/MeasurementSets/MSColumns.h>
+#include <casacore/ms/MSOper/MSKeys.h>
+#include <casacore/ms/MSOper/MSMetaData.h>
+#include <casacore/ms/MSOper/MSSummary.h>
+#include <casacore/ms/MeasurementSets/MSRange.h>
+#include <casacore/ms/MSSel/MSSelector.h>
+#include <casacore/ms/MSSel/MSSelection.h>
+
+#include <casacore/casa/iomanip.h>
+#include <casacore/casa/iostream.h>
+
+namespace casacore { //# NAMESPACE CASACORE - BEGIN
+
+//
+// Constructor assigns pointer. If MS goes out of scope you
+// will get rubbish. Also sets string to separate subtable output.
+//
+MSSummary::MSSummary (const MeasurementSet& ms)
+: pMS(&ms), _msmd(new MSMetaData(&ms, 50.0)),
+ dashlin1(replicate("-",80)),
+ dashlin2(replicate("=",80)),
+ _listUnflaggedRowCount(False),
+ _cacheSizeMB(50)
+{}
+
+MSSummary::MSSummary (const MeasurementSet* ms)
+: pMS(ms), _msmd(new MSMetaData(ms, 50.0)),
+ dashlin1(replicate("-",80)),
+ dashlin2(replicate("=",80)),
+ _listUnflaggedRowCount(False),
+ _cacheSizeMB(50)
+{}
+
+MSSummary::MSSummary (const MeasurementSet* ms, const String msname)
+: pMS(ms), _msmd(new MSMetaData(ms, 50)),
+ dashlin1(replicate("-",80)),
+ dashlin2(replicate("=",80)),
+ msname_p(msname),
+ _listUnflaggedRowCount(False),
+ _cacheSizeMB(50)
+{}
+//
+// Destructor does nothing
+//
+MSSummary::~MSSummary ()
+{}
+
+
+//
+// Retrieve number of rows
+//
+Int MSSummary::nrow () const
+{
+ return _msmd->nRows();
+}
+
+
+//
+// Get ms name
+//
+String MSSummary::name () const
+{
+ if (! msname_p.empty())
+ return msname_p;
+
+ return pMS->tableName();
+}
+
+
+//
+// Reassign pointer.
+//
+Bool MSSummary::setMS (const MeasurementSet& ms)
+{
+ const MeasurementSet* pTemp;
+ pTemp = &ms;
+ if (pTemp == 0) {
+ return False;
+ } else {
+ pMS = pTemp;
+ _msmd.reset(new MSMetaData(&ms, _cacheSizeMB));
+ return True;
+ }
+}
+
+
+//
+// List information about an ms to the logger
+//
+void MSSummary::list (LogIO& os, Bool verbose, Bool oneBased) const
+{
+ Record dummy;
+ list(os, dummy, verbose, False, oneBased);
+}
+
+void MSSummary::list (LogIO& os, Record& outRec, Bool verbose,
+ Bool fillRecord, Bool oneBased) const
+{
+ // List a title for the Summary
+ listTitle (os);
+
+ // List the main table as well as the subtables in a useful order and
format
+ listWhere (os,verbose);
+ listWhat (os,outRec, verbose, fillRecord);
+ listHow (os,verbose, oneBased);
+
+ // These aren't really useful (yet?)
+ // listSource (os,verbose);
+ // listSysCal (os,verbose);
+ // listWeather (os,verbose);
+
+ // List a summary of table sizes
+ // os << dashlin1 << endl << endl;
+ // listTables (os,verbose);
+ // os << dashlin2 << endl;
+
+ // Post it
+
os.post();
+
+}
+
+
+//
+// List a title for the Summary
+//
+void MSSummary::listTitle (LogIO& os) const
+{
+ // Version number of the MS definition
+ Float vers = 1.0;
+ if (pMS->keywordSet().isDefined("MS_VERSION")) {
+ vers = pMS->keywordSet().asFloat("MS_VERSION");
+ }
+
+ // List the MS name and version as the title of the Summary
+ os << LogIO::NORMAL;
+ os << dashlin2 << endl << " MeasurementSet Name: " <<
this->name()
+ << " MS Version " << vers << endl << dashlin2 << endl;
+}
+
+
+//
+// Convenient table groupings
+//
+void MSSummary::listWhere (LogIO& os, Bool verbose) const
+{
+ listObservation (os,verbose);
+}
+void MSSummary::listWhat (LogIO& os, Bool verbose) const
+{
+ Record dummy;
+ listWhat(os, dummy, verbose, False);
+
+}
+void MSSummary::listWhat (LogIO& os, Record& outRec, Bool verbose, Bool
fillRecord) const
+{
+ listMain (os,outRec, verbose, fillRecord);
+ listField (os,outRec, verbose, fillRecord);
+}
+
+
+void MSSummary::listHow (LogIO& os, Bool verbose, Bool oneBased) const
+{
+ // listSpectralWindow (os,verbose);
+ // listPolarization (os,verbose);
+ listSpectralAndPolInfo(os, verbose, oneBased);
+ listSource (os,verbose);
+ // listFeed (os,verbose, oneBased));
+ listAntenna (os,verbose);
+}
+
+
+//
+// SUBTABLES
+//
+void MSSummary::listMain (LogIO& os, Bool verbose) const
+{
+ Record dummy;
+ listMain(os, dummy, verbose, False);
+
+}
+
+// TESTING CAS-2751
+void MSSummary::listMain (LogIO& os, Record& outRec, Bool verbose,
+ Bool fillRecord) const
+{
+ if (nrow()<=0) {
+ os << "The MAIN table is empty: there are no data!!!" << endl <<
LogIO::POST;
+ return;
+ }
+ std::pair<Double, Double> timerange = _msmd->getTimeRange();
+ Double startTime = timerange.first;
+ Double stopTime = timerange.second;
+ Double exposTime = stopTime - startTime;
+ // Double exposTime = sum(msc.exposure().getColumn());
+ MVTime startMVT(startTime/86400.0), stopMVT(stopTime/86400.0);
+
+ ROMSMainColumns msmc(*pMS);
+ String
timeref=msmc.time().keywordSet().subRecord("MEASINFO").asString("Ref");
+
+ // Output info
+ os << "Data records: " << nrow() << " Total elapsed time = "
+ << exposTime << " seconds" << endl
+ << " Observed from " <<
MVTime(startTime/C::day).string(MVTime::DMY,7) //startMVT.string()
+ << " to " << MVTime(stopTime/C::day).string(MVTime::DMY,7) //
stopMVT.string()
+ << " (" << timeref << ")"
+ << endl << endl;
+ os << LogIO::POST;
+
+ if(fillRecord){
+ outRec.define("numrecords", nrow());
+ outRec.define("IntegrationTime", exposTime);
+ outRec.define("BeginTime", startTime/C::day);
+ outRec.define("EndTime", stopTime/C::day);
+ outRec.define("timeref", timeref);
+ }
+
+ // if (verbose) { // do "scan" listing
+
+ // Set up iteration over OBSID, ARRID, and SCAN_NUMBER:
+ // Block<String> mssortcols(3);
+ // mssortcols[0] = "OBSERVATION_ID";
+ // mssortcols[1] = "ARRAY_ID";
+ // mssortcols[2] = "SCAN_NUMBER";
+ // MSIter
msIter(const_cast<MeasurementSet&>(*pMS),mssortcols,0.0,False );
+
+ // for (msIter.origin(); msIter.more(); msIter++) {
+ // }
+
+
+ // the selected MS (all of it) as a Table tool:
+ // MS is accessed as a generic table here because
+ // the ms tool hard-wires iteration over SPWID, FLDID,
+ // and TIME and this is not desired in this application.
+ // It would be easier if the ms tool did not automatically
+ // iterate over any indices, or if there were an ms.table()
+ // function.
+ MSSelector mssel;
+ mssel.setMS(const_cast<MeasurementSet&>(*pMS));
+ mssel.initSelection(True);
+ Table mstab(mssel.selectedTable());
+
+ // Field names:
+ ROMSFieldColumns field(pMS->field());
+ Vector<String> fieldnames(
field.name().getColumn());
+ nVisPerField_.resize(fieldnames.nelements());
+ nVisPerField_=0;
+
+ // Observing Mode (State Table)
+ ROMSStateColumns state(pMS->state());
+ Vector<String> obsModes(state.obsMode().getColumn());
+
+ // Spw Ids
+ ROMSDataDescColumns dd(pMS->dataDescription());
+ Vector<Int> specwindids(dd.spectralWindowId().getColumn());
+
+ // Field widths for printing:
+ Int widthLead = 2;
+ Int widthScan = 4;
+ Int widthbtime = 22;
+ Int widthetime = 10;
+ Int widthFieldId = 5;
+ Int widthField = 20;
+ Int widthnrow = 10;
+ Int widthNUnflaggedRow = 13;
+ //Int widthInttim = 7;
+
+ // Set up iteration over OBSID and ARRID:
+ Block<String> icols(2);
+ icols[0] = "OBSERVATION_ID";
+ icols[1] = "ARRAY_ID";
+ TableIterator obsarriter(mstab,icols);
+ //Limiting record length
+ Int recLength=0;
+ const Int maxRecLength=10000; //limiting for speed and size sake
+ // Iterate:
+ while (!obsarriter.pastEnd()) {
+
+ // Table containing this iteration:
+ Table obsarrtab(obsarriter.table());
+ // Extract (zero-based) OBSID and ARRID for this iteration:
+ ROTableVector<Int> obsidcol(obsarrtab,"OBSERVATION_ID");
+ Int obsid(obsidcol(0));
+ ROTableVector<Int> arridcol(obsarrtab,"ARRAY_ID");
+ Int arrid(arridcol(0));
+
+ if (verbose) {
+ // Report OBSID and ARRID, and header for listing:
+ os << endl << " ObservationID = " << obsid;
+ os << " ArrayID = " << arrid << endl;
+ String datetime=" Date Timerange ";
+ datetime.replace(24,1,"(");
+ datetime.replace(25,timeref.length(),timeref);
+ datetime.replace(25+timeref.length(),1,")");
+ os << datetime;
+ os << "Scan FldId FieldName "
+ << " nRows ";
+ if (_listUnflaggedRowCount) {
+ os << "nUnflRows ";
+ }
+ os << "SpwIds Average Interval(s) ScanIntent"
<< endl;
+ }
+ /* CAS-2751. Sort the table by scan then field (not timestamp)
+ * so that scans are not listed for every different DDID
+ */
+ // Setup iteration over scan and field within this iteration:
+ Block<String> jcols(2);
+ jcols[0] = "SCAN_NUMBER";
+ jcols[1] = "FIELD_ID";
+ TableIterator stiter(obsarrtab,jcols);
+
+ // Vars for keeping track of time, fields, and ddis
+ Int lastscan(-1);
+ Vector<Int> lastfldids;
+ Vector<Int> lastddids;
+ Vector<Int> laststids;
+ Vector<Int> fldids(1,0);
+ Vector<Int> ddids(1,0);
+ Vector<Int> stids(1,0); // State IDs
+ //Vector<Int> spwids;
+ Int nfld(1);
+ Int nddi(1);
+ Int nst(1);
+ Double btime(0.0), etime(0.0);
+ Double lastday(0.0), day(0.0);
+ Bool firsttime(True);
+ Int thisnrow(0);
+ Double meanIntTim(0.0);
+
+ os.output().precision(3);
+ Int subsetscan=0;
+ // Iterate over scans/fields:
+ std::set<uInt> spw;
+ ScanKey lastScanKey;
+ while (!stiter.pastEnd()) {
+ // ms table at this scan
+ Table t(stiter.table());
+ Int nrow=t.nrow();
+
+ // relevant columns
+ ROTableVector<Double> timecol(t,"TIME");
+ ROTableVector<Double> inttim(t,"EXPOSURE");
+ ROTableVector<Int> scncol(t,"SCAN_NUMBER");
+ ROTableVector<Int> fldcol(t,"FIELD_ID");
+ ROTableVector<Int> ddicol(t,"DATA_DESC_ID");
+ ROTableVector<Int> stidcol(t,"STATE_ID");
+
+ lastScanKey.obsID = obsid;
+ lastScanKey.arrayID = arrid;
+ lastScanKey.scan = lastscan;
+
+ // this timestamp
+ //Double thistime(timecol(0));
+
+ // this scan_number
+ Int thisscan(scncol(0));
+
+ // First field and ddi at this timestamp:
+ fldids.resize(1,False);
+ fldids(0)=fldcol(0);
+ nfld=1;
+ ddids.resize(1,False);
+ ddids(0)=ddicol(0);
+ nddi=1;
+
+ stids.resize(1, False);
+ stids(0) = stidcol(0);
+ nst=1;
+ nVisPerField_(fldids(0))+=nrow;
+
+ // fill field and ddi lists for this scan
+ for (Int i=1; i < nrow; i++) {
+ if ( !anyEQ(fldids,fldcol(i)) ) {
+ nfld++;
+ fldids.resize(nfld,True);
+ fldids(nfld-1)=fldcol(i);
+ }
+
+ if ( !anyEQ(ddids,ddicol(i)) ) {
+ nddi++;
+ ddids.resize(nddi,True);
+ ddids(nddi-1)=ddicol(i);
+ }
+
+ if ( !anyEQ(stids,stidcol(i)) ) {
+ nst++;
+ stids.resize(nst,True);
+ stids(nst-1)=stidcol(i);
+ }
+
+ }
+
+ // If not first timestamp, check if scan changed, etc.
+ ScanKey thisScanKey = lastScanKey;
+ thisScanKey.scan = thisscan;
+ if (!firsttime) {
+ // Has state changed?
+ Bool samefld;
+ samefld=fldids.conform(lastfldids) && !anyNE(fldids,lastfldids);
+ Bool sameddi;
+ sameddi=ddids.conform(lastddids) && !anyNE(ddids,lastddids);
+
+ Bool samest;
+ samest=stids.conform(laststids) && !anyNE(stids,laststids);
+
+ Bool samescan;
+ samescan=(thisscan==lastscan);
+
+ samescan = samescan && samefld && sameddi && samest;
+ // samescan = samescan && samefld;
+
+ // If state changed, then print out last scan's info
+ if (!samescan) {
+ // cout << "thisscan " << thisscan << "lastscan " << lastscan
+ // << " fldids " << fldids << " lastfldids " << lastfldids
+ // << " ddids " << ddids << " lastddids " << lastddids
+ // << " samescan " << (thisscan==lastscan) << " samefld " <<
samefld << " sameddi " << sameddi
+ // << " meanIntTim " << meanIntTim << " thisnrow " << thisnrow
<< " inttim.makeVector().size() "
+ // << inttim.makeVector().size() << " meanIntTim/thisnrow " <<
meanIntTim/thisnrow << endl;
+ if (thisnrow>0){
+ meanIntTim/=thisnrow;
+ }
+ else {
+ meanIntTim=0.0;
+ }
+ // this MJD
+ day=floor(MVTime(btime/C::day).day());
+ spw = _msmd->getSpwsForScan(lastScanKey);
+ String name=fieldnames(lastfldids(0));
+ if (verbose) {
+ // Print out last scan's times, fields, ddis
+ os.output().setf(ios::right, ios::adjustfield);
+ os.output().width(widthLead); os << " ";
+ os.output().width(widthbtime);
+ if (day!=lastday) { // print date
+ os << MVTime(btime/C::day).string(MVTime::DMY,7);
+ } else { // omit date
+ os << MVTime(btime/C::day).string(MVTime::TIME,7);
+ }
+ os.output().width(3); os << " - ";
+ os.output().width(widthetime);
+ os << MVTime(etime/C::day).string(MVTime::TIME,7);
+ os.output().width(widthLead); os << " ";
+ os.output().setf(ios::right, ios::adjustfield);
+ os.output().width(widthScan); os << lastscan;
+ os.output().width(widthLead); os << " ";
+ os.output().setf(ios::right, ios::adjustfield);
+ os.output().width(widthFieldId); os << lastfldids(0) << " ";
+ os.output().setf(ios::left, ios::adjustfield);
+ if (name.length()>20) name.replace(19,1,'*');
+ os.output().width(widthField); os <<
name.at(0,20);
+ //os.output().width(widthnrow); os << thisnrow;
+ os.output().width(widthnrow);
+ os.output().setf(ios::right, ios::adjustfield);
+ os << _msmd->nRows(MSMetaData::BOTH, arrid, obsid, lastscan,
lastfldids(0));
+ if
(_listUnflaggedRowCount) {
+ ostringstream xx;
+ xx << std::fixed <<
setprecision(2)
+ <<
_msmd->nUnflaggedRows(
+ MSMetaData::BOTH, arrid, obsid, lastscan, lastfldids(0)
+ );
+
os.output().width(widthNUnflaggedRow);
+ os << xx.str();
+ }
+ //os.output().width(widthInttim); os << meanIntTim;
+ os.output().width(widthLead); os << " ";
+
+ os << spw;
+ /*
+ if (spw.size() <= 9) {
+ os.output().width(28 - (3*spw.size())); os << " ";
+ }
+ */
+ os.output().width(widthLead); os << " ";
+
+ std::map<uInt, Double> intToScanMap =
_msmd->getAverageIntervalsForScan(lastScanKey);
+ os << "[";
+ for (
+ std::set<uInt>::const_iterator iter=spw.begin();
+ iter!=spw.end(); iter++
+ ) {
+ if (iter!=spw.begin()) {
+ os << ", ";
+ }
+ os << intToScanMap[*iter];
+ }
+ os << "] ";
+ // The Obsmode column can be empty only report them if it is not
+ //String obsMode = "";
+ //if (obsModes.size() > (unsigned int) 0) {
+ // obsMode=obsModes(laststids(0));
+ //}
+ //os << obsMode;
+
+ //os << endl;
+ std::set<String> intents = _msmd->getIntentsForScan(lastScanKey);
+ if (intents.size() > 0) {
+ os << intents;
+ }
+ os << endl;
+ }
+ if(fillRecord && (recLength < maxRecLength)) {
+ Record scanRecord;
+ Record subScanRecord;
+ String scanrecid=String("scan_")+String::toString(lastscan);
+ if(outRec.isDefined(scanrecid)){
+ scanRecord=outRec.asrwRecord(scanrecid);
+ outRec.removeField(scanrecid);
+ }
+
+ subScanRecord.define("BeginTime", btime/C::day);
+ subScanRecord.define("EndTime", etime/C::day);
+ subScanRecord.define("scanId", lastscan);
+ subScanRecord.define("FieldId", lastfldids(0));
+ subScanRecord.define("FieldName", name);
+ subScanRecord.define("StateId", laststids(0));
+ subScanRecord.define("nRow", thisnrow);
+ subScanRecord.define("IntegrationTime", meanIntTim);
+ subScanRecord.define("SpwIds", Vector<Int>(spw.begin(), spw.size(),
0));
+ scanRecord.defineRecord(String::toString(subsetscan), subScanRecord);
+ if(!outRec.isDefined(scanrecid)){
+ outRec.defineRecord(scanrecid, scanRecord);
+ }
+ if(lastscan == thisscan){
+ ++subsetscan;
+ }
+ else{
+ subsetscan=0;
+ }
+ }
+ btime = _msmd->getTimeRangeForScan(thisScanKey).first;
+ // next last day is this day
+ lastday=day;
+
+ thisnrow=0;
+ meanIntTim=0.;
+ ++recLength;
+ }
+ // etime=thistime;
+ //etime=timecol(nrow-1); //CAS-2751
+ etime = _msmd->getTimeRangeForScan(thisScanKey).second;
+ }
+ else {
+ std::pair<Double, Double> timeRange =
_msmd->getTimeRangeForScan(thisScanKey);
+ // initialize btime and etime
+ //btime=thistime;
+ btime = timeRange.first;
+ // etime=thistime;
+ //etime=timecol(nrow-1); //CAS-2751
+ etime = timeRange.second;
+ // no longer first time thru
+ firsttime=False;
+ }
+
+ thisnrow+=nrow;
+
+ meanIntTim+=sum(inttim.makeVector());
+
+ // for comparison at next timestamp
+ lastfldids.assign(fldids);
+ lastddids.assign(ddids);
+ laststids.assign(stids);
+ lastscan=thisscan;
+
+ // push iteration
+ stiter.next();
+ } // end of time iteration
+
+ meanIntTim = thisnrow > 0 ? meanIntTim/thisnrow : 0;
+ /*
+ if
+ meanIntTim/=thisnrow;
+ else
+ meanIntTim=0.0;
+ */
+ // this MJD
+ day=floor(MVTime(btime/C::day).day());
+ lastScanKey.obsID = obsid;
+ lastScanKey.arrayID = arrid;
+ lastScanKey.scan = lastscan;
+ spw = _msmd->getSpwsForScan(lastScanKey);
+ String name=fieldnames(lastfldids(0));
+ if (verbose) {
+ // Print out final scan's times, fields, ddis
+ os.output().setf(ios::right, ios::adjustfield);
+ os.output().width(widthLead); os << " ";
+ os.output().width(widthbtime);
+ if (day!=lastday) {
+ os << MVTime(btime/C::day).string(MVTime::DMY,7);
+ } else {
+ os << MVTime(btime/C::day).string(MVTime::TIME,7);
+ }
+ os.output().width(widthLead); os << " - ";
+ os.output().width(widthetime);
+ os << MVTime(etime/C::day).string(MVTime::TIME,7);
+ os.output().width(widthLead); os << " ";
+ os.output().setf(ios::right, ios::adjustfield);
+ os.output().width(widthScan); os << lastscan;
+ os.output().width(widthLead); os << " ";
+ os.output().setf(ios::right, ios::adjustfield);
+ os.output().width(widthFieldId); os << lastfldids(0) << " ";
+ os.output().setf(ios::left, ios::adjustfield);
+ if (name.length()>20) name.replace(19,1,'*');
+ os.output().width(widthField); os <<
name.at(0,20);
+ os.output().width(widthnrow);
+ os.output().setf(ios::right, ios::adjustfield);
+ os << _msmd->nRows(MSMetaData::BOTH, arrid, obsid, lastscan,
lastfldids(0));
+ if (_listUnflaggedRowCount) {
+ ostringstream xx;
+ xx << std::fixed << setprecision(2)
+ << _msmd->nUnflaggedRows(MSMetaData::BOTH,
arrid, obsid, lastscan, lastfldids(0));
+ os.output().width(widthNUnflaggedRow);
+ os << xx.str();
+ }
+// os.output().width(widthInttim); os << meanIntTim;
+ os.output().width(widthLead); os << " ";
+ showContainer (os.output(), spw, ", ", "[", "]");
+ os.output().width(widthLead); os << " ";
+
+ std::map<uInt, Double> intToScanMap =
_msmd->getAverageIntervalsForScan(lastScanKey);
+ os << "[";
+ for (
+ std::set<uInt>::const_iterator iter=spw.begin();
+ iter!=spw.end(); iter++
+ ) {
+ if (iter!=spw.begin()) {
+ os << ", ";
+ }
+ os << intToScanMap[*iter];
+ }
+ os << "] ";
+ // The Obsmode column can be empty only report them if it is not
+ //String obsMode = "";
+ //if (obsModes.size() > (unsigned int) 0) {
+ // obsMode=obsModes(laststids(0));
+ //}
+ //os << obsMode;
+ //os << endl;
+ set<String> intents = _msmd->getIntentsForScan(lastScanKey);
+ if (intents.size() > 0) {
+ os << intents;
+ }
+ os << endl;
+ }
+ if(fillRecord && (recLength < maxRecLength)){
+ Record scanRecord;
+ Record subScanRecord;
+ String scanrecid=String("scan_")+String::toString(lastscan);
+ if(outRec.isDefined(scanrecid)){
+ scanRecord=outRec.asrwRecord(scanrecid);
+ outRec.removeField(scanrecid);
+ }
+
+ subScanRecord.define("BeginTime", btime/C::day);
+ subScanRecord.define("EndTime", etime/C::day);
+ subScanRecord.define("scanId", lastscan);
+ subScanRecord.define("FieldId", lastfldids(0));
+ subScanRecord.define("FieldName", name);
+ subScanRecord.define("nRow", thisnrow);
+ subScanRecord.define("IntegrationTime", meanIntTim);
+ subScanRecord.define("SpwIds", Vector<Int>(spw.begin(), spw.size(), 0));
+ scanRecord.defineRecord(String::toString(subsetscan), subScanRecord);
+ if(!outRec.isDefined(scanrecid)){
+ outRec.defineRecord(scanrecid, scanRecord);
+ }
+ subsetscan=0;
+ ++recLength;
+ }
+
+ // post to logger
+ if (verbose) os << LogIO::POST;
+
+ // push OBS/ARR iteration
+ obsarriter.next();
+ } // end of OBS/ARR iteration
+ if (verbose){
+ os << " (nRows = Total number of rows per scan) " << endl;
+ os << LogIO::POST;
+ }
+
+ // } // end of verbose section
+
+
+
+ os << LogIO::POST;
+}
+
+
+void MSSummary::getScanSummary (Record& outRec) const
+{
+
+ if (nrow()<=0) {
+ return;
+ }
+
+ // Make objects
+ ROMSColumns msc(*pMS);
+ Double startTime, stopTime;
+ minMax(startTime, stopTime, msc.time().getColumn());
+
+ MVTime startMVT(startTime/86400.0), stopMVT(stopTime/86400.0);
+
+ ROMSMainColumns msmc(*pMS);
+ String
timeref=msmc.time().keywordSet().subRecord("MEASINFO").asString("Ref");
+ //outRec.define("numrecords", nrow());
+ //outRec.define("IntegrationTime", exposTime);
+ //outRec.define("BeginTime", startTime/C::day);
+ //outRec.define("EndTime", stopTime/C::day);
+ //outRec.define("timeref", timeref);
+
+
+ // the selected MS (all of it) as a Table tool:
+ // MS is accessed as a generic table here because
+ // the ms tool hard-wires iteration over SPWID, FLDID,
+ // and TIME and this is not desired in this application.
+ // It would be easier if the ms tool did not automatically
+ // iterate over any indices, or if there were an ms.table()
+ // function.
+ MSSelector mssel;
+ mssel.setMS(const_cast<MeasurementSet&>(*pMS));
+ mssel.initSelection(True);
+ Table mstab(mssel.selectedTable());
+
+ // Field names:
+ ROMSFieldColumns field(pMS->field());
+ Vector<String> fieldnames(
field.name().getColumn());
+ nVisPerField_.resize(fieldnames.nelements());
+ nVisPerField_=0;
+
+ // Spw Ids
+ ROMSDataDescColumns dd(pMS->dataDescription());
+ Vector<Int> specwindids(dd.spectralWindowId().getColumn());
+
+ // Set up iteration over OBSID and ARRID:
+ Block<String> icols(2);
+ icols[0] = "OBSERVATION_ID";
+ icols[1] = "ARRAY_ID";
+ TableIterator obsarriter(mstab,icols);
+ //Limiting record length
+ Int recLength=0;
+ // Iterate:
+ while (!obsarriter.pastEnd()) {
+
+ // Table containing this iteration:
+ Table obsarrtab(obsarriter.table());
+
+ // Extract (zero-based) OBSID and ARRID for this iteration:
+ ROTableVector<Int> obsidcol(obsarrtab,"OBSERVATION_ID");
+ ROTableVector<Int> arridcol(obsarrtab,"ARRAY_ID");
+
+ // Report OBSID and ARRID, and header for listing:
+ // os << endl << " ObservationID = " << obsid;
+ // os << " ArrayID = " << arrid << endl;
+ String datetime=" Date Timerange ";
+ datetime.replace(24,1,"(");
+ datetime.replace(25,timeref.length(),timeref);
+ datetime.replace(25+timeref.length(),1,")");
+ // os << datetime;
+ // os << "Scan FldId FieldName nVis Int(s) SpwIds" << endl;
+
+ // Setup iteration over timestamps within this iteration:
+ Block<String> jcols(2);
+ jcols[0] = "SCAN_NUMBER";
+ jcols[1] = "TIME";
+ TableIterator stiter(obsarrtab,jcols);
+
+ // Vars for keeping track of time, fields, and ddis
+ Int lastscan(-1);
+ Vector<Int> lastfldids;
+ Vector<Int> lastddids;
+ Vector<Int> laststids;
+ Vector<Int> fldids(1,0);
+ Vector<Int> ddids(1,0);
+ Vector<Int> stids(1,0); // State IDs
+ Vector<Int> spwids;
+ Int nfld(1);
+ Int nddi(1);
+ Int nst(1);
+ Double btime(0.0), etime(0.0);
+ Bool firsttime(True);
+ Int thisnrow(0);
+ Double meanIntTim(0.0);
+
+
+ // os.output().precision(3);
+ Int subsetscan=0;
+ // Iterate over timestamps:
+ while (!stiter.pastEnd()) {
+
+ // ms table at this timestamp
+ Table t(stiter.table());
+ Int nrow=t.nrow();
+
+ // relevant columns
+ ROTableVector<Double> timecol(t,"TIME");
+ ROTableVector<Double> inttim(t,"EXPOSURE");
+ ROTableVector<Int> scncol(t,"SCAN_NUMBER");
+ ROTableVector<Int> fldcol(t,"FIELD_ID");
+ ROTableVector<Int> ddicol(t,"DATA_DESC_ID");
+ ROTableVector<Int> stidcol(t,"STATE_ID");
+
+ // this timestamp
+ Double thistime(timecol(0));
+
+ // this scan_number
+ Int thisscan(scncol(0));
+
+ // First field and ddi at this timestamp:
+ fldids.resize(1,False);
+ fldids(0)=fldcol(0);
+ nfld=1;
+ ddids.resize(1,False);
+ ddids(0)=ddicol(0);
+ nddi=1;
+
+ stids.resize(1, False);
+ stids(0) = stidcol(0);
+ nst=1;
+
+ nVisPerField_(fldids(0))+=nrow;
+
+ // fill field and ddi lists for this timestamp
+ for (Int i=1; i < nrow; i++) {
+ if ( !anyEQ(fldids,fldcol(i)) ) {
+ nfld++;
+ fldids.resize(nfld,True);
+ fldids(nfld-1)=fldcol(i);
+ }
+
+ if ( !anyEQ(ddids,ddicol(i)) ) {
+ nddi++;
+ ddids.resize(nddi,True);
+ ddids(nddi-1)=ddicol(i);
+ }
+
+ if ( !anyEQ(stids,stidcol(i)) ) {
+ nst++;
+ stids.resize(nst,True);
+ stids(nst-1)=stidcol(i);
+ }
+ }
+
+ // If not first timestamp, check if scan changed, etc.
+ if (!firsttime) {
+
+ // Has state changed?
+ Bool samefld;
+ samefld=fldids.conform(lastfldids) && !anyNE(fldids,lastfldids);
+
+ Bool sameddi;
+ sameddi=ddids.conform(lastddids) && !anyNE(ddids,lastddids);
+
+ Bool samest;
+ samest=stids.conform(laststids) && !anyNE(stids,laststids);
+
+ Bool samescan;
+ samescan=(thisscan==lastscan);
+
+ samescan = samescan && samefld && sameddi && samest;
+
+ // If state changed, then print out last scan's info
+ if (!samescan) {
+ if (thisnrow>0){
+ meanIntTim/=thisnrow;
+ }
+ else {
+ meanIntTim=0.0;
+ }
+
+ // Spws
+ spwids.resize(lastddids.nelements());
+ for (uInt iddi=0; iddi<spwids.nelements();++iddi)
+ spwids(iddi)=specwindids(lastddids(iddi));
+
+ Record scanRecord;
+ Record subScanRecord;
+ String scanrecid=String::toString(lastscan);
+ if(outRec.isDefined(scanrecid)){
+ scanRecord=outRec.asrwRecord(scanrecid);
+ outRec.removeField(scanrecid);
+ }
+
+ subScanRecord.define("BeginTime", btime/C::day);
+ subScanRecord.define("EndTime", etime/C::day);
+ subScanRecord.define("FieldId", lastfldids(0));
+ subScanRecord.define("StateId", laststids(0));
+ subScanRecord.define("nRow", thisnrow);
+ subScanRecord.define("IntegrationTime", meanIntTim);
+ subScanRecord.define("SpwIds", spwids);
+ subScanRecord.define("DDIds", lastddids);
+ scanRecord.defineRecord(String::toString(subsetscan), subScanRecord);
+ if(!outRec.isDefined(scanrecid)){
+ outRec.defineRecord(scanrecid, scanRecord);
+ }
+ if(lastscan == thisscan){
+ ++subsetscan;
+ }
+ else{
+ subsetscan=0;
+ }
+ //}
+
+ // new btime:
+ btime=thistime;
+
+ thisnrow=0;
+ meanIntTim=0.;
+ ++recLength;
+ }
+
+ // etime keeps pace with thistime
+ etime=thistime;
+
+ } else {
+ // initialize btime and etime
+ btime=thistime;
+ etime=thistime;
+ // no longer first time thru
+ firsttime=False;
+ }
+
+ thisnrow+=nrow;
+
+ meanIntTim+=sum(inttim.makeVector());
+
+ // for comparison at next timestamp
+ lastfldids.assign(fldids);
+ lastddids.assign(ddids);
+ laststids.assign(stids);
+ lastscan=thisscan;
+
+ // push iteration
+ stiter.next();
+ } // end of time iteration
+
+ if (thisnrow>0)
+ meanIntTim/=thisnrow;
+ else
+ meanIntTim=0.0;
+
+ // Spws
+ spwids.resize(lastddids.nelements());
+ for (uInt iddi=0; iddi<spwids.nelements();++iddi)
+ spwids(iddi)=specwindids(lastddids(iddi));
+
+ // Print out final scan's times, fields, ddis
+ Record scanRecord;
***The diff for this file has been truncated for email.***
=======================================
--- /dev/null
+++ /branches/nov14/ms/MSOper/MSSummary.h Wed Mar 25 14:33:54 2015 UTC
@@ -0,0 +1,195 @@
+//# MSSummary.h: Helper class for applications listing an image header
+//# Copyright (C) 1996,1997,1998,1999,2000,2001
+//# Associated Universities, Inc. Washington DC, USA.
+//#
+//# This library is free software; you can redistribute it and/or modify it
+//# under the terms of the GNU Library General Public License as published
by
+//# the Free Software Foundation; either version 2 of the License, or (at
your
+//# option) any later version.
+//#
+//# This library is distributed in the hope that it will be useful, but
WITHOUT
+//# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+//# FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
+//# License for more details.
+//#
+//# You should have received a copy of the GNU Library General Public
License
+//# along with this library; if not, write to the Free Software Foundation,
+//# Inc., 675 Massachusetts Ave, Cambridge, MA 02139, USA.
+//#
+//# Correspondence concerning AIPS++ should be addressed as follows:
+//# Internet email:
aips2-...@nrao.edu.
+//# Postal address: AIPS++ Project Office
+//# National Radio Astronomy Observatory
+//# 520 Edgemont Road
+//# Charlottesville, VA 22903-2475 USA
+//#
+//# $Id$
+//#
+#ifndef MS_MSSUMMARY_H
+#define MS_MSSUMMARY_H
+
+#include <casacore/casa/aips.h>
+#include <casacore/casa/BasicSL/String.h>
+#include <casacore/casa/Utilities/PtrHolder.h>
+#include <casacore/ms/MeasurementSets/MSColumns.h>
+#include <memory>
+
+namespace casacore { //# NAMESPACE CASACORE - BEGIN
+
+class MeasurementSet;
+class LogIO;
+class MSMetaData;
+
+// <summary>Provides and lists information about the header of an
image</summary>
+// <use visibility=export>
+//
+// <reviewed reviewer="" date="yyyy/mm/dd" tests="" demos="">
+// </reviewed>
+//
+// <prerequisite>
+// <li> <linkto class=MeasurementSet>MeasurementSet</linkto>
+// <li> <linkto module=Coordinates>Coordinates</linkto>
+// </prerequisite>
+//
+// <etymology>
+// This class lists the ancilliary or header information from a
+// MeasurementSet in a Summary format.
+// </etymology>
+//
+// <synopsis>
+// MSs consist of pixels and descriptive information stored in what
+// is loosely termed the header. This is information describing the
+// coordinate system, the image units etc. This class enables you to
+// retrieve the descriptive header information and/or list it.
+// </synopsis>
+//
+// <example>
+// <srcBlock>
+// PagedMS<Float> inMS(fileName);
+// MSSummary<Float> header(inMS);
+// LogOrigin or("myClass", "myFunction(...)", WHERE);
+// LogIO os(or);
+// header.list(os);
+// </srcBlock>
+// A <src>PagedMS</src> object is constructed and then logged to the
+// supplied <src>LogIO</src> object.
+// </example>
+//
+// <note role=caution>
+// Note that if the <src>PagedMS</src> goes out of scope, this
+// class will retrieve rubbish as it just maintains a pointer
+// to the image.
+// </note>
+//
+// <motivation>
+// The viewing of the image header is a basic capability that is
+// commonly required.
+// </motivation>
+//
+// <todo asof="1998/12/09">
+// There are various placeholders which will need to be activated for
+// Version 2 of the MeasurementSet definition.
+// </todo>
+
+
+class MSSummary
+{
+public:
+// Constructor
+ MSSummary (const MeasurementSet&);
+ MSSummary (const MeasurementSet*);
+ MSSummary (const MeasurementSet* ms, const String msname);
+
+// Destructor
+ ~MSSummary();
+
+// Retrieve number of rows
+ Int nrow() const;
+
+// Retrieve image name
+ String name() const;
+
+// Set a new MS
+ Bool setMS (const MeasurementSet& ms);
+
+// List all header information.
+ void list (LogIO& os, Bool verbose=False, Bool oneBased=True) const;
+//Return some useful info in a record too along with os
+ void list (LogIO& os, Record& outRec, Bool verbose=False,
+ Bool fillRecord=True, Bool oneBased=True) const;
+
+// List a title for the Summary.
+ void listTitle (LogIO& os) const;
+
+// List convenient groupings of tables: list where MS obtained
+// (Observation and Array tables)
+ void listWhere (LogIO& os, Bool verbose=False) const;
+
+// List what was observed (Field and Main tables)
+ void listWhat (LogIO& os, Bool verbose=False) const;
+ void listWhat (LogIO& os, Record& outRec, Bool verbose=False,
+ Bool fillRecord=True) const;
+// List how data were obtained (SpectralWindow, Feed, and Antenna tables)
+ void listHow (LogIO& os, Bool verbose=False, Bool oneBased=True) const;
+
+// List main table
+ void listMain (LogIO& os, Bool verbose=False) const;
+//Return some useful info in a record too along with os
+ void listMain (LogIO& os, Record& outRec, Bool verbose=False,
+ Bool fillRecord=True) const;
+ // Return a Record with information derived from the main table
+ void getScanSummary (Record& outRec) const;
+
+// List subtables
+// <group>
+ void listAntenna (LogIO& os, Bool verbose=False) const;
+ void listFeed (LogIO& os, Bool verbose=False, Bool oneBased=True) const;
+ void listField (LogIO& os, Bool verbose=False) const;
+ void listField (LogIO& os, Record& outRec, Bool verbose=False,
+ Bool fillRecord=True) const;
+ void listObservation (LogIO& os, Bool verbose=False) const;
+ void listHistory (LogIO& os) const;
+ void listPolarization (LogIO& os, Bool verbose=False) const;
+ void listSource (LogIO& os, Bool verbose=False) const;
+ void listSpectralWindow (LogIO& os, Bool verbose=False) const;
+ void getSpectralWindowInfo(Record& outRec) const;
+ void listSpectralAndPolInfo (LogIO& os, Bool verbose=False,
+ Bool oneBased=True) const;
+ void listSysCal (LogIO& os, Bool verbose=False) const;
+ void listWeather (LogIO& os, Bool verbose=False) const;
+// </group>
+
+// List table size summary
+ void listTables (LogIO& os, Bool verbose=False) const;
+
+ void setListUnflaggedRowCount(Bool v) { _listUnflaggedRowCount = v; }
+
+ // set the cache size, in MB, for the MSMetaData object.
+ void setMetaDataCacheSizeInMB(Float cacheSize) { _cacheSizeMB =
cacheSize; }
+
+private:
+// Pointer to MS
+ const MeasurementSet* pMS;
+ SPtrHolder<MSMetaData> _msmd;
+
+// Formatting strings
+ const String dashlin1, dashlin2;
+
+// Clear formatting flags
+ void clearFlags (LogIO& os) const;
+
+// For keeping track of the number of vis per field
+ mutable Vector<Int> nVisPerField_;
+
+ // Name of the MS used in the constructor
+ String msname_p;
+
+ Bool _listUnflaggedRowCount;
+
+ Float _cacheSizeMB;
+};
+
+
+} //# NAMESPACE CASACORE - END
+
+#endif
=======================================
--- /dev/null
+++ /branches/nov14/ms/MSOper/MSValidIds.cc Wed Mar 25 14:33:54 2015 UTC
@@ -0,0 +1,186 @@
+//# MSValidIds.cc: this defines MSValidIds.
+//# Copyright (C) 2000
+//# Associated Universities, Inc. Washington DC, USA.
+//#
+//# This library is free software; you can redistribute it and/or modify it
+//# under the terms of the GNU Library General Public License as published
by
+//# the Free Software Foundation; either version 2 of the License, or (at
your
+//# option) any later version.
+//#
+//# This library is distributed in the hope that it will be useful, but
WITHOUT
+//# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+//# FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
+//# License for more details.
+//#
+//# You should have received a copy of the GNU Library General Public
License
+//# along with this library; if not, write to the Free Software Foundation,
+//# Inc., 675 Massachusetts Ave, Cambridge, MA 02139, USA.
+//#
+//# Correspondence concerning AIPS++ should be addressed as follows:
+//# Internet email:
aips2-...@nrao.edu.
+//# Postal address: AIPS++ Project Office
+//# National Radio Astronomy Observatory
+//# 520 Edgemont Road
+//# Charlottesville, VA 22903-2475 USA
+//#
+//# $Id$
+
+//# Includes
+
+#include <casacore/ms/MSOper/MSValidIds.h>
+
+#include <casacore/casa/Exceptions/Error.h>
+#include <casacore/ms/MeasurementSets/MSColumns.h>
+#include <casacore/tables/Tables/TableRecord.h>
+#include <casacore/casa/Utilities/Assert.h>
+#include <casacore/casa/BasicSL/String.h>
+
+namespace casacore { //# NAMESPACE CASACORE - BEGIN
+
+MSValidIds::MSValidIds()
+ : romsCols_p(0), hasDoppler_p(False), hasSource_p(False)
+{ ;}
+
+MSValidIds::MSValidIds(const MeasurementSet &ms)
+ : romsCols_p(0), hasDoppler_p(False), hasSource_p(False)
+{ attach(ms);}
+
+MSValidIds::MSValidIds(const MSValidIds &other)
+ : romsCols_p(0), hasDoppler_p(False), hasSource_p(False)
+{ *this = other;}
+
+MSValidIds::~MSValidIds()
+{ clear(); }
+
+MSValidIds &MSValidIds::operator=(const MSValidIds &other)
+{
+ if (this != &other) {
+ attach(other.ms_p);
+ }
+ return *this;
+}
+
+void MSValidIds::attach(const MeasurementSet &ms)
+{
+ clear();
+
+ ms_p = ms;
+
+ romsCols_p = new ROMSColumns(ms_p);
+ AlwaysAssert(romsCols_p, AipsError);
+
+ // check on existance of optional sub-tables
+ hasDoppler_p = ms_p.keywordSet().isDefined("DOPPLER");
+ hasSource_p = ms_p.keywordSet().isDefined("SOURCE");
+}
+
+Int MSValidIds::antenna1(uInt rownr) const
+{
+ Int result = -1;
+ if (checkRow(rownr) && romsCols_p) {
+ result = checkResult(romsCols_p->antenna1()(rownr), ms_p.antenna());
+ }
+ return result;
+}
+
+Int MSValidIds::antenna2(uInt rownr) const
+{
+ Int result = -1;
+ if (checkRow(rownr) && romsCols_p) {
+ result = checkResult(romsCols_p->antenna2()(rownr), ms_p.antenna());
+ }
+ return result;
+}
+
+Int MSValidIds::dataDescId(uInt rownr) const
+{
+ Int result = -1;
+ if (checkRow(rownr) && romsCols_p) {
+ result = checkResult(romsCols_p->dataDescId()(rownr),
ms_p.dataDescription());
+ }
+ return result;
+}
+
+Int MSValidIds::fieldId(uInt rownr) const
+{
+ Int result = -1;
+ if (checkRow(rownr) && romsCols_p) {
+ result = checkResult(romsCols_p->fieldId()(rownr), ms_p.field());
+ }
+ return result;
+}
+
+Int MSValidIds::observationId(uInt rownr) const
+{
+ Int result = -1;
+ if (checkRow(rownr) && romsCols_p) {
+ result = checkResult(romsCols_p->observationId()(rownr),
ms_p.observation());
+ }
+ return result;
+}
+
+Int MSValidIds::processorId(uInt rownr) const
+{
+ Int result = -1;
+ if (checkRow(rownr) && romsCols_p) {
+ result = checkResult(romsCols_p->processorId()(rownr), ms_p.processor());
+ }
+ return result;
+}
+
+Int MSValidIds::stateId(uInt rownr) const
+{
+ Int result = -1;
+ if (checkRow(rownr) && romsCols_p) {
+ result = checkResult(romsCols_p->stateId()(rownr), ms_p.state());
+ }
+ return result;
+}
+
+Int MSValidIds::polarizationId(uInt rownr) const
+{
+ Int result = dataDescId(rownr);
+ if (result >= 0) {
+ result =
checkResult(romsCols_p->dataDescription().polarizationId()(result),
ms_p.polarization());
+ }
+ return result;
+}
+
+Int MSValidIds::spectralWindowId(uInt rownr) const
+{
+ Int result = dataDescId(rownr);
+ if (result >= 0) {
+ result =
checkResult(romsCols_p->dataDescription().spectralWindowId()(result),
ms_p.spectralWindow());
+ }
+ return result;
+}
+
+Int MSValidIds::dopplerId(uInt rownr) const
+{
+ Int result = hasDoppler_p ? spectralWindowId(rownr) : -1;
+ if (result >= 0) {
+ result = romsCols_p->spectralWindow().dopplerId().isNull() ? -1 :
+ romsCols_p->spectralWindow().dopplerId()(result);
+ }
+ return result;
+}
+
+Int MSValidIds::sourceId(uInt rownr) const
+{
+ Int result = hasSource_p ? fieldId(rownr) : -1;
+ if (result >= 0) {
+ result = romsCols_p->field().sourceId()(result);
+ }
+ return result;
+}
+
+void MSValidIds::clear()
+{
+ delete romsCols_p;
+ romsCols_p = 0;
+
+ hasDoppler_p = hasSource_p = False;
+}
+
+} //# NAMESPACE CASACORE - END
+
=======================================
--- /dev/null
+++ /branches/nov14/ms/MSOper/MSValidIds.h Wed Mar 25 14:33:54 2015 UTC
@@ -0,0 +1,140 @@
+//# MSValidIds: ensures that required MS Ids are valid or -1 by row number
+//# Copyright (C) 2000
+//# Associated Universities, Inc. Washington DC, USA.
+//#
+//# This library is free software; you can redistribute it and/or modify it
+//# under the terms of the GNU Library General Public License as published
by
+//# the Free Software Foundation; either version 2 of the License, or (at
your
+//# option) any later version.
+//#
+//# This library is distributed in the hope that it will be useful, but
WITHOUT
+//# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+//# FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
+//# License for more details.
+//#
+//# You should have received a copy of the GNU Library General Public
License
+//# along with this library; if not, write to the Free Software Foundation,
+//# Inc., 675 Massachusetts Ave, Cambridge, MA 02139, USA.
+//#
+//# Correspondence concerning AIPS++ should be addressed as follows:
+//# Internet email:
aips2-...@nrao.edu.
+//# Postal address: AIPS++ Project Office
+//# National Radio Astronomy Observatory
+//# 520 Edgemont Road
+//# Charlottesville, VA 22903-2475 USA
+//#
+//#
+//# $Id$
+
+#ifndef MS_MSVALIDIDS_H
+#define MS_MSVALIDIDS_H
+
+#include <casacore/casa/aips.h>
+#include <casacore/ms/MeasurementSets/MeasurementSet.h>
+
+namespace casacore { //# NAMESPACE CASACORE - BEGIN
+
+//# Forward declarations
+class ROMSColumns;
+
+// <summary>
+// </summary>
+
+// <use visibility=export>
+
+// <reviewed reviewer="" date="yyyy/mm/dd" tests="" demos="">
+// </reviewed>
+
+// <prerequisite>
+// <li> MeasurementSet
+// </prerequisite>
+//
+// <etymology>
+// </etymology>
+//
+// <synopsis>
+// </synopsis>
+//
+// <example>
+// </example>
+//
+// <motivation>
+// </motivation>
+//
+// <thrown>
+// <li>
+// <li>
+// </thrown>
+
+class MSValidIds
+{
+public:
+ // Construct one unattached to a MeasurementSet. All functions return
-1.
+ // Use the attach function to attach this to a MeasurementSet after
construction.
+ MSValidIds();
+
+ // Construct one attached to the indicated MeasurementSet
+ MSValidIds(const MeasurementSet &ms);
+
+ // Construct one from another
+ MSValidIds(const MSValidIds &other);
+
+ // The destructor
+ ~MSValidIds();
+
+ // Assignment operator, reference semantics.
+ MSValidIds &operator=(const MSValidIds &other);
+
+ // Attach this one to a MeasurementSet. This can also be used to
+ // re-attach to the same MeasurementSet when additional optional
+ // subtables have been added since this object was constructed.
+ void attach(const MeasurementSet &ms);
+
+ // These functions check on the validity of the appropriate value in
+ // the main table or sub-tables in the case of some Ids. The actual
+ // value stored is returned unless the sub-table does not exist (for
+ // optional subtables) or the indicated row number does not exist
+ // in that sub-table where appropriate.
+ // <group>
+ Int antenna1(uInt rownr) const;
+ Int antenna2(uInt rownr) const;
+ Int dataDescId(uInt rownr) const;
+ Int fieldId(uInt rownr) const;
+ Int observationId(uInt rownr) const;
+ Int processorId(uInt rownr) const;
+ Int stateId(uInt rownr) const;
+ // The polarizationId comes from the DATA_DESCRIPTION subtable, so
dataDescId must
+ // first be valid in order for this to also be valid.
+ Int polarizationId(uInt rownr) const;
+ // The spectralWindowId comes from the DATA_DESCRIPTION subtable, so
dataDescId must
+ // first be valid in order for this to also be valid.
+ Int spectralWindowId(uInt rownr) const;
+ // the dopplerId comes from the SPECTRAL_WINDOW subtable so
spectralWindowId must
+ // first be valid in order for this to also be valid. Since the
DOPPLER subtable
+ // is not simply indexed by DOPPLER_ID, the DOPPLER subtable exists
and a dopplerId
+ // can be found in the SPECTRAL_WINDOW subtable, that value will be
returned, whatever
+ // it is.
+ Int dopplerId(uInt rownr) const;
+ // The sourceId comes from the FIELD subtable so fieldId must first be
valid
+ // in order for this to also be valid. Since the SOURCE table is also
+ // indexed by TIME, the only additional check is that a SOURCE table
must
+ // exist in order for this to be valid.
+ Int sourceId(uInt rownr) const;
+ // </group>
+private:
+ MeasurementSet ms_p;
+ ROMSColumns *romsCols_p;
+
+ Bool hasDoppler_p, hasSource_p;
+
+ void clear();
+ Int checkResult(Int testResult, const Table &mstable) const
+ { return (testResult < 0 || uInt(testResult) >= mstable.nrow()) ? -1 :
testResult;}
+
+ Bool checkRow(uInt rownr) const {return rownr < ms_p.nrow();}
+};
+
+
+} //# NAMESPACE CASACORE - END
+
+#endif
=======================================
--- /dev/null
+++ /branches/nov14/ms/MSOper/NewMSSimulator.cc Wed Mar 25 14:33:54 2015 UTC
@@ -0,0 +1,1899 @@
+ //# NewMSSimulator.cc: this defines NewMSSimulator, which simulates a
MeasurementSet
+//# Copyright (C) 1995-2009
+//# Associated Universities, Inc. Washington DC, USA.
+//#
+//# This library is free software; you can redistribute it and/or modify it
+//# under the terms of the GNU Library General Public License as published
by
+//# the Free Software Foundation; either version 2 of the License, or (at
your
+//# option) any later version.
+//#
+//# This library is distributed in the hope that it will be useful, but
WITHOUT
+//# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+//# FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
+//# License for more details.
+//#
+//# You should have received a copy of the GNU Library General Public
License
+//# along with this library; if not, write to the Free Software Foundation,
+//# Inc., 675 Massachusetts Ave, Cambridge, MA 02139, USA.
+//#
+//# Correspondence concerning AIPS++ should be addressed as follows:
+//# Internet email:
aips2-...@nrao.edu.
+//# Postal address: AIPS++ Project Office
+//# National Radio Astronomy Observatory
+//# 520 Edgemont Road
+//# Charlottesville, VA 22903-2475 USA
+//#
+//# $Id$
+
+//# Includes
+#include <casacore/ms/MSOper/NewMSSimulator.h>
+#include <casacore/ms/MSOper/MSDerivedValues.h>
+#include <casacore/ms/MeasurementSets/MeasurementSet.h>
+#include <casacore/ms/MeasurementSets/MSColumns.h>
+#include <casacore/casa/Logging/LogIO.h>
+#include <casacore/casa/Containers/Record.h>
+#include <casacore/tables/Tables/SetupNewTab.h>
+#include <casacore/tables/Tables/ScalarColumn.h>
+#include <casacore/tables/Tables/ArrayColumn.h>
+#include <casacore/tables/Tables/TableDesc.h>
+#include <casacore/tables/Tables/ScaColDesc.h>
+#include <casacore/tables/Tables/TableRecord.h>
+#include <casacore/tables/DataMan/StManAipsIO.h>
+#include <casacore/tables/DataMan/IncrementalStMan.h>
+#include <casacore/tables/DataMan/StandardStMan.h>
+#include <casacore/tables/DataMan/TiledColumnStMan.h>
+#include <casacore/tables/DataMan/TiledShapeStMan.h>
+#include <casacore/tables/DataMan/TiledDataStMan.h>
+#include <casacore/tables/DataMan/TiledStManAccessor.h>
+#include <casacore/tables/DataMan/TiledDataStManAccessor.h>
+#include <casacore/casa/BasicSL/Constants.h>
+#include <casacore/casa/BasicMath/Random.h>
+#include <casacore/casa/Arrays/ArrayMath.h>
+#include <casacore/casa/Arrays/Cube.h>
+#include <casacore/casa/Arrays/MatrixMath.h>
+#include <casacore/casa/Arrays/ArrayLogical.h>
+#include <casacore/casa/Arrays/Slice.h>
+#include <casacore/measures/Measures/Stokes.h>
+#include <casacore/measures/Measures/MeasFrame.h>
+#include <casacore/casa/Quanta/MVuvw.h>
+#include <casacore/casa/Quanta/MVDirection.h>
+#include <casacore/casa/Quanta/MVAngle.h>
+#include <casacore/casa/Quanta/MVTime.h>
+#include <casacore/measures/Measures/MeasTable.h>
+#include <casacore/measures/Measures/MBaseline.h>
+#include <casacore/measures/Measures/MCBaseline.h>
+#include <casacore/measures/Measures/Muvw.h>
+#include <casacore/measures/Measures/MEpoch.h>
+#include <casacore/measures/Measures/MCPosition.h>
+#include <casacore/measures/Measures/MPosition.h>
+#include <casacore/measures/Measures/MDirection.h>
+#include <casacore/measures/Measures/MeasConvert.h>
+#include <casacore/measures/Measures/MeasData.h>
+#include <casacore/measures/Measures/MFrequency.h>
+#include <casacore/measures/Measures.h>
+#include <casacore/casa/Utilities/CountedPtr.h>
+#include <casacore/casa/Utilities/Assert.h>
+#include <casacore/casa/Arrays/ArrayUtil.h>
+#include <casacore/casa/Arrays/Slicer.h>
+#include <casacore/casa/iostream.h>
+#include <casacore/casa/fstream.h>
+#include <casacore/casa/sstream.h>
+#include <casacore/ms/MeasurementSets/MSTileLayout.h>
+#include <casacore/scimath/Mathematics/RigidVector.h>
+#include <casacore/scimath/Mathematics/SquareMatrix.h>
+
+// temporary to get access to beam_offsets
+#include <casacore/ms/MeasurementSets/MSIter.h>
+//
+
+namespace casacore { //# NAMESPACE CASACORE - BEGIN
+
+const uInt nCat = 6; // Number of Flag categories
+
+const String sigmaCol = "sigmaHyperColumn";
+const String dataCol = "dataHyperColumn";
+const String scratchDataCol = "scratchDataHyperColumn";
+const String flagCol = "flagHyperColumn";
+
+const String sigmaTileId = "SIGMA_HYPERCUBE_ID";
+const String dataTileId = "DATA_HYPERCUBE_ID";
+const String scratchDataTileId = "SCRATCH_DATA_HYPERCUBE_ID";
+const String flagTileId = "FLAG_CATEGORY_HYPERCUBE_ID";
+
+// a but ugly solution to use the feed table parser of MSIter
+// to extract antennaMounts and BeamOffsets.
+struct MSFeedParameterExtractor : protected MSIter {
+
+ MSFeedParameterExtractor(const MeasurementSet &ms) {
+ msc_p=new ROMSColumns(ms);
+ msc_p->antenna().mount().getColumn(antennaMounts_p,True);
+ checkFeed_p=True;
+ setFeedInfo();
+ }
+ // Return a string mount identifier for each antenna
+ using MSIter::antennaMounts;
+
+ // Return a cube containing pairs of coordinate offset for each receptor
+ // of each feed (values are in radians, coordinate system is fixed with
+ // antenna and is the same as used to define the BEAM_OFFSET parameter
+ // in the feed table). The cube axes are receptor, antenna, feed.
+ using MSIter::getBeamOffsets;
+
+ // True if all elements of the cube returned by getBeamOffsets are zero
+ using MSIter::allBeamOffsetsZero;
+
+};
+//
+
+
+
+void NewMSSimulator::defaults() {
+ fractionBlockageLimit_p=1e-6;
+ elevationLimit_p=Quantity(8.0, "deg");
+ autoCorrelationWt_p=1.0;
+ telescope_p="Unknown";
+ qIntegrationTime_p=Quantity(10.0, "s");
+ useHourAngle_p=True;
+ Quantity today;
+ MVTime::read(today, "today");
+ mRefTime_p=MEpoch(today, MEpoch::UTC);
+}
+
+NewMSSimulator::NewMSSimulator(const String& MSName) :
+ ms_p(0), dataAcc_p(), scratchDataAcc_p(), sigmaAcc_p(), flagAcc_p(),
+ maxData_p(2e9)
+{
+ LogIO os(LogOrigin("NewMSSimulator", "NewMSSimulator<const String&
MSName)", WHERE));
+
+ defaults();
+
+ // make MS with standard columns
+ TableDesc msDesc(MS::requiredTableDesc());
+
+ // Add other columns, including the scratch columns
+ MS::addColumnToDesc(msDesc,MS::DATA,2);
+ MS::addColumnToDesc(msDesc,MS::MODEL_DATA,2);
+ MS::addColumnToDesc(msDesc,MS::CORRECTED_DATA,2);
+
+ // Add index columns for tiling. We use three tiles: data, sigma, and
flag.
+ // Some of these contain more than one column
+ /*
+ msDesc.addColumn(ScalarColumnDesc<Int>(dataTileId,
+ "Index for Data tiling"));
+ msDesc.addColumn(ScalarColumnDesc<Int>(scratchDataTileId,
+ "Index for Scratch Data tiling"));
+ msDesc.addColumn(ScalarColumnDesc<Int>(sigmaTileId,
+ "Index for Sigma tiling"));
+ msDesc.addColumn(ScalarColumnDesc<Int>(flagTileId,
+ "Index for Flag Category tiling"));
+ */
+ // setup hypercolumns for the data/flag/flag_catagory/sigma & weight
columns.
+ {
+ Vector<String> dataCols(1);
+ dataCols(0) = MeasurementSet::columnName(MeasurementSet::DATA);
+ const Vector<String> coordCols(0);
+ const Vector<String> idCols(1, dataTileId);
+ //msDesc.defineHypercolumn(dataCol, 3, dataCols, coordCols, idCols);
+ msDesc.defineHypercolumn(dataCol, 3, dataCols);
+ }
+{
+ Vector<String> dataCols(1);
+ dataCols(0) = MeasurementSet::columnName(MeasurementSet::FLAG);
+ const Vector<String> coordCols(0);
+ const Vector<String> idCols(1, dataTileId);
+ //msDesc.defineHypercolumn(dataCol, 3, dataCols, coordCols, idCols);
+ msDesc.defineHypercolumn("FlagColumn", 3, dataCols);
+ }
+ {
+ Vector<String> dataCols(1);
+ dataCols(0) = MeasurementSet::columnName(MeasurementSet::MODEL_DATA);
+ const Vector<String> coordCols(0);
+ const Vector<String> idCols(1, scratchDataTileId);
+ // msDesc.defineHypercolumn(scratchDataCol, 3, dataCols, coordCols,
idCols);
+ msDesc.defineHypercolumn("ModelDataColumn", 3, dataCols);
+ }
+ {
+ Vector<String> dataCols(1);
+ dataCols(0) =
MeasurementSet::columnName(MeasurementSet::CORRECTED_DATA);
+ const Vector<String> coordCols(0);
+ const Vector<String> idCols(1, scratchDataTileId);
+ //msDesc.defineHypercolumn(scratchDataCol, 3, dataCols, coordCols,
idCols);
+ msDesc.defineHypercolumn("CorrectedDataColumn", 3, dataCols);
+ }
+
+ {
+ Vector<String> dataCols(1);
+ dataCols(0) = MeasurementSet::columnName(MeasurementSet::SIGMA);
+ const Vector<String> coordCols(0);
+ const Vector<String> idCols(1, sigmaTileId);
+ //msDesc.defineHypercolumn(sigmaCol, 2, dataCols, coordCols, idCols);
+ msDesc.defineHypercolumn("SigmaColumn", 2, dataCols);
+ }
+ {
+ Vector<String> dataCols(1);
+ dataCols(0) = MeasurementSet::columnName(MeasurementSet::WEIGHT);
+ const Vector<String> coordCols(0);
+ const Vector<String> idCols(1, sigmaTileId);
+ // msDesc.defineHypercolumn(sigmaCol, 2, dataCols, coordCols, idCols);
+ msDesc.defineHypercolumn("WeightColumn", 2, dataCols);
+ }
+
+ {
+ Vector<String> dataCols(1);
+ dataCols(0) =
MeasurementSet::columnName(MeasurementSet::FLAG_CATEGORY);
+ const Vector<String> coordCols(0);
+ const Vector<String> idCols(1, flagTileId);
+ // msDesc.defineHypercolumn(flagCol, 4, dataCols, coordCols,
idCols);
+ msDesc.defineHypercolumn(flagCol, 4, dataCols);
+ }
+
+ SetupNewTable newMS(MSName, msDesc, Table::New);
+
+ // Set the default Storage Manager to be the Incr one
+ {
+ IncrementalStMan incrStMan ("ismdata");
+ newMS.bindAll(incrStMan, True);
+ }
+
+ // Bind ANTENNA1, and ANTENNA2 to the standardStMan
+ // as they may change sufficiently frequently to make the
+ // incremental storage manager inefficient for these columns.
+
+ {
+ StandardStMan ssm(32768);
+ newMS.bindColumn(MS::columnName(MS::ANTENNA1), ssm);
+ newMS.bindColumn(MS::columnName(MS::ANTENNA2), ssm);
+ }
+
+ IPosition tileShape(3, 4, 100, 100);
+ // These columns contain the bulk of the data so save them in a tiled way
+ {
+ TiledShapeStMan dataMan(dataCol, tileShape);
+ newMS.bindColumn(MeasurementSet::
+ columnName(MeasurementSet::DATA), dataMan);
+ }
+ {
+ TiledShapeStMan dataMan("FlagColumn", tileShape);
+ newMS.bindColumn(MeasurementSet::
+ columnName(MeasurementSet::FLAG), dataMan);
+ }
+ {
+ TiledShapeStMan dataMan("ModelDataColumn", tileShape);
+ newMS.bindColumn(MeasurementSet::
+ columnName(MeasurementSet::MODEL_DATA), dataMan);
+ }
+ {
+ TiledShapeStMan dataMan("CorrectedDataColumn", tileShape);
+ newMS.bindColumn(MeasurementSet::
+ columnName(MeasurementSet::CORRECTED_DATA), dataMan);
+ }
+ {
+ TiledShapeStMan dataMan("SigmaColumn", IPosition(2,tileShape(0),
tileShape(2)));
+ newMS.bindColumn(MeasurementSet::
+ columnName(MeasurementSet::SIGMA), dataMan);
+ }
+ {
+ TiledShapeStMan dataMan("WeightColumn", IPosition(2,tileShape(0),
tileShape(2)));
+ newMS.bindColumn(MeasurementSet::
+ columnName(MeasurementSet::WEIGHT), dataMan);
+ }
+
+ {
+ TiledShapeStMan dataMan(flagCol,
+ IPosition(4,tileShape(0),tileShape(1), 1,
+ tileShape(2)));
+ newMS.bindColumn(MeasurementSet::
+ columnName(MeasurementSet::FLAG_CATEGORY), dataMan);
+ // newMS.bindColumn(flagTileId, dataMan);
+ }
+
+ // Now we can create the MeasurementSet and add the (empty) subtables
+ ms_p=new MeasurementSet(newMS,0);
+ ms_p->createDefaultSubtables(Table::New);
+
+ // add the SOURCE table [copied from SimpleSimulator]
+ TableDesc tdesc; // = MSSource::requiredTableDesc();
+ for (uInt i = 1 ; i<=MSSource::NUMBER_PREDEFINED_COLUMNS; i++) {
+ MSSource::addColumnToDesc(tdesc, MSSource::PredefinedColumns(i));
+ }
+ MSSource::addColumnToDesc(tdesc, MSSourceEnums::REST_FREQUENCY, 1);
+ SetupNewTable sourceSetup(ms_p->sourceTableName(),tdesc,Table::New);
+ ms_p->rwKeywordSet().defineTable(MS::keywordName(MS::SOURCE),
+ Table(sourceSetup));
+
+
+// // add the STATE table [copied from SimpleSimulator]
+// TableDesc tdesc2;
+// for (uInt i = 1 ; i<=MSState::NUMBER_PREDEFINED_COLUMNS; i++) {
+// MSState::addColumnToDesc(tdesc2, MSState::PredefinedColumns(i));
+// }
+// SetupNewTable stateSetup(ms_p->stateTableName(),tdesc2,Table::New);
+// ms_p->rwKeywordSet().defineTable(MS::keywordName(MS::STATE),
+// Table(stateSetup));
+//
+
+ // intialize the references to the subtables just added
+ ms_p->initRefs();
+ //
+ ms_p->flush();
+
+ // Set the TableInfo
+ {
+ TableInfo& info(ms_p->tableInfo());
+ info.setType(TableInfo::type(TableInfo::MEASUREMENTSET));
+ info.setSubType(String("simulator"));
+ info.readmeAddLine
+ ("This is a MeasurementSet Table holding simulated astronomical
observations");
+ }
+
+ // Now we can make the accessors to be used when adding hypercolumns
+ /*
+ dataAcc_p = TiledDataStManAccessor(*ms_p, dataCol);
+ scratchDataAcc_p = TiledDataStManAccessor(*ms_p, scratchDataCol);
+ sigmaAcc_p = TiledDataStManAccessor(*ms_p, sigmaCol);
+ flagAcc_p = TiledDataStManAccessor(*ms_p, flagCol);
+ */
+ // We're done - wasn't that easy?
+
+ dataWritten_p=0.0;
+ hyperCubeID_p=-1;
+ lastSpWID_p=-1;
+ lastNchan_p=-1;
+ hasHyperCubes_p=False;
+}
+
+NewMSSimulator::NewMSSimulator(MeasurementSet& theMS) :
+ ms_p(0), dataAcc_p(), scratchDataAcc_p(), sigmaAcc_p(), flagAcc_p(),
+ maxData_p(2e9)
+{
+ LogIO os(LogOrigin("NewMSSimulator", "NewMSSimulator(MeasurementSet&
theMS)", WHERE));
+
+ defaults();
+
+ ms_p = new MeasurementSet(theMS);
+
+ os << "Opening MeasurementSet " << ms_p->tableName() << " with " <<
ms_p->nrow() << " rows" << LogIO::POST;
+ dataWritten_p=ms_p->nrow();
+
+ TableDesc td(ms_p->tableDesc());
+ if(td.isColumn(dataTileId)) {
+ hasHyperCubes_p=True;
+ // Now we can make the accessors to be used when adding hypercolumns
+ dataAcc_p = TiledDataStManAccessor(*ms_p, dataCol);
+ scratchDataAcc_p = TiledDataStManAccessor(*ms_p, scratchDataCol);
+ sigmaAcc_p = TiledDataStManAccessor(*ms_p, sigmaCol);
+ flagAcc_p = TiledDataStManAccessor(*ms_p, flagCol);
+
+ ScalarColumn<Int> hyperCubeIDColumn(*ms_p, dataTileId);
+ hyperCubeID_p=max(hyperCubeIDColumn.getColumn());
+ os << " last hyper cube ID = " << hyperCubeID_p << LogIO::POST;
+ }
+ else {
+ hasHyperCubes_p=False;
+ }
+ {
+ MSColumns msc(*ms_p);
+ MSSpWindowColumns& spwc=msc.spectralWindow();
+ lastSpWID_p=spwc.nrow();
+ lastNchan_p=spwc.chanFreq()(lastSpWID_p-1).nelements();
+
+ os << " last spectral window ID = " << lastSpWID_p << LogIO::POST;
+ }
+}
+
+// Add new hypercubes as the shape changes
+void NewMSSimulator::addHyperCubes(const Int id, const Int nBase, const
Int nChan,
+ const Int nCorr)
+{
+ Record tileId;
+ const uInt chanTiles=(nChan+7)/8;
+
+ tileId.define(sigmaTileId, static_cast<Int>(10*id));
+ sigmaAcc_p.addHypercube(IPosition(2, nCorr, 0),
+ IPosition(2, nCorr, nBase),
+ tileId);
+
+ tileId.define(dataTileId, static_cast<Int>(10*id+1));
+ dataAcc_p.addHypercube(IPosition(3, nCorr, nChan, 0),
+ IPosition(3, nCorr, chanTiles, nBase),
+ tileId);
+
+ tileId.define(scratchDataTileId, static_cast<Int>(10*id+2));
+ scratchDataAcc_p.addHypercube(IPosition(3, nCorr, nChan, 0),
+ IPosition(3, nCorr, chanTiles, nBase),
+ tileId);
+
+ tileId.define(flagTileId, static_cast<Int>(10*id + 3));
+ flagAcc_p.addHypercube(IPosition(4, nCorr, nChan, nCat, 0),
+ IPosition(4, nCorr, chanTiles, nCat, nBase),
+ tileId);
+}
+
+NewMSSimulator::NewMSSimulator(const NewMSSimulator & mss)
+{
+ operator=(mss);
+}
+
+
+void NewMSSimulator::initAnt(const String& telescope,
+ const Vector<Double>& x,
+ const Vector<Double>& y,
+ const Vector<Double>& z,
+ const Vector<Double>& dishDiameter,
+ const Vector<Double>&,
+ const Vector<String>& mount,
+ const Vector<String>& name,
+ const Vector<String>& padname,
+ const String& coordsystem,
+ const MPosition& mRefLocation)
+{
+ LogIO os(LogOrigin("NewMSSimulator", "initAnt()", WHERE));
+
+ telescope_p=telescope;
+
+ Int nAnt = x.nelements();
+
+ Vector<Double> xx( x.nelements() );
+ Vector<Double> yy( x.nelements() );
+ Vector<Double> zz( x.nelements() );
+ if (coordsystem == "global") {
+ xx = x; yy = y; zz = z;
+ os << "Using global coordinates for the antennas" << LogIO::POST;
+ } else if (coordsystem == "local") {
+
+ MVAngle mvLong= mRefLocation.getAngle().getValue()(0);
+ MVAngle mvLat= mRefLocation.getAngle().getValue()(1);
+
+ os << "Using local coordinates for the antennas" << endl
+ << "Reference position = ";
+ os.output().width(13); os << mvLong.string(MVAngle::ANGLE,7);
+ os.output().width(14); os << mvLat.string(MVAngle::DIG2,7);
+ os << LogIO::POST;
+ local2global( xx, yy, zz, mRefLocation, x, y, z);
+ } else if (coordsystem == "longlat") {
+ os << "Using longitude-latitude coordinates for the antennas" <<
LogIO::POST;
+ longlat2global( xx, yy, zz, mRefLocation, x, y, z);
+ } else {
+ os << LogIO::SEVERE << "Unknown coordinate system type: "
+ << coordsystem << LogIO::POST;
+ }
+
+ Vector<Int> antId(nAnt);
+ Matrix<Double> antXYZ(3,nAnt);
+
+ for (Int i=0; i<nAnt; i++) {
+ antXYZ(0,i)=xx(i);
+ antXYZ(1,i)=yy(i);
+ antXYZ(2,i)=zz(i);
+ antId(i)=i;
+ }
+
+ MSColumns msc(*ms_p);
+ MSAntennaColumns& antc=msc.antenna();
+ Int numOfAnt=antc.nrow();
+ MSAntenna& ant=ms_p->antenna();
+
+ ant.addRow(nAnt); // make nAnt rows
+ Slicer antSlice(IPosition(1,numOfAnt),
+ IPosition(1, numOfAnt+nAnt-1),
+ IPosition(1,1), Slicer::endIsLast );
+ antc.dishDiameter().putColumnRange(antSlice,dishDiameter);
+ antc.mount().putColumnRange(antSlice, mount);
+
antc.name().putColumnRange(antSlice,name);
+ // antc.offset().putColumnRange(antSlice,offset);
+ antc.position().putColumnRange(antSlice, antXYZ);
+ //antc.station().fillColumn("");
+ antc.station().putColumnRange(antSlice,padname);
+ antc.flagRow().fillColumn(False);
+ antc.type().fillColumn("GROUND-BASED");
+ os << "Added rows to ANTENNA table" << LogIO::POST;
+}
+
+//getAnt(telescope_p, nAnt, xyz_p, diam_p, offset_p, mount_p, antName_p,
+// coordsystem_p, mRefLocation_p)) {
+bool NewMSSimulator::getAnt(String& telescope, Int& nAnt, Matrix<Double>*
antXYZ,
+ Vector<Double>& antDiam, Vector<Double>& /*offset*/,
+ Vector<String>& mount, Vector<String>& name, Vector<String>&
padname,
+ String& coordsystem, MPosition& mRefLocation ) {
+ // return already set config info
+ LogIO os(LogOrigin("NewMSSimulator", "getAnt()", WHERE));
+
+ MSColumns msc(*ms_p);
+ MSAntennaColumns& antc=msc.antenna();
+ if(antc.nrow()==0) {
+ os << "Antenna information not yet defined" << LogIO::WARN;
+ return False;
+ }
+ telescope=telescope_p;
+ nAnt=antc.nrow();
+ if (!antXYZ) antXYZ = new Matrix<Double>(3,nAnt);
+ antXYZ->resize(3,nAnt);
+ antc.position().getColumn(*antXYZ);
+ antc.dishDiameter().getColumn(antDiam);
+ //antc.offset().getColumn(offset);
+ antc.mount().getColumn(mount);
+
antc.name().getColumn(name);
+ antc.station().getColumn(padname);
+
+ coordsystem="global";
+ MVPosition mvzero(0.,0.,0.);
+ MPosition mzero(mvzero,MPosition::ITRF);
+ mRefLocation=mzero;
+
+ return True;
+}
+
+
+
+
+
+void NewMSSimulator::local2global(Vector<Double>& xGeo,
+ Vector<Double>& yGeo,
+ Vector<Double>& zGeo,
+ const MPosition& mRefLocation,
+ const Vector<Double>& xLocal,
+ const Vector<Double>& yLocal,
+ const Vector<Double>& zLocal)
+{
+ uInt nn = xLocal.nelements();
+ xGeo.resize(nn);
+ yGeo.resize(nn);
+ zGeo.resize(nn);
+
+ MPosition::Convert loc2(mRefLocation, MPosition::ITRF);
+ MPosition locitrf(loc2());
+ Vector<Double> xyz = locitrf.get("m").getValue();
+
+ Vector<Double> ang = locitrf.getAngle("rad").getValue();
+ Double d1, d2;
+ d1 = ang(0);
+ d2 = ang(1);
+ Double cosLong = cos(d1);
+ Double sinLong = sin(d1);
+ Double cosLat = cos(d2);
+ Double sinLat = sin(d2);
+
+ for (uInt i=0; i< nn; i++) {
+
+ Double xG1 = -sinLat * yLocal(i) + cosLat * zLocal(i);
+ Double yG1 = xLocal(i);
+
+ xGeo(i) = cosLong * xG1 - sinLong * yG1 + xyz(0);
+ yGeo(i) = sinLong * xG1 + cosLong * yG1 + xyz(1);
+
+ zGeo(i) = cosLat * yLocal(i) + sinLat * zLocal(i) + xyz(2);
+ }
+
+}
+
+void NewMSSimulator::longlat2global(Vector<Double>&,
+ Vector<Double>&,
+ Vector<Double>&,
+ const MPosition&,
+ const Vector<Double>&,
+ const Vector<Double>&,
+ const Vector<Double>&)
+{
+ LogIO os(LogOrigin("NewMSSimulator", "longlat2global()", WHERE));
+ os << LogIO::SEVERE << "NewMSSimulator::longlat2global not yet
implemented" << LogIO::POST;
+}
+
+
+void NewMSSimulator::initFields(const String& sourceName,
+ const MDirection& sourceDirection,
+ const String& calCode)
+{
+ LogIO os(LogOrigin("MSsimulator", "initFields()", WHERE));
+
+ MSColumns msc(*ms_p);
+ MSFieldColumns& fieldc=msc.field();
+ Int baseFieldID=fieldc.nrow();
+ MSSourceColumns& sourcec=msc.source();
+ Int baseSrcID=sourcec.nrow();
+
+ const double forever=1.e30;
+
+ // os << "Creating new field table row for " << sourceName << ", ID "
+ // << baseFieldID << LogIO::POST;
+
+// if(!ms_p->source().isNull()){
+// os << "Creating new source table row for " << sourceName << ", ID "
+// << baseSrcID << LogIO::DEBUG1;
+// }
+
+ ms_p->field().addRow(1); //SINGLE DISH CASE
+
fieldc.name().put(baseFieldID, sourceName);
+ fieldc.code().put(baseFieldID, calCode);
+ fieldc.time().put(baseFieldID, 0.0);
+ fieldc.numPoly().put(baseFieldID, 0);
+ fieldc.sourceId().put(baseFieldID, baseSrcID);
+ Vector<MDirection> direction(1);
+ direction(0)=sourceDirection;
+ fieldc.delayDirMeasCol().put(baseFieldID,direction);
+ fieldc.phaseDirMeasCol().put(baseFieldID,direction);
+ fieldc.referenceDirMeasCol().put(baseFieldID,direction);
+
+ ms_p->source().addRow(1); //SINGLE DISH CASE
+
sourcec.name().put(baseSrcID, sourceName);
+ sourcec.code().put(baseSrcID, calCode);
+ sourcec.timeMeas().put(baseSrcID, mRefTime_p);
+ sourcec.interval().put(baseSrcID, forever);
+ sourcec.sourceId().put(baseSrcID, baseSrcID);
+ sourcec.directionMeas().put(baseSrcID,sourceDirection);
+ sourcec.spectralWindowId().put(baseSrcID,-1);
+ Vector<Double> pmV(2,0.);
+ sourcec.properMotion().put(baseSrcID,pmV);
+ sourcec.numLines().put(baseSrcID, 0);
+ sourcec.calibrationGroup().put(baseSrcID, 0);
+ if(!sourcec.sourceModel().isNull()){
+
+// The following commented out code is an example of how to insert
component list tables into the sourceModel column
+// RecordDesc smRecDesc;
+// smRecDesc.addField("model", TpTable);
+// TableRecord sm(smRecDesc, RecordInterface::Variable);
+
+// // create a dummy table to fill in
+// TableDesc td("", "1", TableDesc::Scratch);
+// SetupNewTable newtab("dummyModel", td, Table::New);
+// Table tab(newtab);
+// sm.defineTable("model", tab);
+// // Note: If there actually is a source model, it has to be a Table
file on disk.
+// // A table object for it has to be crated here and put into the
TableRecord
+// // instead of the "tab" above. DP
+// sourcec.sourceModel().put(baseSrcID, sm);
+
+ // but since we don't have models at the moment, I am removing this
column
+ ms_p->source().removeColumn("SOURCE_MODEL");
+ }
+
+ MSSpWindowColumns& spwc=msc.spectralWindow();
+ if(spwc.nrow()>0) {
+ sourcec.numLines().put(baseSrcID, 1);
+ sourcec.spectralWindowId().put(baseSrcID,0);
+ Vector<Double> rfV(1, spwc.refFrequency()(0));
+ sourcec.restFrequency().put(baseSrcID, rfV);
+ Vector<String> tV(1,"X");
+ sourcec.transition().put(baseSrcID, tV);
+ Vector<Double> svV(1, 0.);
+ sourcec.sysvel().put(baseSrcID, svV);
+ }
+
+}
+
+
+ bool NewMSSimulator::getFields(Int& nField,
+ Vector<String>& sourceName,
+ Vector<MDirection>& sourceDirection,
+ Vector<String>& calCode)
+{
+ LogIO os(LogOrigin("MSsimulator", "getFields()", WHERE));
+
+// os << sourceName_p
+// << " " << formatDirection(sourceDirection_p)
+// << " " << calCode_p
+
+ MSColumns msc(*ms_p);
+ MSFieldColumns& fieldc=msc.field();
+ nField=fieldc.nrow();
+
+ sourceName.resize(nField);
+ sourceDirection.resize(nField);
+ calCode.resize(nField);
+
+ for (Int i=0;i<nField;i++) {
+
fieldc.name().get(i, sourceName[i]);
+ fieldc.code().get(i, calCode[i]);
+ Vector<MDirection> direction;
+ fieldc.referenceDirMeasCol().get(i,direction,True);
+ // and if theres a varying reference direction per row, we'll just all
go
+ // merrily off into lala land.
+ sourceDirection[i]=direction[0];
+ }
+
+ return (nField>0);
+
+}
+
+MeasurementSet *
+NewMSSimulator::getMs () const
+{
+ return ms_p;
+}
+
+
+void NewMSSimulator::initSpWindows(const String& spWindowName,
+ const Int& nChan,
+ const Quantity& startFreq,
+ const Quantity& freqInc,
+ const Quantity&,
+ const MFrequency::Types& freqType,
+ const String& stokesString)
+{
+
+ LogIO os(LogOrigin("MSsimulator", "initSpWindows()", WHERE));
+
+ Vector<Int> stokesTypes(4);
+ stokesTypes=Stokes::Undefined;
+ String myStokesString = stokesString;
+ Int nCorr=0;
+ for (Int j=0; j<4; j++) {
+ while (myStokesString.at(0,1) == " ") {
+ myStokesString.del(0,1);
+ }
+
+ if (myStokesString.length() == 0)
+ break;
+
+ stokesTypes(j) = Stokes::type( myStokesString.at(0, 2) );
+ myStokesString.del(0,2);
+ nCorr = j+1;
+ if (stokesTypes(j)==Stokes::Undefined) {
+ os<< " Undefined polarization type in input"<<LogIO::POST;
+ }
+ }
+ MSColumns msc(*ms_p);
+ MSSpWindowColumns& spwc=msc.spectralWindow();
+ MSDataDescColumns& ddc=msc.dataDescription();
+ MSPolarizationColumns& polc=msc.polarization();
+ Int baseSpWID=spwc.nrow();
+ os << "Creating new spectral window " << spWindowName << ", ID "
+ << baseSpWID+1 << LogIO::POST;
+ // fill spectralWindow table
+ ms_p->spectralWindow().addRow(1);
+ ms_p->polarization().addRow(1);
+ ms_p->dataDescription().addRow(1);
+ spwc.numChan().put(baseSpWID,nChan);
+
spwc.name().put(baseSpWID,spWindowName);
+ spwc.netSideband().fillColumn(1);
+ spwc.ifConvChain().fillColumn(0);
+ spwc.freqGroup().fillColumn(0);
+ spwc.freqGroupName().fillColumn("Group 1");
+ spwc.flagRow().fillColumn(False);
+ // spwc.measFreqRef().fillColumn(MFrequency::TOPO);
+ spwc.measFreqRef().fillColumn(freqType);
+ polc.flagRow().fillColumn(False);
+ ddc.flagRow().fillColumn(False);
+ polc.numCorr().put(baseSpWID, nCorr);
+ Vector <Double> freqs(nChan), bandwidth(nChan);
+ bandwidth=freqInc.getValue("Hz");
+ ddc.spectralWindowId().put(baseSpWID,baseSpWID);
+ ddc.polarizationId().put(baseSpWID,baseSpWID);
+ Double vStartFreq(startFreq.getValue("Hz"));
+ Double vFreqInc(freqInc.getValue("Hz"));
+ for (Int chan=0; chan<nChan; chan++) {
+ freqs(chan)=vStartFreq+chan*vFreqInc;
+ }
+
+ // translate stokesTypes into receptor products, catch invalid
+ // fallibles.
+ Matrix<Int> corrProduct(uInt(2),uInt(nCorr));
+ Fallible<Int> fi;
+ stokesTypes.resize(nCorr, True);
+ for (Int j=0; j< nCorr; j++) {
+ fi=Stokes::receptor1(Stokes::type(stokesTypes(j)));
+ corrProduct(0,j)=(fi.isValid() ? fi.value() : 0);
+ fi=Stokes::receptor2(Stokes::type(stokesTypes(j)));
+ corrProduct(1,j)=(fi.isValid() ? fi.value() : 0);
+ }
+ spwc.refFrequency().put(baseSpWID,vStartFreq);
+ spwc.chanFreq().put(baseSpWID,freqs);
+ spwc.chanWidth().put(baseSpWID,bandwidth);
+ spwc.effectiveBW().put(baseSpWID,bandwidth);
+ spwc.resolution().put(baseSpWID,bandwidth);
+ spwc.totalBandwidth().put(baseSpWID,nChan*vFreqInc);
+ polc.corrType().put(baseSpWID,stokesTypes);
+ polc.corrProduct().put(baseSpWID,corrProduct);
+
+ {
+ MSSpWindowColumns msSpW(ms_p->spectralWindow());
+ Int nSpw=ms_p->spectralWindow().nrow();
+ if(nSpw==0) nSpw=1;
+ Matrix<Int> selection(2,nSpw);
+ selection.row(0)=0; //start
+ selection.row(1)=msSpW.numChan().getColumn();
+ ArrayColumn<Complex> mcd(*ms_p,"MODEL_DATA");
+ mcd.rwKeywordSet().define("CHANNEL_SELECTION",selection);
+ }
+
+}
+
+// if known already e.g. from openfromms()
+bool NewMSSimulator::getSpWindows(Int& nSpw,
+ Vector<String>& spWindowName,
+ Vector<Int>& nChan,
+ Vector<Quantity>& startFreq,
+ Vector<Quantity>& freqInc,
+ Vector<String>& stokesString)
+{
+
+ LogIO os(LogOrigin("MSsimulator", "getSpWindows()", WHERE));
+
+ MSColumns msc(*ms_p);
+ MSSpWindowColumns& spwc=msc.spectralWindow();
+ //MSDataDescColumns& ddc=msc.dataDescription();
+ MSPolarizationColumns& polc=msc.polarization();
+ nSpw=spwc.nrow();
+
+ spWindowName.resize(nSpw);
+ nChan.resize(nSpw);
+ startFreq.resize(nSpw);
+ freqInc.resize(nSpw);
+ stokesString.resize(nSpw);
+
+ Int nPols(polc.nrow());
+ Vector<Int> stokes(4);
+ for (Int i=0;i<nSpw;i++) {
+
spwc.name().get(i,spWindowName[i]);
+ spwc.numChan().get(i,nChan[i]);
+ Double vStartFreq,vBW; //vFreqInc
+ spwc.refFrequency().get(i,vStartFreq);
+ startFreq[i].setValue(vStartFreq);
+ startFreq[i].setUnit("Hz");
+ spwc.totalBandwidth().get(i,vBW);
+ // yeah, ok - maybe they're not uniform. we're doing what we can
here.x
+ freqInc[i].setValue(vBW/nChan[i]);
+ freqInc[i].setUnit("Hz");
+ // need to translate enum Stokes::type back into strings... there's no
+ // easy way to do that in C++, but there is a Stokes Name function:
+ Int nCorr;
+ if (nPols==nSpw) {
+ polc.numCorr().get(i, nCorr);
+ stokes.resize(nCorr);
+ polc.corrType().get(i,stokes);
+ } else if (nPols<=0) {
+ throw(AipsError("Polarations not defined in
MSSimulator::getSpWindows"));
+ } else {
+ // if not specified for all spw, use the first one for all spw.
+ polc.numCorr().get(0, nCorr);
+ stokes.resize(nCorr);
+ polc.corrType().get(0,stokes);
+ }
+ String t;
+ for (Int j=0; j<nCorr; j++)
+ t += Stokes::name(Stokes::StokesTypes(stokes(j))) + " ";
+ stokesString[i]=t;
+ }
+ return True;
+}
+
+
+
+
+void NewMSSimulator::initFeeds(const String& mode) {
+ LogIO os(LogOrigin("MSsimulator", "initFeeds()", WHERE));
+ if(mode=="list") {
+ os << "Mode list not supported without x,y,pol set" <<
LogIO::EXCEPTION;
+ }
+
+ Vector<Double> x;
+ Vector<Double> y;
+ Vector<String> pol;
+ initFeeds(mode, x, y, pol);
+}
+
+// NOTE: initAnt and initSpWindows must be called before this one!
+void NewMSSimulator::initFeeds(const String& mode,
+ const Vector<Double>& x,
+ const Vector<Double>& y,
+ const Vector<String>& pol)
+{
+ LogIO os(LogOrigin("MSsimulator", "initFeeds()", WHERE));
+
+ MSColumns msc(*ms_p);
+ MSAntennaColumns& antc=msc.antenna();
+ Int nAnt=antc.nrow();
+
+ if (nAnt <= 0) {
+ os << LogIO::SEVERE << "NewMSSimulator::initFeeds: must call
initAnt() first" << LogIO::POST;
+ }
+
+ Int nFeed=x.nelements();
+
+ // cout << "nFeed = " << nFeed << endl;
+
+ String feedPol0="R", feedPol1="L";
+ Bool isList=False;
+ if(nFeed>1) {
+ isList=True;
+ if(x.nelements()!=y.nelements()) {
+ os << "Feed x and y must be the same length" << LogIO::EXCEPTION;
+ }
+ if(pol.nelements()!=x.nelements()) {
+ os << "Feed polarization list must be same length as the number of
positions" << LogIO::EXCEPTION;
+ }
+ os << "Constructing FEED table from list" << LogIO::POST;
+ }
+ else {
+ nFeed=1;
+ // mode == "perfect R L" OR "perfect X Y"
+ if (mode.contains("X", 0)) {
+ feedPol0 = "X";
+ feedPol1 = "Y";
+ }
+ }
+
+ //cout << "Mode in initFeeds = " << mode << endl;
+ //cout << "feedPol0,1 = " << feedPol0 << " " << feedPol1 << endl;
+
+ Int nRow=nFeed*nAnt;
+ Vector<Int> feedAntId(nRow);
+ Vector<Int> feedId(nRow);
+ Vector<Int> feedSpWId(nRow);
+ Vector<Int> feedBeamId(nRow);
+
+ Vector<Int> feedNumRec(nRow);
+ Cube<Double> beamOffset(2,2,nRow);
+
+ Matrix<String> feedPol(2,nRow);
+ Matrix<Double> feedXYZ(3,nRow);
+ Matrix<Double> feedAngle(2,nRow);
+ Cube<Complex> polResp(2,2,nRow);
+
+ Int iRow=0;
+ if(isList) {
+ polResp=Complex(0.0,0.0);
+ for (Int i=0; i<nAnt; i++) {
+ for (Int j=0; j<nFeed; j++) {
+ feedAntId(iRow)=i;
+ feedId(iRow) = j;
+ feedSpWId(iRow) = -1;
+ feedBeamId(iRow) = -1;
+ feedNumRec(iRow) = 2;
+ beamOffset(0,0,iRow) = x(j);
+ beamOffset(1,0,iRow) = y(j);
+ beamOffset(0,1,iRow) = x(j);
+ beamOffset(1,1,iRow) = y(j);
+ feedXYZ(0,iRow) = 0.0;
+ feedXYZ(1,iRow) = 0.0;
+ feedXYZ(2,iRow) = 0.0;
+ feedAngle(0,iRow) = 0.0;
+ feedAngle(1,iRow) = 0.0;
+ if (pol(j).contains("X", 0)) {
+ feedPol(0, iRow) = "X";
+ feedPol(1, iRow) = "Y";
+ }
+ else {
+ feedPol(0, iRow) = "L";
+ feedPol(1, iRow) = "R";
+ }
+ polResp(0,0,iRow)=polResp(1,1,iRow)=Complex(1.0,0.0);
+ os << "Row " << iRow+1 << " : Feed " << j+1 << " on antenna "
+ << i+1 << " "
+ << x(j) << " " << y(j) << " " << pol(j) << LogIO::POST;
+ iRow++;
+ }
+ }
+ }
+ else {
+ polResp=Complex(0.0,0.0);
+ for (Int i=0; i<nAnt; i++) {
+ feedAntId(iRow)=i;
+ feedId(iRow) = 0;
+ feedSpWId(iRow) = -1;
+ feedBeamId(iRow) = -1;
+ feedNumRec(iRow) = 2;
+ beamOffset(0,0,iRow) = 0.0;
+ beamOffset(1,0,iRow) = 0.0;
+ beamOffset(0,1,iRow) = 0.0;
+ beamOffset(1,1,iRow) = 0.0;
+ feedXYZ(0,iRow) = 0.0;
+ feedXYZ(1,iRow) = 0.0;
+ feedXYZ(2,iRow) = 0.0;
+ feedAngle(0,iRow) = 0.0;
+ feedAngle(1,iRow) = 0.0;
+ feedPol(0, iRow) = feedPol0;
+ feedPol(1, iRow) = feedPol1;
+ polResp(0,0,iRow)=polResp(1,1,iRow)=Complex(1.0,0.0);
+ iRow++;
+ }
+ }
+
+ // fill Feed table - don't check to see if any of the positions match
+ MSFeedColumns& feedc=msc.feed();
+ Int numFeeds=feedc.nrow();
+ Slicer feedSlice(IPosition(1,numFeeds),IPosition(1, nRow+numFeeds-1),
+ IPosition(1,1), Slicer::endIsLast);
+ ms_p->feed().addRow(nRow);
+ feedc.antennaId().putColumnRange(feedSlice,feedAntId);
+ feedc.feedId().putColumnRange(feedSlice,feedId);
***The diff for this file has been truncated for email.***
=======================================
--- /dev/null
+++ /branches/nov14/ms/MSOper/NewMSSimulator.h Wed Mar 25 14:33:54 2015 UTC
@@ -0,0 +1,292 @@
+//# NewMSSimulator.h: this defines the MeasurementSet Simulator
+//# Copyright (C) 1995-2009
+//# Associated Universities, Inc. Washington DC, USA.
+//#
+//# This library is free software; you can redistribute it and/or modify it
+//# under the terms of the GNU Library General Public License as published
by
+//# the Free Software Foundation; either version 2 of the License, or (at
your
+//# option) any later version.
+//#
+//# This library is distributed in the hope that it will be useful, but
WITHOUT
+//# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+//# FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
+//# License for more details.
+//#
+//# You should have received a copy of the GNU Library General Public
License
+//# along with this library; if not, write to the Free Software Foundation,
+//# Inc., 675 Massachusetts Ave, Cambridge, MA 02139, USA.
+//#
+//# Correspondence concerning AIPS++ should be addressed as follows:
+//# Internet email:
aips2-...@nrao.edu.
+//# Postal address: AIPS++ Project Office
+//# National Radio Astronomy Observatory
+//# 520 Edgemont Road
+//# Charlottesville, VA 22903-2475 USA
+//#
+//# $Id$
+
+#ifndef MS_NEWMSSIMULATOR_H
+#define MS_NEWMSSIMULATOR_H
+
+
+//# Includes
+#include <casacore/casa/aips.h>
+#include <casacore/casa/BasicSL/String.h>
+#include <casacore/casa/Arrays/Vector.h>
+#include <casacore/casa/Arrays/Matrix.h>
+#include <casacore/casa/Arrays/Cube.h>
+#include <casacore/casa/BasicSL/Complex.h>
+#include <casacore/casa/Quanta/Quantum.h>
+#include <casacore/measures/Measures/MPosition.h>
+#include <casacore/measures/Measures/MEpoch.h>
+#include <casacore/measures/Measures/MFrequency.h>
+#include <casacore/measures/Measures/MDirection.h>
+
+#include <casacore/tables/DataMan/TiledDataStManAccessor.h>
+
+namespace casacore { //# NAMESPACE CASACORE - BEGIN
+
+//# Forward Declarations
+class MeasurementSet;
+
+// <category lib=aips module="ModuleName">
+// <summary> Create an empty MeasurementSet from observation and telescope
descriptions. </summary>
+// <reviewed reviewer="" date="" tests="">
+//
+// <prerequisite>
+//# Classes you should understand before using this one.
+// <li> MeasurementSet
+// </prerequisite>
+//
+// <etymology>
+// MS is from MeasurementSet, Simulator refers to the generation of
+// 'fake' data from a set of parameters for instrument and sources.
+// </etymology>
+//
+// <synopsis>
+// This class creates a MeasurementSet from a set of parameters for
instrument
+// and sources. It does not simulate the data, only the coordinates of a
+// measurement. The application "simulator" uses this class to create a
true
+// simulated MS with perfect or corrupted data.
+// </synopsis>
+//
+// <motivation>
+// To test calibration and imaging programs it is necessary to have
flawless
+// data and data with errors that are known exactly. This class generates
+// empty MeasurementSets (only coordinates filled in) that can be filled
+// with predicted data.
+// </motivation>
+//
+// <todo asof="$DATE:$">
+//# A List of bugs, limitations, extensions or planned refinements.
+// <li> The amount of information to be specified by the user
+// could be much larger. For the moment it has been restricted to
+// what is needed for testing the synthesis imaging code. Already
+// it is possible to create MeasurementSets that cannot be
processed
+// yet.
+// </todo>
+
+class NewMSSimulator
+{
+public:
+
+ // Constructor from name only
+ NewMSSimulator(const String&);
+
+ // Constructor from existing MS
+ NewMSSimulator(MeasurementSet&);
+
+ // Copy constructor - for completeness only
+ NewMSSimulator(const NewMSSimulator & mss);
+
+ //# Destructor
+ ~NewMSSimulator();
+
+//# Operators
+ // Assignment
+ NewMSSimulator & operator=(const NewMSSimulator &);
+
+ // Set maximum amount of data (bytes) to be written into any one
+ // scratch column hypercube
+ void setMaxData(const Double maxData=2e9) {maxData_p=maxData;}
+
+ // set the antenna and array data. These are written immediately to the
+ // existing MS. The same model is used for the other init infor.
+ void initAnt(const String& telname,
+ const Vector<Double>& x,
+ const Vector<Double>& y,
+ const Vector<Double>& z,
+ const Vector<Double>& dishDiameter,
+ const Vector<Double>& offset,
+ const Vector<String>& mount,
+ const Vector<String>& name,
+ const Vector<String>& padname,
+ const String& coordsystem,
+ const MPosition& mRefLocation);
+ // get the info back
+ bool getAnt(String& telescope, Int& nAnt, Matrix<Double>* antXYZ,
+ Vector<Double>& antDiam, Vector<Double>& offset,
+ Vector<String>& mount, Vector<String>& name, Vector<String>&
padname,
+ String& coordsystem, MPosition& mRefLocation );
+
+ // set the observed fields
+ void initFields(const String& sourceName,
+ const MDirection& sourceDirection,
+ const String& calCode);
+
+ bool getFields(Int& nField,
+ Vector<String>& sourceName,
+ Vector<MDirection>& sourceDirection,
+ Vector<String>& calCode);
+
+ // set the Feeds; brain dead version
+ void initFeeds(const String& mode);
+
+ bool getFeedMode(String& mode);
+
+ // set the Feeds; Smart version
+ void initFeeds(const String& mode,
+ const Vector<Double>& x,
+ const Vector<Double>& y,
+ const Vector<String>& pol);
+
+ // set the spectral windows information
+ void initSpWindows(const String& spWindowName,
+ const Int& nChan,
+ const Quantity& startFreq,
+ const Quantity& freqInc,
+ const Quantity& freqRes,
+ const MFrequency::Types& freqType,
+ const String& stokesString);
+
+ bool getSpWindows(Int& nSpw,
+ Vector<String>& spWindowName,
+ Vector<Int>& nChan,
+ Vector<Quantity>& startFreq,
+ Vector<Quantity>& freqInc,
+ Vector<String>& stokesString);
+
+ void setFractionBlockageLimit(const Double fraclimit)
+ { fractionBlockageLimit_p = fraclimit; }
+
+ void setElevationLimit(const Quantity& ellimit)
+ { elevationLimit_p = ellimit; }
+
+ void setAutoCorrelationWt(const Float autocorrwt)
+ { autoCorrelationWt_p = autocorrwt; }
+
+ void settimes(const Quantity& qIntegrationTime,
+ const Bool useHourAngles,
+ const MEpoch& mRefTime);
+
+ void observe(const String& sourceName,
+ const String& spWindowName,
+ const Quantity& qStartTime,
+ const Quantity& qStopTime,
+ const Bool add_observation=True,
+//# from int ASDM2MSFiller::addUniqueState(
+//# defaults for ALMA as known on 20100831
+ const Bool state_sig=True,
+ const Bool state_ref=True,
+ const double& state_cal=0.,
+ const double& state_load=0.,
+ const unsigned int state_sub_scan=1,
+ const String& state_obs_mode="OBSERVE_TARGET.ON_SOURCE",
+ const String& observername="CASA simulator",
+ const String& projectname="CASA simulation");
+
+
+ void observe(const Vector<String>& sourceNames,
+ const String& spWindowName,
+ const Vector<Quantity>& qStartTimes,
+ const Vector<Quantity>& qStopTimes,
+ const Vector<MDirection>& directions,
+ const Bool add_observation=True,
+//# from int ASDM2MSFiller::addUniqueState(
+//# defaults for ALMA as known on 20100831
+ const Bool state_sig=True,
+ const Bool state_ref=True,
+ const double& state_cal=0.,
+ const double& state_load=0.,
+ const unsigned int state_sub_scan=1,
+ const String& state_obs_mode="OBSERVE_TARGET.ON_SOURCE",
+ const String& observername="CASA simulator",
+ const String& projectname="CASA simulation");
+
+ MeasurementSet * getMs () const;
+
+
+private:
+
+ // Prevent use of default constructor
+ NewMSSimulator() {}
+
+//# Data Members
+ Double fractionBlockageLimit_p;
+ Quantity elevationLimit_p;
+ Float autoCorrelationWt_p;
+ String telescope_p;
+ Quantity qIntegrationTime_p;
+ Bool useHourAngle_p;
+ Bool hourAngleDefined_p;
+ MEpoch mRefTime_p;
+ Double t_offset_p;
+ Double dataWritten_p;
+ Int hyperCubeID_p;
+ Bool hasHyperCubes_p;
+ Int lastSpWID_p;
+ Int lastNchan_p;
+
+ MeasurementSet* ms_p;
+
+ TiledDataStManAccessor dataAcc_p, scratchDataAcc_p, sigmaAcc_p,
flagAcc_p;
+
+ Double maxData_p;
+
+ void local2global(Vector<Double>& xReturned,
+ Vector<Double>& yReturned,
+ Vector<Double>& zReturned,
+ const MPosition& mRefLocation,
+ const Vector<Double>& xIn,
+ const Vector<Double>& yIn,
+ const Vector<Double>& zIn);
+
+ void longlat2global(Vector<Double>& xReturned,
+ Vector<Double>& yReturned,
+ Vector<Double>& zReturned,
+ const MPosition& mRefLocation,
+ const Vector<Double>& xIn,
+ const Vector<Double>& yIn,
+ const Vector<Double>& zIn);
+
+ // Returns the fractional blockage of one antenna by another
+ // We will want to put this somewhere else eventually, but I don't yet
know where!
+ // Till then.
+ // fraction1: fraction of antenna 1 that is blocked by 2
+ // fraction2: fraction of antenna 2 that is blocked by 1
+ // hint: at least one of the two will be 0.0
+ void blockage(Double &fraction1, Double &fraction2,
+ const Vector<Double>& uvw, // uvw in same units as diam!
+ const Double diam1, const Double diam2);
+
+ String formatDirection(const MDirection&);
+ String formatTime(const Double);
+
+ void addHyperCubes(const Int id, const Int nBase, const Int nChan, const
Int nCorr);
+
+ void defaults();
+
+ Bool calcAntUVW(MEpoch& epoch, MDirection& refdir,
+ Matrix<Double>& uvwAnt);
+
+
+};
+
+
+} //# NAMESPACE CASACORE - END
+
+#endif
+
+
+
+
=======================================
--- /dev/null
+++ /branches/nov14/ms/MSOper/test/CMakeLists.txt Wed Mar 25 14:33:54 2015
UTC
@@ -0,0 +1,12 @@
+set (tests
+tMSDerivedValues
+tMSMetaData
+tMSReader
+tMSSummary
+)
+
+foreach (test ${tests})
+ add_executable (${test} ${test}.cc)
+ target_link_libraries (${test} casa_ms)
+ add_test (${test} ${CMAKE_SOURCE_DIR}/cmake/cmake_assay ./${test})
+endforeach (test)
=======================================
--- /dev/null
+++ /branches/nov14/ms/MSOper/test/tMSDerivedValues.cc Wed Mar 25 14:33:54
2015 UTC
@@ -0,0 +1,125 @@
+//# tMSDerivedValues: Tests the MSDerivedValues class
+//# Copyright (C) 1997,1998,1999,2000,2001
+//# Associated Universities, Inc. Washington DC, USA.
+//#
+//# This program is free software; you can redistribute it and/or modify it
+//# under the terms of the GNU General Public License as published by the
Free
+//# Software Foundation; either version 2 of the License, or (at your
option)
+//# any later version.
+//#
+//# This program is distributed in the hope that it will be useful, but
WITHOUT
+//# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+//# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for
+//# more details.
+//#
+//# You should have received a copy of the GNU General Public License along
+//# with this program; if not, write to the Free Software Foundation, Inc.,
+//# 675 Massachusetts Ave, Cambridge, MA 02139, USA.
+//#
+//# Correspondence concerning AIPS++ should be addressed as follows:
+//# Internet email:
aips2-...@nrao.edu.
+//# Postal address: AIPS++ Project Office
+//# National Radio Astronomy Observatory
+//# 520 Edgemont Road
+//# Charlottesville, VA 22903-2475 USA
+//#
+//# $Id$
+
+#include <casacore/ms/MSOper/MSDerivedValues.h>
+#include <casacore/casa/iostream.h>
+#include <casacore/casa/iomanip.h>
+#include <casacore/casa/Exceptions/Error.h>
+#include <casacore/casa/Quanta/MVAngle.h>
+#include <casacore/casa/Quanta/MVTime.h>
+#include <casacore/casa/Arrays/ArrayIO.h>
+
+#include <casacore/casa/namespace.h>
+int main()
+{
+ try {
+ Quantity longitude; Quantity::read(longitude,"149.33.00.5");
+ cout << "longitude: "<<MVAngle(longitude)<<endl;
+ Quantity latitude; Quantity::read(latitude,"-30.18.46.385");
+ cout << "latitude : "<<MVAngle(latitude)<<endl;
+ Vector<MPosition> pos(1);
+ pos(0)=MPosition(Quantity(236.9,"m"),longitude,latitude,
+ MPosition::Ref(MPosition::WGS84));
+
+ MSDerivedValues msd;
+ msd.setAntennaPositions(pos);
+
+ Quantity time; MVTime::read(time,"today");
+ MEpoch today(time);
+
+ cout <<" Current time: "<<MVTime(today.getValue())<<endl;
+
+ msd.setEpoch(today);
+
+ MEpoch last = msd.last();
+
+ cout <<" Current last: "<< MVTime(last.getValue())<<endl;
+
+ Quantity ra; Quantity::read(ra,"12:00:00.0");
+ Quantity dec; Quantity::read(dec,"-30.00.00.0");
+ MDirection mySource(ra,dec);
+
+ cout <<" FieldCenter: "<< mySource.getAngle("deg") <<endl;
+
+ msd.setFieldCenter(mySource);
+
+ cout <<" Hour angle : "<< MVAngle(msd.hourAngle()) <<endl;
+
+ cout <<" Az & El : "<< msd.azel().getAngle("deg")<<endl;
+
+ Vector<String> mount(1); mount(0)="alt-az";
+
+ msd.setAntennaMount(mount);
+
+ cout << " Par. angle: "<< MVAngle(msd.parAngle()) << endl;
+
+ // test the obsVel conversion
+
+ cout << " observatory velocity in LSR frame: "<<
msd.obsVel().get("km/s").
+ getValue() << "km/s"<<endl;
+
+ msd.setVelocityFrame(MRadialVelocity::BARY);
+ cout << " observatory velocity in BARY frame: "<<
msd.obsVel().get("km/s").
+ getValue() << "km/s"<<endl;
+
+
+ msd.setVelocityFrame(MRadialVelocity::GEO);
+ cout << " observatory velocity in GEO frame: "<<
msd.obsVel().get("km/s").
+ getValue() << "km/s"<<endl;
+
+ Quantity restFreq(1.42041,"GHz");
+ Quantity radioVel(2196.25,"km/s");
+ msd.setVelocityReference(MDoppler::RADIO);
+ msd.setFrequencyReference(MFrequency::TOPO);
+ cout << "radio velocity " << radioVel << " is frequency " <<
+ msd.toFrequency(radioVel, restFreq) << endl;
+ //====
+ /*
+ MSDerivedValues msd1;
+ MeasurementSet
ms("/home/rohir/kgolap/Regression/ALMATST1/NGC5921/
ngc5921.ms");
+ msd1.setMeasurementSet(ms);
+ msd1.setVelocityReference(MDoppler::RADIO);
+ msd1.setFrequencyReference(MFrequency::LSRK);
+ //locate restFrequency for field 0 and spwid 0
+ Bool hasRestFreq=msd1.setRestFrequency(0,0);
+ if(!hasRestFreq){
+ cout << "Ou la la .....has no restfrequency in this ms" << endl;
+ }
+ else{
+ cout << "radio velocity " << radioVel << " is frequency " <<
+ msd1.toFrequency(radioVel) << endl;
+ }
+ */
+
+ } catch (AipsError x) {
+ cout << "Caught exception " << endl;
+ cout << x.getMesg() << endl;
+ return 1;
+ }
+ cout << "Done." << endl;
+ return 0;
+}
=======================================
--- /dev/null
+++ /branches/nov14/ms/MSOper/test/tMSMetaData.cc Wed Mar 25 14:33:54 2015
UTC
@@ -0,0 +1,1488 @@
+//# tMSMetaData.cc: This program tests the MSMetaData class
+//# Copyright (C) 2013
+//# Associated Universities, Inc. Washington DC, USA.
+//#
+//# This program is free software; you can redistribute it and/or modify it
+//# under the terms of the GNU General Public License as published by the
Free
+//# Software Foundation; either version 2 of the License, or (at your
option)
+//# any later version.
+//#
+//# This program is distributed in the hope that it will be useful, but
WITHOUT
+//# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+//# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for
+//# more details.
+//#
+//# You should have received a copy of the GNU General Public License along
+//# with this program; if not, write to the Free Software Foundation, Inc.,
+//# 675 Massachusetts Ave, Cambridge, MA 02139, USA.
+//#
+//# Correspondence concerning AIPS++ should be addressed as follows:
+//# Internet email:
aips2-...@nrao.edu.
+//# Postal address: AIPS++ Project Office
+//# National Radio Astronomy Observatory
+//# 520 Edgemont Road
+//# Charlottesville, VA 22903-2475 USA
+//#
+//# $Id$
+
+#include <casacore/casa/aips.h>
+
+#include <casacore/ms/MSOper/MSMetaData.h>
+
+#include <casacore/casa/BasicMath/StdLogical.h>
+#include <casacore/casa/Containers/Record.h>
+#include <casacore/casa/OS/Directory.h>
+#include <casacore/casa/OS/EnvVar.h>
+#include <casacore/casa/Quanta/QLogical.h>
+#include <casacore/ms/MSOper/MSKeys.h>
+#include <casacore/ms/MeasurementSets/MeasurementSet.h>
+#include <casacore/measures/Measures/MDirection.h>
+
+#include <casacore/casa/BasicSL/STLIO.h>
+#include <iomanip>
+
+#include <casacore/casa/namespace.h>
+
+void _printSet(const std::set<uInt>& set) {
+ const std::set<uInt>::const_iterator end = set.end();
+ for (
+ std::set<uInt>::const_iterator iter = set.begin();
+ iter!=end; ++iter
+ ) {
+ if (iter!=set.begin()) {
+ cout << ", ";
+ }
+ cout << *iter;
+ }
+ cout << endl;
+}
+
+void _printSet(const std::set<String>& set) {
+ const std::set<String>::const_iterator end = set.end();
+ for (
+ std::set<String>::const_iterator iter = set.begin();
+ iter!=end; ++iter
+ ) {
+ if (iter!=set.begin()) {
+ cout << ", ";
+ }
+ cout << *iter;
+ }
+ cout << endl;
+}
+
+void testIt(MSMetaData& md) {
+ ArrayKey arrayKey;
+ arrayKey.obsID = 0;
+ arrayKey.arrayID = 0;
+ cout << "*** test nStates()" << endl;
+ AlwaysAssert(md.nStates() == 43, AipsError);
+ cout << "*** cache size " << md.getCache() << endl;
+
+ cout << "*** test getScansForState()" << endl;
+ for (uInt stateID=0; stateID<md.nStates(); ++stateID) {
+ std::set<Int> scans = md.getScansForState(stateID, 0, 0);
+ std::set<Int> expec;
+ if (stateID < 5) {
+ uInt myints[]= {1, 5, 8};
+ expec.insert(myints, myints + 3);
+ }
+ else if (stateID < 7) {
+ expec.insert(2);
+ }
+ else if (stateID < 10) {
+ uInt myints[]= {3, 6, 9, 11, 13, 15, 17, 19, 22, 24, 26, 29, 31};
+ expec.insert(myints, myints + 13);
+ }
+ else if (stateID < 26) {
+ expec.insert(4);
+ }
+ else if (stateID < 32) {
+ expec.insert(7);
+ }
+ else if (stateID < 33) {
+ uInt myints[] = {10, 14, 18, 21, 25, 28, 32};
+ expec.insert(myints, myints + 7);
+ }
+ else if (stateID < 37) {
+ uInt myints[] = {12, 16, 20, 23, 27, 30};
+ expec.insert(myints, myints + 6);
+ }
+ else {
+ uInt myints[] = {12, 16, 20, 23};
+ expec.insert(myints, myints + 4);
+ }
+ AlwaysAssert(scans == expec, AipsError);
+ }
+ cout << "*** cache size " << md.getCache() << endl;
+
+ cout << "*** test getIntents()" << endl;
+ cout << "*** size " << md.getIntents().size() << endl;
+ cout << "*** size " << md.getIntents().size() << endl;
+
+ AlwaysAssert(md.getIntents().size() == 11, AipsError);
+ cout << "*** cache size " << md.getCache() << endl;
+
+ cout << "*** test getScanNumbers()" << endl;
+ std::set<Int> scans = md.getScanNumbers(0, 0);
+ uInt myints[] = {
+ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17,
+ 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32
+ };
+ {
+ std::set<Int> exp;
+ exp.insert(myints, myints+32);
+ AlwaysAssert(scans == exp, AipsError);
+ cout << "*** cache size " << md.getCache() << endl;
+ }
+ std::set<String> uniqueIntents;
+ cout << "*** test getIntentsForScan()" << endl;
+ ScanKey scanKey;
+ scanKey.obsID = 0;
+ scanKey.arrayID = 0;
+ for (
+ std::set<Int>::const_iterator scanNum = scans.begin();
+ scanNum!=scans.end(); ++scanNum
+ ) {
+ scanKey.scan = *scanNum;
+ std::set<String> intents = md.getIntentsForScan(scanKey);
+ std::set<String> exp;
+
+ if (*scanNum == 1 || *scanNum == 5 || *scanNum == 8) {
+ String mystr[] = {
+ "CALIBRATE_POINTING#ON_SOURCE", "CALIBRATE_WVR#ON_SOURCE"
+ };
+ exp.insert(mystr, mystr+2);
+ }
+ else if (*scanNum == 2) {
+ String mystr[] = {
+ "CALIBRATE_SIDEBAND_RATIO#OFF_SOURCE",
+ "CALIBRATE_SIDEBAND_RATIO#ON_SOURCE",
+ "CALIBRATE_WVR#OFF_SOURCE",
+ "CALIBRATE_WVR#ON_SOURCE"
+ };
+ exp.insert(mystr, mystr+4);
+ }
+ else if (
+ *scanNum == 3 || *scanNum == 6
+ || *scanNum == 9 || *scanNum == 11
+ || *scanNum == 13 || *scanNum == 15
+ || *scanNum == 17 || *scanNum == 19
+ || *scanNum == 22 || *scanNum == 24
+ || *scanNum == 26 || *scanNum == 29
+ || *scanNum == 31
+ ) {
+ String mystr[] = {
+ "CALIBRATE_ATMOSPHERE#OFF_SOURCE",
+ "CALIBRATE_ATMOSPHERE#ON_SOURCE",
+ "CALIBRATE_WVR#OFF_SOURCE",
+ "CALIBRATE_WVR#ON_SOURCE"
+ };
+ exp.insert(mystr, mystr+4);
+ }
+ else if (*scanNum == 4) {
+ String mystr[] = {
+ "CALIBRATE_BANDPASS#ON_SOURCE",
+ "CALIBRATE_PHASE#ON_SOURCE",
+ "CALIBRATE_WVR#ON_SOURCE"
+ };
+ exp.insert(mystr, mystr+3);
+ }
+ else if (*scanNum == 7) {
+ String mystr[] = {
+ "CALIBRATE_AMPLI#ON_SOURCE",
+ "CALIBRATE_PHASE#ON_SOURCE",
+ "CALIBRATE_WVR#ON_SOURCE"
+ };
+ exp.insert(mystr, mystr+3);
+ }
+ else if (
+ *scanNum == 10 || *scanNum == 14
+ || *scanNum == 18 || *scanNum == 21
+ || *scanNum == 25 || *scanNum == 28
+ || *scanNum == 32
+ ) {
+ String mystr[] = {
+ "CALIBRATE_PHASE#ON_SOURCE",
+ "CALIBRATE_WVR#ON_SOURCE"
+ };
+ exp.insert(mystr, mystr+2);
+ }
+ else if (
+ *scanNum == 12 || *scanNum == 16
+ || *scanNum == 20 || *scanNum == 23
+ || *scanNum == 27 || *scanNum == 30
+ ) {
+ exp.insert("OBSERVE_TARGET#ON_SOURCE");
+ }
+ uniqueIntents.insert(exp.begin(), exp.end());
+ AlwaysAssert(intents == exp, AipsError);
+ }
+ AlwaysAssert(md.getIntents() == uniqueIntents, AipsError);
+ cout << "*** test getSpwsForIntent()" << endl;
+ for (
+ std::set<String>::const_iterator intent=uniqueIntents.begin();
+ intent!=uniqueIntents.end(); ++intent
+ ) {
+ std::set<uInt> exp;
+ if (
+ *intent == "CALIBRATE_AMPLI#ON_SOURCE"
+ || *intent == "CALIBRATE_BANDPASS#ON_SOURCE"
+ || *intent == "CALIBRATE_PHASE#ON_SOURCE"
+ || *intent == "OBSERVE_TARGET#ON_SOURCE"
+ ) {
+ uInt myints[] = {0, 17, 18, 19, 20, 21, 22, 23, 24};
+ exp.insert(myints, myints+9);
+ }
+ else if (
+ *intent == "CALIBRATE_ATMOSPHERE#OFF_SOURCE"
+ || *intent == "CALIBRATE_ATMOSPHERE#ON_SOURCE"
+ || *intent == "CALIBRATE_SIDEBAND_RATIO#OFF_SOURCE"
+ || *intent == "CALIBRATE_SIDEBAND_RATIO#ON_SOURCE"
+ || *intent == "CALIBRATE_WVR#OFF_SOURCE"
+ ) {
+ uInt myints[] = {0, 9, 10, 11, 12, 13, 14, 15, 16};
+ exp.insert(myints, myints+9);
+ }
+ else if (
+ *intent == "CALIBRATE_POINTING#ON_SOURCE"
+ ) {
+ uInt myints[] = {0, 1, 2, 3, 4, 5, 6, 7, 8};
+ exp.insert(myints, myints+9);
+ }
+ else if (
+ *intent == "CALIBRATE_WVR#ON_SOURCE"
+ ) {
+ uInt myints[] = {
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
+ 10, 11, 12, 13, 14, 15, 16,
+ 17, 18, 19, 20, 21, 22, 23, 24
+ };
+ exp.insert(myints, myints+25);
+ }
+ AlwaysAssert(md.getSpwsForIntent(*intent) == exp, AipsError);
+ }
+ cout << "*** test nSpw()" << endl;
+ uInt nSpw = md.nSpw(True);
+ AlwaysAssert(nSpw == 40, AipsError);
+ AlwaysAssert(md.nSpw(False) == 24, AipsError);
+ cout << "*** test getIntentsForSpw()" << endl;
+ for (uInt spw=0; spw<nSpw; ++spw) {
+ std::set<String> exp;
+ if (spw == 0) {
+ String mystr[] = {
+ "CALIBRATE_AMPLI#ON_SOURCE",
+ "CALIBRATE_ATMOSPHERE#OFF_SOURCE",
+ "CALIBRATE_ATMOSPHERE#ON_SOURCE",
+ "CALIBRATE_BANDPASS#ON_SOURCE",
+ "CALIBRATE_PHASE#ON_SOURCE",
+ "CALIBRATE_POINTING#ON_SOURCE",
+ "CALIBRATE_SIDEBAND_RATIO#OFF_SOURCE",
+ "CALIBRATE_SIDEBAND_RATIO#ON_SOURCE",
+ "CALIBRATE_WVR#OFF_SOURCE",
+ "CALIBRATE_WVR#ON_SOURCE",
+ "OBSERVE_TARGET#ON_SOURCE"
+ };
+ exp.insert(mystr, mystr+11);
+ }
+ else if (spw < 9) {
+ String mystr[] = {
+ "CALIBRATE_POINTING#ON_SOURCE",
+ "CALIBRATE_WVR#ON_SOURCE"
+ };
+ exp.insert(mystr, mystr+2);
+ }
+ else if (spw < 17) {
+ String mystr[] = {
+ "CALIBRATE_ATMOSPHERE#OFF_SOURCE",
+ "CALIBRATE_ATMOSPHERE#ON_SOURCE",
+ "CALIBRATE_SIDEBAND_RATIO#OFF_SOURCE",
+ "CALIBRATE_SIDEBAND_RATIO#ON_SOURCE",
+ "CALIBRATE_WVR#OFF_SOURCE",
+ "CALIBRATE_WVR#ON_SOURCE"
+ };
+ exp.insert(mystr, mystr+6);
+ }
+ else if (spw < 25) {
+ String mystr[] = {
+ "CALIBRATE_AMPLI#ON_SOURCE",
+ "CALIBRATE_BANDPASS#ON_SOURCE",
+ "CALIBRATE_PHASE#ON_SOURCE",
+ "CALIBRATE_WVR#ON_SOURCE",
+ "OBSERVE_TARGET#ON_SOURCE"
+ };
+ exp.insert(mystr, mystr+5);
+ }
+ AlwaysAssert(md.getIntentsForSpw(spw) == exp, AipsError);
+ }
+ {
+ cout << "*** test nFields()" << endl;
+ uInt nFields = md.nFields();
+ AlwaysAssert(nFields == 6, AipsError);
+ cout << "*** test getSpwsForField()" << endl;
+ String names[] = {
+ "3C279", "J1337-129", "Titan",
+ "J1625-254", "V866 Sco", "RNO 90"
+ };
+ for (uInt i=0; i<nFields; ++i) {
+ std::set<uInt> exp;
+ if (i==0 || i==3) {
+ uInt myints[] = {
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
+ 10, 11, 12, 13, 14, 15, 16, 17,
+ 18, 19, 20, 21, 22, 23, 24
+ };
+ exp.insert(myints, myints+25);
+ }
+ if (i == 1) {
+ uInt myints[] = {
+ 0, 1, 2, 3, 4, 5, 6, 7, 8
+ };
+ exp.insert(myints, myints+9);
+ }
+ if (i==2 || i==4 || i==5) {
+ uInt myints[] = {
+ 0, 9, 10, 11, 12, 13, 14, 15, 16,
+ 17, 18, 19, 20, 21, 22, 23, 24
+ };
+ exp.insert(myints, myints+17);
+ }
+ cout << "*** i " << i << " " << md.getSpwsForField(i) << endl;
+ AlwaysAssert(md.getSpwsForField(i) == exp, AipsError);
+ AlwaysAssert(md.getSpwsForField(names[i]) == exp, AipsError);
+ cout << "*** cache size " << md.getCache() << endl;
+
+ }
+ cout << "*** test getFieldIDsForSpw()" << endl;
+ for (uInt i=0; i<md.nSpw(True); ++i) {
+ std::set<Int> exp;
+ std::set<String> expNames;
+ if (i==0) {
+ uInt myints[] = {0, 1, 2, 3, 4, 5};
+ exp.insert(myints, myints+6);
+ String mystr[] = {
+ "3C279", "J1337-129", "Titan", "J1625-254",
+ "V866 Sco", "RNO 90"
+ };
+ expNames.insert(mystr, mystr+6);
+
+ }
+ else if (i<9) {
+ uInt myints[] = {0, 1, 3};
+ exp.insert(myints, myints+3);
+ String mystr[] = {
+ "3C279", "J1337-129", "J1625-254"
+ };
+ expNames.insert(mystr, mystr+3);
+ }
+ else if (i<25) {
+ uInt myints[] = {0, 2, 3, 4, 5};
+ exp.insert(myints, myints+5);
+ String mystr[] = {
+ "3C279", "Titan", "J1625-254",
+ "V866 Sco", "RNO 90"
+
+ };
+ expNames.insert(mystr, mystr+5);
+ }
+ else {
+ // nothing, exp is an empty set
+ }
+ AlwaysAssert(md.getFieldIDsForSpw(i) == exp, AipsError);
+ AlwaysAssert(md.getFieldNamesForSpw(i) == expNames, AipsError);
+ }
+ }
+ {
+ cout << "*** test nScans()" << endl;
+ cout << "nscans " << md.nScans() << endl;
+ AlwaysAssert(md.nScans() == 32, AipsError);
+ std::set<Int> scanNumbers = md.getScanNumbers(0, 0);
+ cout << "*** test getSpwsForScan() and getPolarizationIDs()" << endl;
+ ScanKey scanKey;
+ scanKey.obsID = 0;
+ scanKey.arrayID = 0;
+ for (
+ std::set<Int>::const_iterator scan=scanNumbers.begin();
+ scan!=scanNumbers.end(); ++scan
+ ) {
+ std::set<uInt> exp;
+ if (*scan == 1 || *scan==5 || *scan==8) {
+ uInt myints[] = {
+ 0, 1, 2, 3, 4, 5, 6, 7, 8
+ };
+ exp.insert(myints, myints+9);
+ }
+ else if (
+ *scan == 2 || *scan==3 || *scan==6 || *scan==9
+ || *scan==11 || *scan==13 || *scan==15 || *scan==17
+ || *scan==19 || *scan==22 || *scan==24 || *scan==26
+ || *scan==29 || *scan==31
+ ) {
+ uInt myints[] = {
+ 0, 9, 10, 11, 12, 13, 14, 15, 16
+ };
+ exp.insert(myints, myints+9);
+ }
+ else if (
+ *scan==4 || *scan==7 || *scan==10 || *scan==12
+ || *scan==14 || *scan==16 || *scan==18 || *scan==20
+ || *scan==21 || *scan==23 || *scan==25 || *scan==27
+ || *scan==28 || *scan==30 || *scan==32
+ ) {
+ uInt myints[] = {
+ 0, 17, 18, 19, 20, 21, 22, 23, 24
+ };
+ exp.insert(myints, myints+9);
+ }
+ scanKey.scan = *scan;
+ AlwaysAssert(md.getSpwsForScan(scanKey) == exp, AipsError);
+ for (
+ std::set<uInt>::const_iterator spw=exp.begin();
+ spw!=exp.end(); ++spw
+ ) {
+ std::set<uInt> exppols;
+ std::set<uInt> pols = md.getPolarizationIDs(0, 0, *scan, *spw);
+ if (*spw == 0) {
+ exppols.insert(1);
+ }
+ else {
+ exppols.insert(0);
+ }
+ AlwaysAssert(pols == exppols, AipsError);
+ }
+ }
+ cout << "*** test getScansForSpw()" << endl;
+ for (uInt i=0; i<md.nSpw(True); ++i) {
+ std::set<Int> exp;
+ if (i==0) {
+ Int myints[] = {
+ 1, 2, 3, 4, 5, 6, 7, 8, 9,
+ 10, 11, 12, 13, 14, 15, 16, 17, 18,
+ 19, 20, 21, 22, 23, 24, 25, 26, 27,
+ 28, 29, 30, 31, 32
+ };
+ exp.insert(myints, myints+32);
+ }
+ else if (i<9) {
+ Int myints[] = {1, 5, 8};
+ exp.insert(myints, myints+3);
+ }
+ else if (i<17) {
+ Int myints[] = {
+ 2, 3, 6, 9, 11, 13, 15,
+ 17, 19, 22, 24, 26, 29, 31
+ };
+ exp.insert(myints, myints+14);
+ }
+ else if (i<25) {
+ Int myints[] = {
+ 4, 7, 10, 12, 14, 16, 18,
+ 20, 21, 23, 25, 27, 28, 30, 32
+ };
+ exp.insert(myints, myints+15);
+ }
+ else {
+ // empty set
+ }
+ AlwaysAssert(md.getScansForSpw(i, 0, 0) == exp, AipsError);
+ }
+ {
+ cout << "*** test nAntennas()" << endl;
+ AlwaysAssert(md.nAntennas()==15, AipsError);
+ cout << "*** test getAntennaName()" << endl;
+ String name;
+ String expnames[] = {
+ "DA43", "DA44", "DV02", "DV03", "DV05",
+ "DV07", "DV08", "DV10", "DV12", "DV13",
+ "DV14", "DV15", "DV16", "DV17", "DV18"
+ };
+ for (uInt i=0; i<md.nAntennas(); ++i) {
+ vector<uInt> ids(1);
+ ids[0] = i;
+ std::map<String, uInt> mymap;
+ AlwaysAssert(
+ md.getAntennaNames(mymap, ids)[0] == expnames[i],
+ AipsError
+ );
+ }
+ cout << "*** test getAntennaID()" << endl;
+ std::map<String, uInt> mymap;
+ for (uInt i=0; i<md.nAntennas(); ++i) {
+ vector<uInt> ids(1);
+ ids[0] = i;
+ AlwaysAssert(
+ md.getAntennaIDs(md.getAntennaNames(mymap, ids))[0]==i,
+ AipsError
+ );
+ }
+ }
+ {
+ cout << "*** test getTDMSpw()" << endl;
+ std::set<uInt> exp;
+ uInt myints[] = {1, 3, 5, 7, 9, 11, 13, 15};
+ exp.insert(myints, myints+8);
+ AlwaysAssert(md.getTDMSpw() == exp, AipsError);
+ }
+ {
+ cout << "*** test getFDMSpw()" << endl;
+ std::set<uInt> exp;
+ uInt myints[] = {17, 19, 21, 23};
+ exp.insert(myints, myints+4);
+ AlwaysAssert(md.getFDMSpw() == exp, AipsError);
+ }
+ {
+ cout << "*** test getChannelAvgSpw()" << endl;
+ std::set<uInt> exp;
+ uInt myints[] = {
+ 2, 4, 6, 8, 10, 12, 14,
+ 16, 18, 20, 22, 24
+ };
+ exp.insert(myints, myints+12);
+ AlwaysAssert(md.getChannelAvgSpw() == exp, AipsError);
+ }
+ {
+ cout << "*** test getWVRSpw()" << endl;
+ std::set<uInt> exp;
+ uInt myints[] = {
+ 0, 25, 26, 27, 28, 29, 30, 31,
+ 32, 33, 34, 35, 36, 37, 38, 39
+ };
+ exp.insert(myints, myints+16);
+ AlwaysAssert(md.getWVRSpw() == exp, AipsError);
+ }
+ {
+ cout << "*** test getScansForTimes()" << endl;
+ std::set<Int> exp;
+ exp.insert(27);
+ AlwaysAssert(
+ md.getScansForTimes(4.84282937e+09, 20, 0, 0) == exp,
+ AipsError
+ );
+ exp.insert(24);
+ exp.insert(25);
+ exp.insert(26);
+ exp.insert(28);
+ AlwaysAssert(
+ md.getScansForTimes(4.84282937e+09, 200, 0, 0) == exp,
+ AipsError
+ );
+ }
+ {
+ cout << "*** test getTimesForScans()" << endl;
+ std::set<Double> expec;
+ Double myd[] = {
+
4842825928.7,
4842825929.5,
+
4842825930.0,
+
4842825930.6,
4842825941.4,
+
4842825942.2,
4842825942.5,
+
4842825942.7,
4842825943.2,
+
4842825954.0,
4842825954.9,
+
4842825955.2, 4842825955.4,
+
4842825955.9, 4842825003.6,
+
4842825004.0, 4842825004.5,
+
4842825004.8, 4842825005.0,
+
4842825016.3, 4842825016.6,
+
4842825017.1, 4842825017.5,
+
4842825017.6, 4842825029.0,
+
4842825029.3, 4842825029.8,
+
4842825030.1, 4842825030.3
+ };
+ expec.insert(myd, myd+29);
+ std::set<Int> myscans;
+ myscans.insert(3);
+ myscans.insert(6);
+ AlwaysAssert(
+ allNearAbs(md.getTimesForScans(scanKeys(myscans, arrayKey)), expec,
0.1),
+ AipsError
+ );
+ }
+ {
+ cout << "*** test getTimesForScan()" << endl;
+ std::set<Double> expec;
+ Double myd[] = {
+
4842825003.6,
+
4842825004.0, 4842825004.5,
+
4842825004.8, 4842825005.0,
+
4842825016.3, 4842825016.6,
+
4842825017.1, 4842825017.5,
+
4842825017.6, 4842825029.0,
+
4842825029.3, 4842825029.8,
+
4842825030.1, 4842825030.3
+ };
+ expec.insert(myd, myd+15);
+ std::set<Int> myscans;
+ myscans.insert(3);
+ AlwaysAssert(
+ allNearAbs(
+ md.getTimesForScans(scanKeys(myscans, arrayKey)),
+ expec, 0.1
+ ),
+ AipsError
+ );
+ }
+ {
+ cout << "*** test getStatesForScan()" << endl;
+ std::set<Int> expec;
+ std::set<Int> scanNumbers = md.getScanNumbers(0, 0);
+ for (
+ std::set<Int>::const_iterator curScan=scanNumbers.begin();
+ curScan!=scanNumbers.end(); ++curScan
+ ) {
+ expec.clear();
+ if (*curScan == 1 || *curScan == 5 || *curScan == 8) {
+ Int mine[] = {0, 1, 2, 3, 4};
+ expec.insert(mine, mine+5);
+ }
+ else if (*curScan == 2) {
+ Int mine[] = {5, 6};
+ expec.insert(mine, mine+2);
+ }
+ else if (
+ *curScan == 3 || *curScan==6 || *curScan==9
+ || *curScan==11 || *curScan==13 || *curScan==15
+ || *curScan==17 || *curScan==19 || *curScan==22
+ || *curScan==24 || *curScan==26 || *curScan==29
+ || *curScan==31
+ ) {
+ Int mine[] = {7, 8, 9};
+ expec.insert(mine, mine+3);
+ }
+ else if (*curScan==4) {
+ Int mine[] = {
+ 10, 11, 12, 13, 14, 15, 16, 17, 18,
+ 19, 20, 21, 22, 23, 24, 25
+ };
+ expec.insert(mine, mine+16);
+ }
+ else if (*curScan==7) {
+ Int mine[] = {26, 27, 28, 29, 30, 31};
+ expec.insert(mine, mine+6);
+ }
+ else if (
+ *curScan==10 || *curScan==14 || *curScan==18
+ || *curScan==21 || *curScan==25 || *curScan==28
+ || *curScan==32
+ ) {
+ expec.insert(32);
+ }
+ else if (
+ *curScan==12 || *curScan==16
+ || *curScan==20 || *curScan==23
+ ) {
+ Int mine[] = {
+ 33, 34, 35, 36, 37, 38, 39, 40, 41, 42
+ };
+ expec.insert(mine, mine+10);
+ }
+ else {
+ Int mine[] = {33, 34, 35, 36};
+ expec.insert(mine, mine+4);
+ }
+ std::set<Int> got = md.getStatesForScan(0, 0, *curScan);
+ AlwaysAssert(got == expec, AipsError);
+ }
+ cout << "*** cache size " << md.getCache() << endl;
+ }
+ {
+ cout << "*** test getScansForIntent()" << endl;
+ std::set<String> intents = md.getIntents();
+ for (
+ std::set<String>::const_iterator intent=intents.begin();
+ intent!=intents.end(); ++intent
+ ) {
+ std::set<Int> expec;
+ if (
+ *intent=="CALIBRATE_AMPLI#ON_SOURCE"
+ ) {
+ expec.insert(7);
+ }
+ else if (
+ *intent=="CALIBRATE_ATMOSPHERE#OFF_SOURCE"
+ || *intent=="CALIBRATE_ATMOSPHERE#ON_SOURCE"
+ ) {
+ Int mine[] = {
+ 3, 6, 9, 11, 13, 15, 17,
+ 19, 22, 24, 26, 29, 31
+ };
+ expec.insert(mine, mine+13);
+ }
+ else if (*intent=="CALIBRATE_BANDPASS#ON_SOURCE") {
+ expec.insert(4);
+ }
+ else if (*intent=="CALIBRATE_PHASE#ON_SOURCE") {
+ Int mine[] = {
+ 4, 7, 10, 14, 18, 21, 25, 28, 32
+ };
+ expec.insert(mine, mine+9);
+ }
+ else if (*intent=="CALIBRATE_POINTING#ON_SOURCE") {
+ Int mine[] = {1, 5, 8};
+ expec.insert(mine, mine+3);
+ }
+ else if (
+ *intent=="CALIBRATE_SIDEBAND_RATIO#OFF_SOURCE"
+ || *intent=="CALIBRATE_SIDEBAND_RATIO#ON_SOURCE"
+ ) {
+ expec.insert(2);
+ }
+ else if (*intent=="CALIBRATE_WVR#OFF_SOURCE") {
+ Int mine[] = {
+ 2, 3, 6, 9, 11, 13, 15, 17,
+ 19, 22, 24, 26, 29, 31
+ };
+ expec.insert(mine, mine+14);
+ }
+ else if (*intent=="CALIBRATE_WVR#ON_SOURCE") {
+ Int mine[] = {
+ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
+ 11, 13, 14, 15, 17, 18, 19, 21,
+ 22, 24, 25, 26, 28, 29, 31, 32
+ };
+ expec.insert(mine, mine+26);
+ }
+ else {
+ Int mine[] = {12, 16, 20, 23, 27, 30};
+ expec.insert(mine, mine+6);
+ }
+ AlwaysAssert(md.getScansForIntent(*intent, 0, 0) == expec, AipsError);
+ AlwaysAssert(
+ casa::scanNumbers(md.getIntentToScansMap()[*intent]) == expec,
+ AipsError
+ );
+ }
+ }
+ {
+ cout << "*** test getScansForFieldID()" << endl;
+ std::set<Int> expec;
+ for (uInt i=0; i<6; ++i) {
+ expec.clear();
+ switch(i) {
+ case 0:
+ {
+ Int mine[] = {1, 2, 3, 4};
+ expec.insert(mine, mine+4);
+ break;
+ }
+ case 1:
+ expec.insert(5);
+ break;
+ case 2:
+ expec.insert(6);
+ expec.insert(7);
+ break;
+ case 3: {
+ Int mine[] = {
+ 8, 9, 10, 13, 14, 17, 18,
+ 21, 24, 25, 28, 31, 32
+ };
+ expec.insert(mine, mine+13);
+ break;
+ }
+ case 4: {
+ Int mine[] = {
+ 11, 12, 19, 20, 26, 27
+ };
+ expec.insert(mine, mine+6);
+ break;
+ }
+ case 5: {
+ Int mine[] = {
+ 15, 16, 22, 23, 29, 30
+ };
+ expec.insert(mine, mine+6);
+ break;
+ }
+ default:
+ throw AipsError("bad fieldID");
+ }
+ AlwaysAssert(md.getScansForFieldID(i, 0, 0) == expec, AipsError);
+ }
+ }
+ {
+ cout << "*** test getFieldIDsForField()" << endl;
+ for (uInt i=0; i<6; ++i) {
+ std::set<Int> expec;
+ expec.insert(i);
+ String name = i == 0 ? "3C279"
+ : i == 1 ? "J1337-129"
+ : i == 2 ? "Titan"
+ : i == 3 ? "J1625-254"
+ : i == 4 ? "V866 Sco"
+ : "RNO 90";
+ AlwaysAssert(
+ md.getFieldIDsForField(name) == expec,
+ AipsError
+ );
+ }
+ }
+ {
+ cout << "*** test getScansForField()" << endl;
+ for (uInt i=0; i<6; ++i) {
+ std::set<Int> expec;
+ String name;
+ switch(i) {
+ case 0:
+ {
+ name = "3C279";
+ uInt mine[] = {1, 2, 3, 4};
+ expec.insert(mine, mine+4);
+ break;
+ }
+ case 1:
+ name = "J1337-129";
+ expec.insert(5);
+ break;
+ case 2:
+ name = "Titan";
+ expec.insert(6);
+ expec.insert(7);
+ break;
+ case 3: {
+ name = "J1625-254";
+ Int mine[] = {
+ 8, 9, 10, 13, 14, 17, 18,
+ 21, 24, 25, 28, 31, 32
+ };
+ expec.insert(mine, mine+13);
+ break;
+ }
+ case 4: {
+ name = "V866 Sco";
+ Int mine[] = {
+ 11, 12, 19, 20, 26, 27
+ };
+ expec.insert(mine, mine+6);
+ break;
+ }
+ case 5: {
+ name = "RNO 90";
+ Int mine[] = {
+ 15, 16, 22, 23, 29, 30
+ };
+ expec.insert(mine, mine+6);
+ break;
+ }
+ default:
+ throw AipsError("bad fieldID");
+ }
+ AlwaysAssert(md.getScansForField(name, 0, 0) == expec, AipsError);
+ }
+ cout << "*** cache size " << md.getCache() << endl;
+ }
+ {
+ cout << "*** test getFieldsForScan() and getFieldsForScans()" << endl;
+ std::set<Int> scans = md.getScanNumbers(0, 0);
+ std::set<Int> expec2;
+ std::set<Int> curScanSet;
+ for (
+ std::set<Int>::const_iterator curScan=scans.begin();
+ curScan!=scans.end(); ++curScan
+ ) {
+ std::set<Int> expec;
+ curScanSet.insert(*curScan);
+ if (*curScan<=4) {
+ expec.insert(0);
+ expec2.insert(0);
+ }
+ else if (*curScan==5) {
+ expec.insert(1);
+ expec2.insert(1);
+ }
+ else if (*curScan<=7) {
+ expec.insert(2);
+ expec2.insert(2);
+ }
+ else if (
+ *curScan<=10 || *curScan==13
+ || *curScan==14 || *curScan==17
+ || *curScan==18 || *curScan==21
+ || *curScan==24 || *curScan==25
+ || *curScan==28 || *curScan==31
+ || *curScan==32
+ ) {
+ expec.insert(3);
+ expec2.insert(3);
+ }
+ else if (
+ *curScan==11 || *curScan==12
+ || *curScan==19 || *curScan==20
+ || *curScan==26 || *curScan==27
+ ) {
+ expec.insert(4);
+ expec2.insert(4);
+ }
+ else {
+ expec.insert(5);
+ expec2.insert(5);
+ }
+ ScanKey scanKey;
+ scanKey.obsID = 0;
+ scanKey.arrayID = 0;
+ scanKey.scan = *curScan;
+ AlwaysAssert(
+ md.getFieldsForScan(scanKey) == expec,
+ AipsError
+ );
+ AlwaysAssert(
+ md.getFieldsForScans(curScanSet, 0, 0) == expec2,
+ AipsError
+ );
+ }
+ }
+ {
+ cout << "*** test getFieldsForIntent() and getIntentToFieldsMap()" <<
endl;
+ std::map<String, std::set<Int> > mymap = md.getIntentToFieldsMap();
+ std::set<String> intents = md.getIntents();
+ for (
+ std::set<String>::const_iterator intent=intents.begin();
+ intent!=intents.end(); ++intent
+ ) {
+ std::set<Int> expec;
+ if (
+ *intent=="CALIBRATE_AMPLI#ON_SOURCE"
+ ) {
+ expec.insert(2);
+ }
+ else if (
+ *intent=="CALIBRATE_BANDPASS#ON_SOURCE"
+ || *intent=="CALIBRATE_SIDEBAND_RATIO#OFF_SOURCE"
+ || *intent=="CALIBRATE_SIDEBAND_RATIO#ON_SOURCE"
+ ) {
+ expec.insert(0);
+ }
+ else if (
+ *intent=="CALIBRATE_ATMOSPHERE#OFF_SOURCE"
+ || *intent=="CALIBRATE_ATMOSPHERE#ON_SOURCE"
+ || *intent=="CALIBRATE_WVR#OFF_SOURCE"
+ ) {
+ Int mine[] = {0, 2, 3, 4, 5};
+ expec.insert(mine, mine+5);
+ }
+ else if (
+ *intent=="CALIBRATE_PHASE#ON_SOURCE"
+ ) {
+ Int mine[] = {0, 2, 3};
+ expec.insert(mine, mine+3);
+ }
+ else if (
+ *intent=="CALIBRATE_POINTING#ON_SOURCE"
+ ) {
+ Int mine[] = {0, 1, 3};
+ expec.insert(mine, mine+3);
+ }
+ else if (*intent=="CALIBRATE_WVR#ON_SOURCE") {
+ Int mine[] = {0, 1, 2, 3, 4, 5};
+ expec.insert(mine, mine+6);
+ }
+ else {
+ Int mine[] = {4, 5};
+ expec.insert(mine, mine+2);
+ }
+ AlwaysAssert(
+ md.getFieldsForIntent(*intent) == expec,
+ AipsError
+ );
+ AlwaysAssert(mymap[*intent] == expec, AipsError);
+ }
+ }
+ {
+ cout << "*** test getFieldNamesForFieldIDs()" << endl;
+ for (uInt i=0; i<md.nFields(); ++i) {
+ String name;
+ switch(i) {
+ case 0:
+ name = "3C279";
+ break;
+ case 1:
+ name = "J1337-129";
+ break;
***The diff for this file has been truncated for email.***
=======================================
--- /dev/null
+++ /branches/nov14/ms/MSOper/test/tMSMetaData.run Wed Mar 25 14:33:54 2015
UTC
@@ -0,0 +1,7 @@
+#!/bin/sh
+
+dir=`echo $CASAPATH | awk '{print $1'}`
+name="${dir}/data/regression/unittest/MSMetaData/MSMetaData.ms"
+# Exit with skipped status if the MS cannot be found.
+test -e "$name" || exit 3
+./tMSMetaData "$name"
=======================================
--- /dev/null
+++ /branches/nov14/ms/MSOper/test/tMSReader.cc Wed Mar 25 14:33:54 2015 UTC
@@ -0,0 +1,78 @@
+//# tMSReader.cc: This program tests the MSReader class
+//# Copyright (C) 2000,2002
+//# Associated Universities, Inc. Washington DC, USA.
+//#
+//# This program is free software; you can redistribute it and/or modify it
+//# under the terms of the GNU General Public License as published by the
Free
+//# Software Foundation; either version 2 of the License, or (at your
option)
+//# any later version.
+//#
+//# This program is distributed in the hope that it will be useful, but
WITHOUT
+//# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+//# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for
+//# more details.
+//#
+//# You should have received a copy of the GNU General Public License along
+//# with this program; if not, write to the Free Software Foundation, Inc.,
+//# 675 Massachusetts Ave, Cambridge, MA 02139, USA.
+//#
+//# Correspondence concerning AIPS++ should be addressed as follows:
+//# Internet email:
aips2-...@nrao.edu.
+//# Postal address: AIPS++ Project Office
+//# National Radio Astronomy Observatory
+//# 520 Edgemont Road
+//# Charlottesville, VA 22903-2475 USA
+//#
+//# $Id$
+
+//# Includes
+
+#include <casacore/casa/Exceptions/Error.h>
+#include <casacore/ms/MeasurementSets/MeasurementSet.h>
+#include <casacore/ms/MSOper/MSReader.h>
+#include <casacore/casa/Arrays/ArrayIO.h>
+#include <casacore/casa/iostream.h>
+#include <casacore/casa/OS/Timer.h>
+
+#include <casacore/casa/namespace.h>
+int main(int argc, const char* argv[])
+{
+ try {
+ if (argc<2) {
+ cout << "Usage: " << argv[0] << " ms_name" << endl;
+ return 1;
+ }
+ String msName(argv[1]);
+ cout << "MS Name = " << msName << endl;
+
+ // construct the MS
+ MeasurementSet ms(msName);
+
+ // start up a reader
+ Timer timer;
+ timer.mark();
+ MSReader reader(ms);
+ timer.show("Construction : ");
+
+ cout << "Tables : " << reader.tables() << endl;
+ Vector<String> tables(reader.tables());
+
+ timer.mark();
+
+ for (uInt i=0;i<ms.nrow();i++) {
+ reader.gotoRow(i);
+ cout << i << " : ";
+ for (uInt j=0;j<tables.nelements();j++) {
+ if (j > 0) cout << " | ";
+ cout << reader.rowNumber(tables(j));
+ }
+ cout << endl;
+ }
+ timer.show("read to end : ");
+ cout << "done" << endl;
+ } catch (AipsError x) {
+ cerr << "Exception : " << x.getMesg() << endl;
+ }
+
+ return 0;
+}
=======================================
--- /dev/null
+++ /branches/nov14/ms/MSOper/test/tMSReader.run Wed Mar 25 14:33:54 2015
UTC
@@ -0,0 +1,24 @@
+#!/bin/sh
+
+if [ ${#AIPSPATH} = 0 ]
+then
+ echo "UNTESTED: tMSReader (AIPSPATH not defined)"
+ exit 3
+fi
+
+DATAFILE=`echo $AIPSPATH | awk '{print
$1}'`/data/demo/dishdemo/dishdemo1.fits
+
+if [ -f $DATAFILE ]
+then
+ $casa_checktool ./sdfits2ms $DATAFILE tMSReader_tmp.ms
+ if [ -d tMSReader_tmp.ms ]
+ then
+ $casa_checktool ./tMSReader tMSReader_tmp.ms
+ else
+ echo "FAIL: tMSReader, could not create tMSReader.ms from" $DATAFILE
+ exit 3
+ fi
+else
+ echo "UNTESTED: tMSReader, could not find the test data" $DATAFILE
+ exit 3
+fi
=======================================
--- /dev/null
+++ /branches/nov14/ms/MSOper/test/tMSSummary.cc Wed Mar 25 14:33:54 2015
UTC
@@ -0,0 +1,62 @@
+//# tMSSummary.cc: This program tests that VPSkyJones works
+//# Copyright (C) 1998,1999,2000
+//# Associated Universities, Inc. Washington DC, USA.
+//#
+//# This program is free software; you can redistribute it and/or modify it
+//# under the terms of the GNU General Public License as published by the
Free
+//# Software Foundation; either version 2 of the License, or (at your
option)
+//# any later version.
+//#
+//# This program is distributed in the hope that it will be useful, but
WITHOUT
+//# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+//# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for
+//# more details.
+//#
+//# You should have received a copy of the GNU General Public License along
+//# with this program; if not, write to the Free Software Foundation, Inc.,
+//# 675 Massachusetts Ave, Cambridge, MA 02139, USA.
+//#
+//# Correspondence concerning AIPS++ should be addressed as follows:
+//# Internet email:
aips2-...@nrao.edu.
+//# Postal address: AIPS++ Project Office
+//# National Radio Astronomy Observatory
+//# 520 Edgemont Road
+//# Charlottesville, VA 22903-2475 USA
+//#
+//# $Id$
+
+//# Includes
+#include <casacore/casa/aips.h>
+#include <casacore/casa/Exceptions/Error.h>
+#include <casacore/casa/Logging/LogIO.h>
+#include <casacore/ms/MeasurementSets/MeasurementSet.h>
+#include <casacore/ms/MSOper/MSSummary.h>
+
+int main(int argc, const char* argv[])
+{
+ using namespace std;
+ using namespace casacore;
+
+ if (argc != 2) {
+ cout << "Usage: "<< argv[0] << " MS_filename" << endl;
+ return 0;
+ }
+
+ try {
+ cout << "MSSummary" << endl;
+ cout << "--------------------------------------" << endl;
+
+ LogIO os(LogOrigin("tMSSummary", "main()"));
+
+ String MSName(argv[1]);
+ MeasurementSet ms(MSName, Table::Old);
+ MSSummary mss(ms);
+ //mss.list(os, verbose);
+ mss.listHistory(os);
+ } catch (AipsError x) {
+ cout << x.getMesg() << endl;
+ }
+
+ return 0;
+}
+
=======================================
--- /dev/null
+++ /branches/nov14/ms/MSOper.h Wed Mar 25 14:33:54 2015 UTC
@@ -0,0 +1,58 @@
+//# MSOper.h: Miscellaneous operations on MeasurementSets
+//# Copyright (C) 1996,1997
+//# Associated Universities, Inc. Washington DC, USA.
+//#
+//# This library is free software; you can redistribute it and/or modify it
+//# under the terms of the GNU Library General Public License as published
by
+//# the Free Software Foundation; either version 2 of the License, or (at
your
+//# option) any later version.
+//#
+//# This library is distributed in the hope that it will be useful, but
WITHOUT
+//# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+//# FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
+//# License for more details.
+//#
+//# You should have received a copy of the GNU Library General Public
License
+//# along with this library; if not, write to the Free Software Foundation,
+//# Inc., 675 Massachusetts Ave, Cambridge, MA 02139, USA.
+//#
+//# Correspondence concerning AIPS++ should be addressed as follows:
+//# Internet email:
aips2-...@nrao.edu.
+//# Postal address: AIPS++ Project Office
+//# National Radio Astronomy Observatory
+//# 520 Edgemont Road
+//# Charlottesville, VA 22903-2475 USA
+//#
+//# $Id: MeasurementSets.h 21538 2015-01-07 09:08:57Z gervandiepen $
+
+#ifndef MS_MSOPER_H
+#define MS_MSOPER_H
+
+#include <casacore/casa/aips.h>
+#include <casacore/ms/MeasurementSets/MeasurementSet.h>
+#include <casacore/ms/MeasurementSets/MSColumns.h>
+
+namespace casacore { //# NAMESPACE CASACORE - BEGIN
+
+// <module>
+//
+// <summary>
+// Miscellaneous operations on MeasurementSets
+// </summary>
+
+// <prerequisite>
+// <li> <linkto
module="MeasurementSets:description">MeasurementSets</linkto> module
+// </prerequisite>
+//
+// <reviewed reviewer="Bob Garwood" date="1997/02/01" demos="">
+// </reviewed>
+
+// <synopsis>
+// </synopsis>
+
+// </module>
+
+
+} //# NAMESPACE CASACORE - END
+
+#endif
=======================================
--- /dev/null
+++ /branches/nov14/ms/MSSel/MSAntennaGram.cc Wed Mar 25 14:33:54 2015 UTC
@@ -0,0 +1,282 @@
+//# MSAntennaGram.cc: Grammar for antenna expressions
+//# Copyright (C) 1998,1999,2001,2003
+//# Associated Universities, Inc. Washington DC, USA.
+//#
+//# This library is free software; you can redistribute it and/or modify it
+//# under the terms of the GNU Library General Public License as published
by
+//# the Free Software Foundation; either version 2 of the License, or (at
your
+//# option) any later version.
+//#
+//# This library is distributed in the hope that it will be useful, but
WITHOUT
+//# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+//# FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
+//# License for more details.
+//#
+//# You should have received a copy of the GNU Library General Public
License
+//# along with this library; if not, write to the Free Software Foundation,
+//# Inc., 675 Massachusetts Ave, Cambridge, MA 02139, USA.
+//#
+//# Correspondence concerning AIPS++ should be addressed as follows:
+//# Internet email:
aips2-...@nrao.edu.
+//# Postal address: AIPS++ Project Office
+//# National Radio Astronomy Observatory
+//# 520 Edgemont Road
+//# Charlottesville, VA 22903-2475 USA
+//#
+//# $Id$
+
+// MSAntennaGram; grammar for antenna command lines
+
+// This file includes the output files of bison and flex for
+// parsing command lines operating on lattices.
+
+#include <casacore/tables/TaQL/ExprNode.h>
+#include <casacore/ms/MeasurementSets/MeasurementSet.h>
+#include <casacore/ms/MSSel/MSAntennaGram.h>
+#include <casacore/ms/MSSel/MSAntennaParse.h> // routines used by bison
actions
+#include <casacore/ms/MSSel/MSAntennaIndex.h>
+#include <casacore/ms/MSSel/MSSelectionError.h>
+
+//# stdlib.h is needed for bison 1.28 and needs to be included here
+//# (before the flex/bison files).
+#include <casacore/casa/stdlib.h>
+//# Define register as empty string to avoid warnings in C++11 compilers
+//# because keyword register is not supported anymore.
+#define register
+#include "MSAntennaGram.ycc" // bison output
+#include "MSAntennaGram.lcc" // flex output
+
+// Define the yywrap function for flex.
+int MSAntennaGramwrap()
+{
+ return 1;
+}
+
+namespace casacore { //# NAMESPACE CASACORE - BEGIN
+
+//# Declare a file global pointer to a char* for the input string.
+ static const char* strpMSAntennaGram = 0;
+ static Int posMSAntennaGram = 0;
+
+//# Parse the command.
+//# Do a yyrestart(yyin) first to make the flex scanner reentrant.
+ TableExprNode baseMSAntennaGramParseCommand(MSAntennaParse* parser,
const String& command,
+ Vector<Int>& selectedAnts1,
+ Vector<Int>& selectedAnts2,
+ Matrix<Int>& selectedBaselines)
+ {
+ try
+ {
+ MSAntennaGramrestart (MSAntennaGramin);
+ yy_start = 1;
+ strpMSAntennaGram = command.chars(); // get pointer to command string
+ posMSAntennaGram = 0; // initialize string position
+ parser->setComplexity();
+ MSAntennaParse::thisMSAParser = parser; // The global pointer to the
parser
+ MSAntennaGramparse(); // parse command string
+
+ selectedAnts1.reference (parser->selectedAnt1());
+ selectedAnts2.reference (parser->selectedAnt2());
+ selectedBaselines.reference (parser->selectedBaselines());
+ return parser->node();
+ }
+ catch (MSSelectionAntennaError& x)
+ {
+ String newMesgs;
+ newMesgs = constructMessage(msAntennaGramPosition(),command);
+ x.addMessage(newMesgs);
+ throw;
+ }
+ }
+
+ TableExprNode msAntennaGramParseCommand (MSSelectableTable& msLike,
+ const String& command,
+ Vector<Int>& selectedAnts1,
+ Vector<Int>& selectedAnts2,
+ Matrix<Int>& selectedBaselines)
+ {
+ TableExprNode col1TEN = msLike.col(msLike.columnName(MS::ANTENNA1)),
+ col2TEN = msLike.col(msLike.columnName(MS::ANTENNA2));
+
+ TableExprNode antennaTEN;
+ // MSAntennaParse *thisParser = new
MSAntennaParse(msLike.antenna(), col1TEN, col2TEN);
+ MSAntennaParse thisParser(msLike.antenna(), col1TEN, col2TEN);
+ try
+ {
+ antennaTEN = baseMSAntennaGramParseCommand(&thisParser, command,
+ selectedAnts1, selectedAnts2,
+ selectedBaselines);
+ }
+ catch(MSSelectionAntennaError &x)
+ {
+ // delete thisParser;
+ throw;
+ }
+
+ //delete thisParser;
+ return antennaTEN;
+ }
+
+ TableExprNode msAntennaGramParseCommand (Table& subTable,
+ TableExprNode& col1TEN,
+ TableExprNode& col2TEN,
+ const String& command,
+ Vector<Int>& selectedAnts1,
+ Vector<Int>& selectedAnts2,
+ Matrix<Int>& selectedBaselines)
+ {
+ // TableExprNode col1TEN = msLike.col(msLike.columnName(MS::ANTENNA1)),
+ // col2TEN = msLike.col(msLike.columnName(MS::ANTENNA2));
+
+ TableExprNode antennaTEN;
+ // MSAntennaParse *thisParser = new
MSAntennaParse(msLike.antenna(), col1TEN, col2TEN);
+ MSAntennaParse thisParser(subTable, col1TEN, col2TEN);
+ try
+ {
+ antennaTEN = baseMSAntennaGramParseCommand(&thisParser, command,
+ selectedAnts1, selectedAnts2,
+ selectedBaselines);
+ }
+ catch(MSSelectionAntennaError &x)
+ {
+ // delete thisParser;
+ throw;
+ }
+
+ //delete thisParser;
+ return antennaTEN;
+ }
+
+ TableExprNode msAntennaGramParseCommand (MSAntennaParse* thisParser,
+ const String& command,
+ Vector<Int>& selectedAnts1,
+ Vector<Int>& selectedAnts2,
+ Matrix<Int>& selectedBaselines)
+ {
+ TableExprNode antennaTEN;
+ try
+ {
+ antennaTEN=baseMSAntennaGramParseCommand(thisParser, command,
+ selectedAnts1, selectedAnts2,
+ selectedBaselines);
+ }
+ catch(MSSelectionAntennaError &x)
+ {
+ delete thisParser;
+ throw;
+ }
+ delete thisParser;
+ return antennaTEN;
+ }
+
+ TableExprNode msAntennaGramParseCommand (const MeasurementSet* ms,
+ const String& command,
+ Vector<Int>& selectedAnts1,
+ Vector<Int>& selectedAnts2,
+ Matrix<Int>& selectedBaselines)
+ {
+ TableExprNode antennaTEN;
+ TableExprNode col1AsTEN = ms->col(ms->columnName(MS::ANTENNA1)),
+ col2AsTEN = ms->col(ms->columnName(MS::ANTENNA2));
+ MSAntennaParse *thisParser = new
MSAntennaParse(ms->antenna(),col1AsTEN, col2AsTEN);
+ try
+ {
+ antennaTEN=baseMSAntennaGramParseCommand(thisParser, command,
+ selectedAnts1, selectedAnts2,
+ selectedBaselines);
+ }
+ catch(MSSelectionAntennaError &x)
+ {
+ delete thisParser;
+ throw;
+ }
+ delete thisParser;
+ return antennaTEN;
+
+
+
+ // try
+ // {
+ // MSAntennaGramrestart (MSAntennaGramin);
+ // yy_start = 1;
+ // strpMSAntennaGram = command.chars(); // get pointer to command
string
+ // posMSAntennaGram = 0; // initialize string
position
+ // MSAntennaParse parser(ms); // setup measurement set
+ // parser.setComplexity();
+ // MSAntennaParse::thisMSAParser = &parser; // The global pointer to
the parser
+ // MSAntennaGramparse(); // parse command string
+
+ // selectedAnts1.reference (parser.selectedAnt1());
+ // selectedAnts2.reference (parser.selectedAnt2());
+ // selectedBaselines.reference (parser.selectedBaselines());
+ // return parser.node();
+ // }
+ // catch (MSSelectionAntennaError& x)
+ // {
+ // String newMesgs;
+ // newMesgs = constructMessage(msAntennaGramPosition(),command);
+ // x.addMessage(newMesgs);
+ // throw;
+ // }
+ }
+
+ //# Give the string position.
+ Int& msAntennaGramPosition()
+ {
+ return posMSAntennaGram;
+ }
+
+ //# Get the next input characters for flex.
+ int msAntennaGramInput (char* buf, int max_size)
+ {
+ int nr=0;
+ while (*strpMSAntennaGram != 0) {
+ if (nr >= max_size) {
+ break; // get max. max_size char.
+ }
+ buf[nr++] = *strpMSAntennaGram++;
+ }
+ return nr;
+ }
+
+ void MSAntennaGramerror (const char*)
+ {
+ throw (MSSelectionAntennaParseError ("Antenna Expression: Parse error
at or near '" +
+ String(MSAntennaGramtext) + "'"));
+ }
+
+ // String msAntennaGramRemoveEscapes (const String& in)
+ // {
+ // String out;
+ // int leng = in.length();
+ // for (int i=0; i<leng; i++) {
+ // if (in[i] == '\\') {
+ // i++;
+ // }
+ // out += in[i];
+ // }
+ // return out;
+ // }
+
+ // String msAntennaGramRemoveQuotes (const String& in)
+ // {
+ // //# A string is formed as "..."'...''...' etc.
+ // //# All ... parts will be extracted and concatenated into an
output string.
+ // String out;
+ // String str = in;
+ // int leng = str.length();
+ // int pos = 0;
+ // while (pos < leng) {
+ // //# Find next occurrence of leading ' or ""
+ // int inx = str.index (str[pos], pos+1);
+ // if (inx < 0) {
+ // throw (AipsError ("MSAntennaParse - Ill-formed quoted string: " +
+ // str));
+ // }
+ // out +=
str.at (pos+1, inx-pos-1); // add substring
+ // pos = inx+1;
+ // }
+ // return out;
+ // }
+
+} //# NAMESPACE CASACORE - END
=======================================
--- /dev/null
+++ /branches/nov14/ms/MSSel/MSAntennaGram.h Wed Mar 25 14:33:54 2015 UTC
@@ -0,0 +1,127 @@
+//# MSAntennaGram.h: Grammar for ms antenna sub-expressions
+//# Copyright (C) 1998
+//# Associated Universities, Inc. Washington DC, USA.
+//#
+//# This library is free software; you can redistribute it and/or modify it
+//# under the terms of the GNU Library General Public License as published
by
+//# the Free Software Foundation; either version 2 of the License, or (at
your
+//# option) any later version.
+//#
+//# This library is distributed in the hope that it will be useful, but
WITHOUT
+//# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+//# FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
+//# License for more details.
+//#
+//# You should have received a copy of the GNU Library General Public
License
+//# along with this library; if not, write to the Free Software Foundation,
+//# Inc., 675 Massachusetts Ave, Cambridge, MA 02139, USA.
+//#
+//# Correspondence concerning AIPS++ should be addressed as follows:
+//# Internet email:
aips2-...@nrao.edu.
+//# Postal address: AIPS++ Project Office
+//# National Radio Astronomy Observatory
+//# 520 Edgemont Road
+//# Charlottesville, VA 22903-2475 USA
+//#
+//# $Id$
+
+#ifndef MS_MSANTENNAGRAM_H
+#define MS_MSANTENNAGRAM_H
+
+
+//# Includes
+#include <casacore/casa/aips.h>
+#include <casacore/casa/BasicSL/String.h>
+#include <casacore/casa/Arrays/Matrix.h>
+#include <casacore/ms/MSSel/MSAntennaParse.h> // routines used by bison
actions
+
+namespace casacore { //# NAMESPACE CASACORE - BEGIN
+
+//# Forward Declarations
+class MeasurementSet;
+class TableExprNode;
+
+// <summary>
+// Global functions for flex/bison scanner/parser for MSAntennaGram
+// </summary>
+
+// <use visibility=local>
+
+// <reviewed reviewer="" date="" tests="">
+// </reviewed>
+
+// <prerequisite>
+//# Classes you should understand before using this one.
+// <li> MSAntennaGram.l and .y (flex and bison grammar)
+// </prerequisite>
+
+// <synopsis>
+// Global functions are needed to define the input of the flex scanner
+// and to start the bison parser.
+// The input is taken from a string.
+// </synopsis>
+
+// <motivation>
+// It is necessary to be able to give an image expression in ASCII.
+// This can be used in glish.
+// </motivation>
+// <todo asof="$DATE:$">
+//# A List of bugs, limitations, extensions or planned refinements.
+// </todo>
+
+
+// <group name=MSAntennaGramFunctions>
+
+// Declare the bison parser (is implemented by bison command).
+// It returns a TaQL expression tree.
+ TableExprNode msAntennaGramParseCommand (MSSelectableTable& msLike,
+ const String& command,
+ Vector<Int>& selectedAnts1,
+ Vector<Int>& selectedAnts2,
+ Matrix<Int>&
selectedBaselines) ;
+ TableExprNode msAntennaGramParseCommand (MSAntennaParse* thisParser,
+ const TableExprNode& col1TEN,
+ const TableExprNode& col2TEN,
+ const String& command,
+ Vector<Int>& selectedAnts1,
+ Vector<Int>& selectedAnts2,
+ Matrix<Int>&
selectedBaselines) ;
+ TableExprNode msAntennaGramParseCommand (Table& subTable,
+ TableExprNode& col1TEN,
+ TableExprNode& col2TEN,
+ const String& command,
+ Vector<Int>& selectedAnts1,
+ Vector<Int>& selectedAnts2,
+ Matrix<Int>&
selectedBaselines) ;
+ TableExprNode msAntennaGramParseCommand (const MeasurementSet *ms,
+ const String& command,
+ Vector<Int>& selectedAnt1,
+ Vector<Int>& selectedAnt2,
+ Matrix<Int>& selectedBaselines);
+
+ TableExprNode baseMSAntennaGramParseCommand(MSAntennaParse* parser,
const String& command,
+ Vector<Int>& selectedAnts1,
+ Vector<Int>& selectedAnts2,
+ Matrix<Int>& selectedBaselines);
+ // The yyerror function for the parser.
+ // It throws an exception with the current token.
+ void MSAntennaGramerror (const char*);
+
+ // Give the current position in the string.
+ // This can be used when parse errors occur.
+ Int& msAntennaGramPosition();
+
+ // Declare the input routine for flex/bison.
+ int msAntennaGramInput (char* buf, int max_size);
+
+ // A function to remove escaped characters.
+ //String msAntennaGramRemoveEscapes (const String& in);
+
+ // A function to remove quotes from a quoted string.
+ //String msAntennaGramRemoveQuotes (const String& in);
+
+ // </group>
+
+} //# NAMESPACE CASACORE - END
+
+#endif
=======================================
--- /dev/null
+++ /branches/nov14/ms/MSSel/MSAntennaGram.ll Wed Mar 25 14:33:54 2015 UTC
@@ -0,0 +1,158 @@
+/* -*- C -*-
+ MSAntennaGram.l: Lexical analyzer for ms selection commands
+ Copyright (C) 1994,1995,1996,1997,1998,2001,2003
+ Associated Universities, Inc. Washington DC, USA.
+
+ This library is free software; you can redistribute it and/or modify it
+ under the terms of the GNU Library General Public License as published
by
+ the Free Software Foundation; either version 2 of the License, or (at
your
+ option) any later version.
+
+ This library is distributed in the hope that it will be useful, but
WITHOUT
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
+ License for more details.
+
+ You should have received a copy of the GNU Library General Public
License
+ along with this library; if not, write to the Free Software Foundation,
+ Inc., 675 Massachusetts Ave, Cambridge, MA 02139, USA.
+
+ Correspondence concerning AIPS++ should be addressed as follows:
+ Internet email:
aips2-...@nrao.edu.
+ Postal address: AIPS++ Project Office
+ National Radio Astronomy Observatory
+ 520 Edgemont Road
+ Charlottesville, VA 22903-2475 USA
+
+ $Id$
+*/
+
+/* yy_unput is not used, so let flex not generate it, otherwise picky
+ compilers will issue warnings. */
+%option nounput
+
+%{
+#undef YY_INPUT
+#define YY_INPUT(buf,result,max_size)
result=msAntennaGramInput(buf,max_size)
+
+#undef YY_DECL
+#define YY_DECL int MSAntennaGramlex (YYSTYPE* lvalp)
+%}
+
+WHITE [ \t\n]*
+DIGIT [0-9]
+INT {DIGIT}+
+EXP [DdEe][+-]?{INT}
+FLOAT {INT}{EXP}|{INT}"."{DIGIT}*({EXP})?|{DIGIT}*"."{INT}({EXP})?
+
+QSTRING \"[^\"\n]*\"
+ASTRING \'[^\'\n]*\'
+STRING ({QSTRING}|{ASTRING})+
+REGEX "^"?"/"[^/\n]*"/"
+
+ALPHA [a-zA-Z]
+UNIT {ALPHA}+
+NAMECHAR [-+a-zA-Z0-9_.]
+NAMENNUM [a-zA-Z_]
+COLON ":"
+NAME1 {NAMENNUM}{NAMECHAR}*
+NAME2 {NAMECHAR}*{COLON}({NAMECHAR}|{COLON})*
+NAME {NAME1}|{NAME2}
+ESCNAME \\[^ \t\n]+
+PATTCHAR [][*?^]
+PATT1 ({NAMENNUM}|{PATTCHAR})({NAMECHAR}|{PATTCHAR})*
+PATT2 ({NAMECHAR}|{PATTCHAR})*{COLON}({NAMECHAR}|{PATTCHAR}|{COLON})*
+PATTERN {PATT1}|{PATT2}
+
+
+/* rules */
+%%
+
+{STRING} {
+ int lenstr = strlen(MSAntennaGramtext) - 2;
+ lvalp->str = (char*)malloc(lenstr+1);
+ strncpy(lvalp->str, MSAntennaGramtext+1, lenstr);
+ lvalp->str[lenstr] = '\0';
+ return QSTRING;
+ }
+
+{REGEX} {
+ int lenstr = strlen(MSAntennaGramtext) - 2;
+ lvalp->str = (char*)malloc(lenstr+1);
+ strncpy(lvalp->str, MSAntennaGramtext+1, lenstr);
+ if (MSAntennaGramtext[0] == '^') lvalp->str[0] = '^';
+ lvalp->str[lenstr] = '\0';
+ return REGEX;
+ }
+
+
+{UNIT} {
+ msAntennaGramPosition() += yyleng;
+ lvalp->str = (char*)malloc(strlen(MSAntennaGramtext) + 1);
+ strcpy(lvalp->str, MSAntennaGramtext);
+ return UNIT;
+ }
+
+{NAME} {
+ msAntennaGramPosition() += yyleng;
+ lvalp->str = (char *)malloc((strlen(MSAntennaGramtext) + 1));
+ strcpy(lvalp->str, MSAntennaGramtext);
+ return IDENTIFIER;
+ }
+
+{ESCNAME} {
+ msAntennaGramPosition() += yyleng;
+ lvalp->str = (char *)malloc((strlen(MSAntennaGramtext)));
+ strcpy(lvalp->str, MSAntennaGramtext+1);
+ return IDENTIFIER;
+ }
+
+{PATTERN} {
+ msAntennaGramPosition() += yyleng;
+ lvalp->str = (char *)malloc((strlen(MSAntennaGramtext) + 1));
+ strcpy(lvalp->str, MSAntennaGramtext);
+ return QSTRING;
+ }
+
+{INT} {
+ msAntennaGramPosition() += yyleng;
+ lvalp->str = (char*)malloc(strlen(MSAntennaGramtext) + 1);
+ strcpy(lvalp->str, MSAntennaGramtext);
+ return INT;
+ }
+
+{FLOAT} {
+ msAntennaGramPosition() += yyleng;
+ lvalp->str = (char*)malloc(strlen(MSAntennaGramtext) + 1);
+ strcpy(lvalp->str, MSAntennaGramtext);
+ return FLOAT;
+ }
+
+";" { msAntennaGramPosition() += yyleng; return SEMICOLON; }
+"@" { msAntennaGramPosition() += yyleng; return AT; }
+"&" { msAntennaGramPosition() += yyleng; return AMPERSAND; }
+"~" { msAntennaGramPosition() += yyleng; return DASH; }
+"," { msAntennaGramPosition() += yyleng; return COMMA;}
+"!" { msAntennaGramPosition() += yyleng; return NOT;}
+"(" { msAntennaGramPosition() += yyleng; return LPAREN; }
+")" { msAntennaGramPosition() += yyleng; return RPAREN;}
+"<" { msAntennaGramPosition() += yyleng; return LT;}
+"<=" { msAntennaGramPosition() += yyleng; return LE;}
+">" { msAntennaGramPosition() += yyleng; return GT;}
+">=" { msAntennaGramPosition() += yyleng; return GE;}
+
+{WHITE} { msAntennaGramPosition() += yyleng;} /* Eat whitespace */
+
+ /* An unterminated string is an error */
+\'|\" { throw MSSelectionAntennaError ("Unterminated string"); }
+
+ /* An unterminated regex is an error */
+"/" { throw MSSelectionAntennaError ("Unterminated regex"); }
+
+ /* terminate on EOF */
+<<EOF>> { yyterminate(); }
+
+ /* Any other character is invalid */
+. { return YYERRCODE; }
+
+%%
=======================================
--- /dev/null
+++ /branches/nov14/ms/MSSel/MSAntennaGram.yy Wed Mar 25 14:33:54 2015 UTC
@@ -0,0 +1,526 @@
+/*-*- C++ -*-
+ MSAntennaGram.y: Parser for antenna expressions
+ Copyright (C) 2004
+ Associated Universities, Inc. Washington DC, USA.
+
+ This library is free software; you can redistribute it and/or modify it
+ under the terms of the GNU Library General Public License as published
by
+ the Free Software Foundation; either version 2 of the License, or (at
your
+ option) any later version.
+
+ This library is distributed in the hope that it will be useful, but
WITHOUT
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
+ License for more details.
+
+ You should have received a copy of the GNU Library General Public
License
+ along with this library; if not, write to the Free Software Foundation,
+ Inc., 675 Massachusetts Ave, Cambridge, MA 02139, USA.
+
+ Correspondence concerning AIPS++ should be addressed as follows:
+ Internet email:
aips2-...@nrao.edu.
+ Postal address: AIPS++ Project Office
+ National Radio Astronomy Observatory
+ 520 Edgemont Road
+ Charlottesville, VA 22903-2475 USA
+
+ $Id$
+*/
+
+%{
+ using namespace casacore;
+%}
+
+%pure-parser /* make parser re-entrant */
+
+%union {
+ const TableExprNode* node;
+ char* str;
+ double dval;
+ Vector<Int>* iv;
+ std::vector<double>* dv;
+ Vector<String>* is;
+}
+
+
+%token AT
+%token COMMA
+%token SEMICOLON
+%token AMPERSAND
+%token DASH
+%token NOT
+%token LPAREN
+%token RPAREN
+%token LT
+%token LE
+%token GT
+%token GE
+
+%token <str> INT
+%token <str> FLOAT
+%token <str> UNIT
+%token <str> QSTRING
+%token <str> REGEX
+%token <str> IDENTIFIER
+
+%type <node> antennastatement
+%type <node> indexcombexpr
+%type <node> baseline
+%type <node> gbaseline
+%type <str> identstr
+%type <dval> flt
+%type <dval> flint
+%type <dval> unit
+%type <dval> flintunit
+%type <dval> flunit
+%type <iv> antlist
+%type <iv> antidrange
+%type <iv> antids
+%type <iv> antid
+%type <iv> stationid
+%type <iv> stationlist
+%type <iv> antatstation
+%type <iv> antcomp
+%type <iv> stationcomp
+%type <dv> blength
+%type <dv> blengthlist
+
+// %destructor {free ($$);} INT FLOAT UNIT QSTRING REGEX IDENTIFIER
identstr
+// %destructor {delete ($$);} antlist antidrange antids antid stationid
stationlist antatstation antcomp stationcomp
+// %destructor {delete ($$);} blength blengthlist
+
+%{
+#include <casacore/casa/Logging/LogIO.h>
+#include <casacore/ms/MSSel/MSSelectionTools.h>
+
+ int MSAntennaGramlex (YYSTYPE*);
+ Bool MSAntennaGramNegate=False;
+ void reportError(char *token,String source=String(""))
+ {
+ LogIO logIO;
+ ostringstream Mesg,tok;
+ if (source != "") Mesg << source; else Mesg << "Antenna Expression";
+
+ Mesg << ": No match found for token(s) ";
+ tok << "\"";
+ if (MSAntennaGramNegate) tok << "!";
+ tok << token << "\"";
+
+ MSAntennaParse::thisMSAErrorHandler->reportError(tok.str().c_str(),
Mesg.str());
+ Mesg << tok.str();
+ // if (MSAntennaGramNegate)
+ // {
+ // logIO << Mesg.str()
+ // << " (just a helpful message (from your friendly
MSAntennaSelection object))"
+ // << LogIO::WARN;
+ // }
+ // else
+ // // throw(MSSelectionAntennaParseError(Mesg.str()));
+ // logIO << Mesg.str() << LogIO::WARN;
+ }
+ //
+ // Keep life from getting too computer-like (encouragement may be a
+ // defining human need/quality).
+ //
+ void kungrachulations(const std::bitset<MSAntennaParse::HIGHESTLEVEL>&
complexity)
+ {
+ LogIO logIO(LogOrigin("MSAntannaParse",""));
+ Bool level1=(complexity.test(MSAntennaParse::ANTREGEX) &
+ complexity.test(MSAntennaParse::ANTLIST) &
+ complexity.test(MSAntennaParse::BASELINELIST));
+ Bool level2=(level1 & complexity.test(MSAntennaParse::STATIONLIST));
+ Bool level3=(level2 & complexity.test(MSAntennaParse::STATIONREGEX)
+ & complexity.test(MSAntennaParse::ANTATSTATIONLIST));
+ if (level3)
+ logIO << "Oh the brave one!\n "
+ "You successfully passed the deepest abyss of parsing in baseline
selection without error.\n "
+ "May The Force (or the CASA User Support Group) be with you. Good luck."
+ << LogIO::POST;
+ else if (level2)
+ logIO << "Many congratulations. You are using an expert level of
complexity in baseline selection.\n "
+ // "Tread carefully at this level (easy to go wrong)."
+ << LogIO::POST;
+ else if (level1)
+ logIO << "Congratulations. You are using a respectable level of
complextiy in baseline selection."
+ << LogIO::POST;
+ }
+%}
+
+%%
+antennastatement: indexcombexpr
+ {
+ $$ = $1;
+ kungrachulations(MSAntennaParse::thisMSAParser->getComplexity());
+ }
+/* | LPAREN indexcombexpr RPAREN {$$ = $2;}*/
+
+indexcombexpr: gbaseline {$$=$1;}
+ | indexcombexpr SEMICOLON gbaseline
+ {
+ $$ = $1;
+
MSAntennaParse::thisMSAParser->setComplexity(MSAntennaParse::BASELINELIST);
+ }
+
+gbaseline: NOT {MSAntennaGramNegate=True;} baseline {$$=$3;}
+ | {MSAntennaGramNegate=False;} baseline {$$=$2;}
+
+baseline: antlist AMPERSAND antlist // Two non-identical lists for
the '&' operator
+ {
+ // MSAntennaIndex
myMSAI(MSAntennaParse::thisMSAParser->ms()->antenna());
+ MSAntennaIndex myMSAI(MSAntennaParse::thisMSAParser->subTable());
+ Vector<Int> a1 = myMSAI.matchId(*($1));
+ Vector<Int> a2 = myMSAI.matchId(*($3));
+ $$ = MSAntennaParse::thisMSAParser->selectAntennaIds
+ (a1,a2,MSAntennaParse::CrossOnly, MSAntennaGramNegate);
+ delete $1;
+ delete $3;
+ }
+ | antlist AMPERSAND // Implicit same list on the RHS of '&'
operator
+ {
+ // MSAntennaIndex
myMSAI(MSAntennaParse::thisMSAParser->ms()->antenna());
+ // cerr << "### ANTLIST&" << endl;
+ // if (!MSAntennaParse::thisMSAParser->msInterface()->isMS())
reportError("& opertor invalid","");
+ // else
+ {
+ MSAntennaIndex myMSAI(MSAntennaParse::thisMSAParser->subTable());
+ Vector<Int> a1 = myMSAI.matchId(*($1));
+ $$ = MSAntennaParse::thisMSAParser->selectAntennaIds
+ (a1,a1,MSAntennaParse::CrossOnly, MSAntennaGramNegate);
+ }
+ delete $1;
+ }
+ | antlist //Match ANTLIST & ALLANTENNAS (implicit "&*")
+ {
+ // MSAntennaIndex
myMSAI(MSAntennaParse::thisMSAParser->ms()->antenna());
+ MSAntennaIndex myMSAI(MSAntennaParse::thisMSAParser->subTable());
+ Vector<Int> a1 = myMSAI.matchId(*($1));
+ $$ = MSAntennaParse::thisMSAParser->selectAntennaIds
+ (a1,MSAntennaParse::CrossOnly, MSAntennaGramNegate);
+ delete $1;
+ }
+ | antlist AMPERSAND AMPERSAND antlist /*Include self-correlations*/
+ {
+ // MSAntennaIndex
myMSAI(MSAntennaParse::thisMSAParser->ms()->antenna());
+ MSAntennaIndex myMSAI(MSAntennaParse::thisMSAParser->subTable());
+ Vector<Int> a1 = myMSAI.matchId(*($1));
+ Vector<Int> a2 = myMSAI.matchId(*($4));
+ $$ = MSAntennaParse::thisMSAParser->selectAntennaIds
+ (a1,a2,MSAntennaParse::AutoCorrAlso, MSAntennaGramNegate);
+ delete $1;
+ delete $4;
+ }
+ | antlist AMPERSAND AMPERSAND // Include self-correlations
+ {
+ // MSAntennaIndex
myMSAI(MSAntennaParse::thisMSAParser->ms()->antenna());
+ MSAntennaIndex myMSAI(MSAntennaParse::thisMSAParser->subTable());
+ Vector<Int> a1 = myMSAI.matchId(*($1));
+ $$ = MSAntennaParse::thisMSAParser->selectAntennaIds
+ (a1,a1,MSAntennaParse::AutoCorrAlso, MSAntennaGramNegate);
+ delete $1;
+ }
+ | antlist AMPERSAND AMPERSAND AMPERSAND // Only
self-correlations :-)
+ {
+ // MSAntennaIndex
myMSAI(MSAntennaParse::thisMSAParser->ms()->antenna());
+ MSAntennaIndex myMSAI(MSAntennaParse::thisMSAParser->subTable());
+ Vector<Int> a1 = myMSAI.matchId(*($1));
+ $$ = MSAntennaParse::thisMSAParser->selectAntennaIds
+ (a1,MSAntennaParse::AutoCorrOnly, MSAntennaGramNegate);
+ delete $1;
+ }
+ | blengthlist // baseline length list
+ {
+ $$ = MSAntennaParse::thisMSAParser->selectLength
+ (*$1, MSAntennaGramNegate);
+ delete $1;
+ }
+
+identstr: IDENTIFIER { $$ = $1; }
+ | UNIT { $$ = $1; } // a unit is an aphabetic
name, so here it is a name
+
+// A single station name (this could be a regex and hence produce a
+// list of indices)
+stationid: identstr // IDENTIFIER
+ { // Use the string as-is. This cannot include patterns/regex
+ // which has characters that are part of range or list
+ // syntax (',', '-') (that's all I think).
+ //
+ // Convert name to index
+ //
+ // MSAntennaIndex
myMSAI(MSAntennaParse::thisMSAParser->ms()->antenna());
+ MSAntennaIndex myMSAI(MSAntennaParse::thisMSAParser->subTable());
+ if (!($$)) delete $$;
+ $$=new Vector<Int>(myMSAI.matchStationName($1));
+ if ((*($$)).nelements() == 0) reportError($1,"Station Expression");
+ free($1);
+ }
+ | QSTRING
+ { // Quoted string: This is a pattern which will be converted
+ // to regex internally. E.g. "VLA{20,21}*" becomes
+ // "VLA((20)|(21)).*" regex. This can include any character
+ // string.
+ //
+ // Convert name to index
+ //
+ // MSAntennaIndex
myMSAI(MSAntennaParse::thisMSAParser->ms()->antenna());
+ MSAntennaIndex myMSAI(MSAntennaParse::thisMSAParser->subTable());
+ if (!$$) delete $$;
+ $$ = new Vector<Int>(myMSAI.matchStationRegexOrPattern($1));
+ if ((*($$)).nelements() == 0) reportError($1,"Station Expression");
+ free($1);
+
MSAntennaParse::thisMSAParser->setComplexity(MSAntennaParse::STATIONREGEX);
+ }
+ | REGEX
+ { // A string delimited by a pair of '/': This will be treated
+ // as a regular expression internally.
+ //
+ // Convert name to index
+ //
+ // MSAntennaIndex
myMSAI(MSAntennaParse::thisMSAParser->ms()->antenna());
+ MSAntennaIndex myMSAI(MSAntennaParse::thisMSAParser->subTable());
+ if (!$$) delete $$;
+ $$ = new Vector<Int>(myMSAI.matchStationRegexOrPattern($1,True));
+ if ((*($$)).nelements() == 0) reportError($1,"Station Expression");
+ free($1);
+
MSAntennaParse::thisMSAParser->setComplexity(MSAntennaParse::STATIONREGEX);
+ }
+
+// A single antenna name (this could be a regex and hence produce a
+// list of indices)
+antid: identstr
+ { // Use the string as-is. This cannot include patterns/regex
+ // which has characters that are part of range or list
+ // syntax (',', '-') (that's all I think).
+ //
+ // Convert name to index
+ //
+ // MSAntennaIndex
myMSAI(MSAntennaParse::thisMSAParser->ms()->antenna());
+ MSAntennaIndex myMSAI(MSAntennaParse::thisMSAParser->subTable());
+ if (!($$)) delete $$;
+ $$=new Vector<Int>(myMSAI.matchAntennaName($1));
+ //$$=new Vector<Int>(myMSAI.matchAntennaRegexOrPattern($1));
+ if ((*($$)).nelements() == 0) reportError($1);
+ free($1);
+ }
+ | QSTRING
+ { // Quoted string: This is a pattern which will be converted
+ // to regex internally. E.g. "VLA{20,21}*" becomes
+ // "VLA((20)|(21)).*" regex. This can include any character
+ // string.
+ //
+ // Convert name to index
+ //
+ // MSAntennaIndex
myMSAI(MSAntennaParse::thisMSAParser->ms()->antenna());
+ MSAntennaIndex myMSAI(MSAntennaParse::thisMSAParser->subTable());
+ if (!$$) delete $$;
+ $$ = new Vector<Int>(myMSAI.matchAntennaRegexOrPattern($1));
+ if ((*($$)).nelements() == 0) reportError($1);
+ free($1);
+ MSAntennaParse::thisMSAParser->setComplexity(MSAntennaParse::ANTREGEX);
+ }
+ | REGEX
+ { // A string delimited by a pair of '/': This will be treated
+ // as a regular expression internally.
+ //
+ // Convert name to index
+ //
+ // MSAntennaIndex
myMSAI(MSAntennaParse::thisMSAParser->ms()->antenna());
+ MSAntennaIndex myMSAI(MSAntennaParse::thisMSAParser->subTable());
+ if (!$$) delete $$;
+ $$ = new Vector<Int>(myMSAI.matchAntennaRegexOrPattern($1,True));
+ if ((*($$)).nelements() == 0) reportError($1);
+ free($1);
+ MSAntennaParse::thisMSAParser->setComplexity(MSAntennaParse::ANTREGEX);
+ }
+
+antidrange: INT // A single antenna index
+ {
+ if (!($$)) delete $$;
+ //
+ // This code is due to VLA specienfic complication
+ // arising due to the fact that VLA antennam "NAMES"
+ // are strings that can be parsed as valid integers!
+ // Believe it or not, VLA antenna NAMES are "1", "2",
+ // "3" and so on..... So (phew). Just for antenna
+ // selection (and this *just* because of silly
+ // convention for VLA antenna naming!), if we get an
+ // INT, treat it as name still and first attempt a
+ // match with the NAME column. If that fails, treat it
+ // as an integer index and do the right thing.
+ //
+ // MSAntennaIndex
myMSAI(MSAntennaParse::thisMSAParser->ms()->antenna());
+ MSAntennaIndex myMSAI(MSAntennaParse::thisMSAParser->subTable());
+ Vector<Int> tmp(myMSAI.matchAntennaName($1));
+ $$ = new Vector<Int>(1);
+ if (tmp.nelements() > 0) (*($$))(0) = tmp[0];
+ else (*($$))(0) = atoi($1);
+ free($1);
+ }
+ | INT DASH INT // A range of integer antenna indices
+ {
+ Int start = atoi($1);
+ Int end = atoi($3);
+ Int len = end - start + 1;
+ Vector<Int> antennaids(len);
+ for(Int i = 0; i < len; i++) antennaids[i] = start + i;
+
+ if (!($$)) delete $$;
+ $$ = new Vector<Int>(len);
+
+ // MSAntennaIndex
myMSAI(MSAntennaParse::thisMSAParser->ms()->antenna());
+ MSAntennaIndex myMSAI(MSAntennaParse::thisMSAParser->subTable());
+ for (Int i=0; i<len; i++)
+ {
+ ostringstream vlaName;
+ vlaName << antennaids[i];
+ Vector<Int> tmp(myMSAI.matchAntennaName(vlaName));
+ if (tmp.nelements() > 0) ((*$$))[i] = tmp[0];
+ else ((*$$))[i] = antennaids[i];
+ }
+ free($1);
+ free($3);
+ }
+
+stationlist: stationid
+ {
+ if (!($$)) delete $$;
+ $$ = new Vector<Int>(*$1);
+ delete $1;
+ }
+ | stationlist COMMA stationid
+ {
+ Int N0=(*($1)).nelements(), N1 = (*($3)).nelements();
+ (*($$)).resize(N0+N1,True); // Resize the existing list
+ for(Int i=N0;i<N0+N1;i++) (*($$))(i) = (*($3))(i-N0);
+ delete $3;
+
MSAntennaParse::thisMSAParser->setComplexity(MSAntennaParse::STATIONLIST);
+ }
+
+antids: antid {$$ = $1;}// A singe antenna ID
+ | antidrange {$$ = $1;}
+ | antatstation {$$ = $1;}
+
+antlist: antids
+ {
+ if (!($$)) delete $$;
+ $$ = new Vector<Int>(*$1);
+ delete $1;
+ }
+ | antlist COMMA antids // AntnnaID, AntnnaID,...
+ {
+ Int N0=(*($1)).nelements(), N1 = (*($3)).nelements();
+ (*($$)).resize(N0+N1,True); // Resize the existing list
+ for(Int i=N0;i<N0+N1;i++) (*($$))(i) = (*($3))(i-N0);
+ delete $3;
+ MSAntennaParse::thisMSAParser->setComplexity(MSAntennaParse::ANTLIST);
+ }
+
+antcomp: antid {$$=$1;}
+ | antidrange {$$=$1;}
+ | LPAREN antlist RPAREN
{$$=$2;MSAntennaParse::thisMSAParser->setComplexity(MSAntennaParse::ANTATSTATIONLIST);}
+
+stationcomp: stationid {$$=$1;}
+ | LPAREN stationlist RPAREN
+
{$$=$2;MSAntennaParse::thisMSAParser->setComplexity(MSAntennaParse::ANTATSTATIONLIST);}
+
+antatstation: antcomp AT stationcomp
+ {
+ if (!($$)) delete $$;
+ $$ = new Vector<Int>(set_intersection(*($1),*($3)));
+ ostringstream token;token
<< "AntID("<<*($1)<<")@StationID("<<*($3)<<")";
+ if ((*($$)).nelements() == 0) reportError((char
*)token.str().c_str(),"Ant@Station Expression");
+ delete $1;
+ delete $3;
+ }
+ | AT stationcomp //Implicit ANT.
+ {
+ if (!($$)) delete $$;
+ $$ = new Vector<Int>(*($2));
+ ostringstream token;token << "@StationID("<<*($2)<<")";
+ if ((*($$)).nelements() == 0) reportError((char
*)token.str().c_str(),"Station Expression");
+ delete $2;
+ }
+
+blengthlist: blength
+ {
+ $$ = $1;
+ }
+ | blengthlist COMMA blength
+ {
+ $$ = $1;
+ $$->push_back ((*$3)[0]);
+ $$->push_back ((*$3)[1]);
+ delete $3;
+ }
+
+blength: LT flunit
+ {
+ $$ = new std::vector<double>();
+ $$->push_back (-1e30);
+ $$->push_back ($2 - 0.000000001);
+ }
+ | LE flunit
+ {
+ $$ = new std::vector<double>();
+ $$->push_back (-1e30);
+ $$->push_back ($2);
+ }
+ | GT flunit
+ {
+ $$ = new std::vector<double>();
+ $$->push_back ($2 + 0.000000001);
+ $$->push_back (1e30);
+ }
+ | GE flunit
+ {
+ $$ = new std::vector<double>();
+ $$->push_back ($2);
+ $$->push_back (1e30);
+ }
+ | flt DASH flt
+ {
+ $$ = new std::vector<double>();
+ $$->push_back ($1);
+ $$->push_back ($3);
+ }
+ | flt DASH flt unit
+ {
+ $$ = new std::vector<double>();
+ $$->push_back ($1 / $4);
+ $$->push_back ($3 / $4);
+ }
+ | flintunit DASH flintunit
+ {
+ $$ = new std::vector<double>();
+ $$->push_back ($1);
+ $$->push_back ($3);
+ }
+
+flunit: flint
+ { $$ = $1; }
+ | flintunit
+ { $$ = $1; }
+
+flintunit: flint unit
+ { $$ = $1/$2; }
+
+unit: UNIT
+ {
+ $$ = MSAntennaParse::getUnitFactor ($1);
+ free($1);
+ }
+
+flint: flt
+ { $$ = $1; }
+ | INT
+ {
+ $$ = atoi($1);
+ free ($1);
+ }
+
+flt: FLOAT
+ {
+ $$ = atof($1);
+ free ($1);
+ }
+
+%%
=======================================
--- /dev/null
+++ /branches/nov14/ms/MSSel/MSAntennaIndex.cc Wed Mar 25 14:33:54 2015 UTC
@@ -0,0 +1,309 @@
+//# MSAntennaIndex.cc: implementation of MSAntennaIndex.h
+//# Copyright (C) 2000,2001,2002
+//# Associated Universities, Inc. Washington DC, USA.
+//#
+//# This library is free software; you can redistribute it and/or modify it
+//# under the terms of the GNU Library General Public License as published
by
+//# the Free Software Foundation; either version 2 of the License, or (at
your
+//# option) any later version.
+//#
+//# This library is distributed in the hope that it will be useful, but
WITHOUT
+//# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+//# FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
+//# License for more details.
+//#
+//# You should have received a copy of the GNU Library General Public
License
+//# along with this library; if not, write to the Free Software Foundation,
+//# Inc., 675 Massachusetts Ave, Cambridge, MA 02139, USA.
+//#
+//# Correspondence concerning AIPS++ should be addressed as follows:
+//# Internet email:
aips2-...@nrao.edu.
+//# Postal address: AIPS++ Project Office
+//# National Radio Astronomy Observatory
+//# 520 Edgemont Road
+//# Charlottesville, VA 22903-2475 USA
+//#
+//# $Id$
+
+#include <casacore/ms/MSSel/MSAntennaIndex.h>
+#include <casacore/ms/MSSel/MSSelectionTools.h>
+#include <casacore/ms/MSSel/MSSelectionError.h>
+#include <casacore/casa/Arrays/MaskedArray.h>
+#include <casacore/casa/Arrays/ArrayMath.h>
+#include <casacore/casa/Arrays/ArrayLogical.h>
+#include <casacore/casa/Arrays/ArrayUtil.h>
+#include <casacore/casa/Arrays/ArrayIO.h>
+#include <casacore/casa/Utilities/Regex.h>
+
+namespace casacore { //# NAMESPACE CASACORE - BEGIN
+
+//-------------------------------------------------------------------------
+
+MSAntennaIndex::MSAntennaIndex(const MSAntenna& antenna)
+ : msAntennaCols_p(antenna)
+{
+// Construct from an MS ANTENNA subtable
+// Input:
+// antenna const MSAntenna& Input MSAntenna object
+// Output to private data:
+// msAntennaCols_p ROMSAntennaColumns MSAntenna columns
accessor
+// antennaIds_p Vector<Int> Antenna id's
+// nrows_p Int Number of rows
+//
+ // Generate an array of antenna id's, used in later queries
+ nrows_p = msAntennaCols_p.nrow();
+ antennaIds_p.resize(nrows_p);
+ stationIds_p.resize(nrows_p);
+ indgen(antennaIds_p);
+ indgen(stationIds_p);
+}
+
+//-------------------------------------------------------------------------
+
+ Vector<Int> MSAntennaIndex::matchId(const Vector<Int>& sourceId)
+ {
+ Vector<Int> IDs;
+ IDs = set_intersection(sourceId,antennaIds_p);
+ if (IDs.nelements() == 0)
+ {
+ ostringstream mesg;
+ mesg << "No match found for the antenna specificion [ID(s): " << sourceId
<< "]";
+ throw (MSSelectionAntennaParseError(mesg));
+ }
+ return IDs;
+ }
+
+//-------------------------------------------------------------------------
+
+Vector<Int> MSAntennaIndex::matchAntennaRegexOrPattern(const String&
pattern,
+ const Bool regex)
+{
+// Match a regular expression or pattern to a set of antenna id's
+// Input:
+// pattern const String& Pattern/regular
expression
+// for Antenna name to match
+// Output:
+// matchAntennaName Vector<Int> Matching antenna id's
+//
+ Int pos=0;
+ Bool negate = False;
+ String patt = pattern;
+ if (patt[0] == '^') {
+ negate = True;
+ patt = patt.from(1);
+ }
+ Regex reg;
+ if (regex) {
+ reg=patt;
+ } else {
+ reg=reg.fromPattern(patt);
+ }
+ // cerr << "Pattern = " << pattern << " Regex = " << reg.regexp() <<
endl;
+ IPosition sh(msAntennaCols_p.name().getColumn().shape());
+ LogicalArray maskArray(sh,False);
+ IPosition i=sh;
+ for(i(0)=0;i(0)<sh(0);i(0)++)
+ {
+ //Int ret=(msAntennaCols_p.name().getColumn()(i).find(reg,pos));
+ Int ret=(msAntennaCols_p.name().getColumn()(i).matches(reg,pos));
+ if (ret <= 0)
+ ret = (msAntennaCols_p.station().getColumn()(i).matches(reg,pos));
+ // cerr << i << " " << ret << endl;
+ maskArray(i) = ( (ret>0) != negate );
+ // && !msAntennaCols_p.flagRow().getColumn()(i));
+ }
+
+ MaskedArray<Int> maskAntennaID(antennaIds_p,maskArray);
+ return maskAntennaID.getCompressedArray();
+}
+
+//-------------------------------------------------------------------------
+
+Vector<Int> MSAntennaIndex::matchAntennaName(const String& name)
+{
+// Match a antenna name to a set of antenna id's
+// Input:
+// name const String& Antenna name to match
+// Output:
+// matchAntennaName Vector<Int> Matching antenna id's
+//
+/*
+ if(name == "*")
+ {
+ LogicalArray maskArray = (True &&
(msAntennaCols_p.flagRow().getColumn()==
+ msAntennaCols_p.flagRow().getColumn()));
+ // !msAntennaCols_p.flagRow().getColumn());
+ MaskedArray<Int> maskAntennaId(antennaIds_p, maskArray);
+ return maskAntennaId.getCompressedArray();
+ }
+ else
+*/
+ {
+ LogicalArray maskArray = (msAntennaCols_p.name().getColumn()==name);
+ MaskedArray<Int> maskAntennaId(antennaIds_p, maskArray);
+ //
+ // If no match with the NAME column, try with the names in the
STATION column.
+ //
+ if (maskAntennaId.getCompressedArray().nelements() == 0)
+ {
+ maskArray = (msAntennaCols_p.station().getColumn()==name);
+ maskAntennaId.setData(antennaIds_p, maskArray);
+ }
+ return maskAntennaId.getCompressedArray();
+ }
+}
+
+//-------------------------------------------------------------------------
+
+Vector<Int> MSAntennaIndex::matchAntennaName(const Vector<String>& names)
+{
+// Match a set of antenna names to a set of antenna id's
+// Input:
+// names const Vector<String>& Antenna names to match
+// Output:
+// matchAntennaNames Vector<Int> Matching antenna id's
+//
+ Vector<Int> matchedAntennaIds;
+ // Match each antenna name individually
+ for (uInt fld=0; fld<names.nelements(); fld++) {
+ // Add to list of antenna id's
+ Vector<Int> currentMatch = matchAntennaName(names(fld));
+ if (currentMatch.nelements() > 0) {
+ Vector<Int> temp(matchedAntennaIds);
+ matchedAntennaIds.resize(matchedAntennaIds.nelements() +
+ currentMatch.nelements(), True);
+ matchedAntennaIds = concatenateArray(temp, currentMatch);
+ }
+ }
+ return matchedAntennaIds;
+}
+
+//-------------------------------------------------------------------------
+
+Vector<Int> MSAntennaIndex::matchStationRegexOrPattern(const String&
pattern,
+ const Bool regex)
+{
+// Match a regular expression or pattern to a set of antenna id's
+// Input:
+// pattern const String& Pattern/regular
expression
+// for Station name to match
+// Output:
+// matchStationName Vector<Int> Matching station id's
+//
+ Int pos=0;
+ Bool negate = False;
+ String patt = pattern;
+ if (patt[0] == '^') {
+ negate = True;
+ patt = patt.from(1);
+ }
+ Regex reg;
+ if (regex) {
+ reg=patt;
+ } else {
+ reg=reg.fromPattern(patt);
+ }
+ // cerr << "Pattern = " << pattern << " Regex = " << reg.regexp() <<
endl;
+ IPosition sh(msAntennaCols_p.station().getColumn().shape());
+ LogicalArray maskArray(sh,False);
+ IPosition i=sh;
+ for(i(0)=0;i(0)<sh(0);i(0)++)
+ {
+ //Int ret=(msAntennaCols_p.name().getColumn()(i).find(reg,pos));
+ Int ret=(msAntennaCols_p.station().getColumn()(i).matches(reg,pos));
+ // if (ret <= 0)
+ // ret =
(msAntennaCols_p.station().getColumn()(i).matches(reg,pos));
+ // cerr << i << " " << ret << endl;
+ maskArray(i) = ( (ret>0) != negate );
+ // && !msAntennaCols_p.flagRow().getColumn()(i));
+ }
+
+ MaskedArray<Int> maskStationID(stationIds_p,maskArray);
+ return maskStationID.getCompressedArray();
+}
+
+//-------------------------------------------------------------------------
+
+Vector<Int> MSAntennaIndex::matchStationName(const String& station)
+{
+// Match a antenna station to a set of antenna id's
+// Input:
+// station const String& Antenna station to match
+// Output:
+// matchAntennaStation Vector<Int> Matching antenna id's
+//
+ // if(station.contains('*'))
+ // {
+ // String subStationName =
station.at(0, station.length()-1);
+ // Vector<String> stationNames =
msAntennaCols_p.station().getColumn();
+ // uInt len = stationNames.nelements();
+ // Vector<Bool> matchstationnames(len, False);
+ // for(uInt j = 0; j < len; j++)
+ // {
+ // if(stationNames[j].contains(subStationName))
+ // matchstationnames(j) = True;
+ // }
+ // LogicalArray maskArray( matchstationnames &&
(msAntennaCols_p.flagRow().getColumn()==
+ // msAntennaCols_p.flagRow().getColumn()));
+ // //!msAntennaCols_p.flagRow().getColumn());
+ // MaskedArray<Int> maskStationId(stationIds_p, maskArray);
+ // return maskAntennaId.getCompressedArray();
+ // }
+ // else
+ {
+ LogicalArray maskArray =
(msAntennaCols_p.station().getColumn()==station);
+ // && !msAntennaCols_p.flagRow().getColumn());
+ MaskedArray<Int> maskStationId(stationIds_p, maskArray);
+ return maskStationId.getCompressedArray();
+ }
+}
+
+//-------------------------------------------------------------------------
+
+Vector<Int> MSAntennaIndex::matchStationName(const Vector<String>& names)
+{
+// Match a set of station names to a set of antenna id's
+// Input:
+// names const Vector<String>& Station names to match
+// Output:
+// matchStationNames Vector<Int> Matching station id's
+//
+ Vector<Int> matchedStationIds;
+ // Match each antenna name individually
+ for (uInt fld=0; fld<names.nelements(); fld++) {
+ // Add to list of antenna id's
+ Vector<Int> currentMatch = matchStationName(names(fld));
+ if (currentMatch.nelements() > 0) {
+ Vector<Int> temp(matchedStationIds);
+ matchedStationIds.resize(matchedStationIds.nelements() +
+ currentMatch.nelements(), True);
+ matchedStationIds = concatenateArray(temp, currentMatch);
+ }
+ }
+ return matchedStationIds;
+}
+
+//-------------------------------------------------------------------------
+
+Vector<Int> MSAntennaIndex::matchAntennaNameAndStation(const String& name,
+ const String& station)
+{
+// Match a antenna and station name pair to a set of antenna id's
+// Input:
+// name const String& Antenna name to match
+// station const String& Station name to match
+// Output:
+// matchAntennaNameAndStation Vector<Int> Matching antenna id's
+//
+ LogicalArray maskArray = (msAntennaCols_p.name().getColumn()==name &&
+ msAntennaCols_p.station().getColumn()==station);
+ // && !msAntennaCols_p.flagRow().getColumn());
+ MaskedArray<Int> maskAntennaId(antennaIds_p, maskArray);
+ return maskAntennaId.getCompressedArray();
+}
+
+//-------------------------------------------------------------------------
+
+
+} //# NAMESPACE CASACORE - END
+
=======================================
--- /dev/null
+++ /branches/nov14/ms/MSSel/MSAntennaIndex.h Wed Mar 25 14:33:54 2015 UTC
@@ -0,0 +1,122 @@
+//# MSAntennaIndex: index or lookup in a MeasurementSet ANTENNA subtable
+//# Copyright (C) 2000,2001,2002
+//# Associated Universities, Inc. Washington DC, USA.
+//#
+//# This library is free software; you can redistribute it and/or modify it
+//# under the terms of the GNU Library General Public License as published
by
+//# the Free Software Foundation; either version 2 of the License, or (at
your
+//# option) any later version.
+//#
+//# This library is distributed in the hope that it will be useful, but
WITHOUT
+//# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+//# FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
+//# License for more details.
+//#
+//# You should have received a copy of the GNU Library General Public
License
+//# along with this library; if not, write to the Free Software Foundation,
+//# Inc., 675 Massachusetts Ave, Cambridge, MA 02139, USA.
+//#
+//# Correspondence concerning AIPS++ should be addressed as follows:
+//# Internet email:
aips2-...@nrao.edu.
+//# Postal address: AIPS++ Project Office
+//# National Radio Astronomy Observatory
+//# 520 Edgemont Road
+//# Charlottesville, VA 22903-2475 USA
+//#
+//#
+//# $Id$
+
+#ifndef MS_MSANTENNAINDEX_H
+#define MS_MSANTENNAINDEX_H
+
+//# includes
+#include <casacore/casa/aips.h>
+#include <casacore/ms/MeasurementSets/MSAntenna.h>
+#include <casacore/ms/MeasurementSets/MSAntennaColumns.h>
+#include <casacore/casa/Arrays/Vector.h>
+#include <casacore/casa/BasicSL/String.h>
+
+namespace casacore { //# NAMESPACE CASACORE - BEGIN
+
+//# forward declarations
+
+// <summary>
+// Class to handle lookup or indexing into a MS ANTENNA subtable
+// </summary>
+
+// <use visibility=export>
+//
+// <reviewed reviewer="" date="yyyy/mm/dd" tests="" demos="">
+// </reviewed>
+
+// <prerequisite>
+// <li> MeasurementSet
+// <li> MSAntenna
+// </prerequisite>
+//
+// <etymology>
+// From "MeasurementSet", "ANTENNA subtable" and "index".
+// </etymology>
+//
+// <synopsis>
+// This class provides lookup and indexing into an MS ANTENNA
+// subtable. These services include returning rows numbers
+// (which for the ANTENNA subtable are ANTENNA_ID's) associated
+// with specific data in the subtable.
+// </synopsis>
+//
+// <example>
+// </example>
+//
+// <motivation>
+// Collect together all subtable indexing and lookup for the
+// ANTENNA subtable, for encapsulation and efficiency.
+// </motivation>
+//
+// <thrown>
+// <li>
+// <li>
+// </thrown>
+//
+
+class MSAntennaIndex
+{
+public:
+ // Construct from an MS ANTENNA subtable
+ MSAntennaIndex(const MSAntenna &antenna);
+
+ // Null destructor
+ virtual ~MSAntennaIndex() {}
+
+ // Look up ANTENNA_ID's for a given a regular expression or pattern
+ Vector<Int> matchAntennaRegexOrPattern(const String& pattern, const Bool
regex=False);
+ // Look up ANTENNA_ID's for a given antenna name, or set of antenna names
+ Vector<Int> matchAntennaName(const String& name);
+ Vector<Int> matchAntennaName(const Vector<String>& names);
+
+ // Look up ANTENNA_ID's for a given antenna station
+ Vector<Int> matchStationRegexOrPattern(const String& pattern, const Bool
regex=False);
+ Vector<Int> matchStationName(const String& station);
+ Vector<Int> matchStationName(const Vector<String>& station);
+
+ // Look up ANTENNA_ID's for a given antenna and station name pair
+ Vector<Int> matchAntennaNameAndStation(const String& name,
+ const String& station);
+
+ Vector<Int> matchId(const Vector<Int>& sourceId);
+private:
+ // Default constructor
+ MSAntennaIndex();
+ // ANTENNA subtable column accessor
+ ROMSAntennaColumns msAntennaCols_p;
+
+ // Vector cache of antenna id's
+ Vector<Int> antennaIds_p, stationIds_p;
+ Int nrows_p;
+};
+
+
+} //# NAMESPACE CASACORE - END
+
+#endif
+
=======================================
--- /dev/null
+++ /branches/nov14/ms/MSSel/MSAntennaParse.cc Wed Mar 25 14:33:54 2015 UTC
@@ -0,0 +1,377 @@
+//# MSAntennaParse.cc: Classes to hold results from antenna grammar parser
+//# Copyright (C) 1994,1995,1997,1998,1999,2000,2001,2003
+//# Associated Universities, Inc. Washington DC, USA.
+//#
+//# This library is free software; you can redistribute it and/or modify it
+//# under the terms of the GNU Library General Public License as published
by
+//# the Free Software Foundation; either version 2 of the License, or (at
your
+//# option) any later version.
+//#
+//# This library is distributed in the hope that it will be useful, but
WITHOUT
+//# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+//# FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
+//# License for more details.
+//#
+//# You should have received a copy of the GNU Library General Public
License
+//# along with this library; if not, write to the Free Software Foundation,
+//# Inc., 675 Massachusetts Ave, Cambridge, MA 02139, USA.
+//#
+//# Correspondence concerning AIPS++ should be addressed as follows:
+//# Internet email:
aips2-...@nrao.edu.
+//# Postal address: AIPS++ Project Office
+//# National Radio Astronomy Observatory
+//# 520 Edgemont Road
+//# Charlottesville, VA 22903-2475 USA
+//#
+//# $Id$
+
+#include <casacore/ms/MSSel/MSAntennaParse.h>
+#include <casacore/ms/MSSel/MSAntennaIndex.h>
+#include <casacore/ms/MSSel/MSSelectionError.h>
+#include <casacore/ms/MeasurementSets/MSAntennaColumns.h>
+#include <casacore/casa/Arrays/ArrayMath.h>
+#include <casacore/casa/BasicSL/String.h>
+#include <casacore/casa/Logging/LogIO.h>
+#include <casacore/ms/MSSel/MSSelectionTools.h>
+#include <casacore/ms/MSSel/MSSelectionErrorHandler.h>
+namespace casacore { //# NAMESPACE CASACORE - BEGIN
+
+ // Global pointer to the parser object
+ MSAntennaParse* MSAntennaParse::thisMSAParser = 0;
+ TableExprNode
MSAntennaParse::column1AsTEN_p,MSAntennaParse::column2AsTEN_p;
+ MSSelectionErrorHandler* MSAntennaParse::thisMSAErrorHandler = 0;
+
+ //# Constructor
+ MSAntennaParse::MSAntennaParse ()
+ : MSParse(),
+ colName1(MS::columnName(MS::ANTENNA1)),
+ colName2(MS::columnName(MS::ANTENNA2)),
+ ant1List(0),ant2List(0), baselineList(0,2)
+ {
+ }
+
+ //# Constructor with given ms name.
+ MSAntennaParse::MSAntennaParse (const MSAntenna& antSubTable,
+ const TableExprNode& ant1AsTEN, const TableExprNode& ant2AsTEN)
+ : MSParse(),
+ colName1(MS::columnName(MS::ANTENNA1)),
+ colName2(MS::columnName(MS::ANTENNA2)),
+ ant1List(0),ant2List(0), baselineList(0,2),
+ msSubTable_p(antSubTable)
+
+ {
+ column1AsTEN_p = ant1AsTEN;
+ column2AsTEN_p = ant2AsTEN;
+ }
+
+ //# Constructor with given ms name.
+ MSAntennaParse::MSAntennaParse (const MeasurementSet* myms)
+ : MSParse(myms, "Antenna"),
+ colName1(MS::columnName(MS::ANTENNA1)),
+ colName2(MS::columnName(MS::ANTENNA2)),
+ ant1List(0),ant2List(0), baselineList(0,2),
+ msSubTable_p(myms->antenna())
+ {
+ column1AsTEN_p = myms->col(myms->columnName(MS::ANTENNA1));
+ column2AsTEN_p = myms->col(myms->columnName(MS::ANTENNA2));
+ }
+
+ // Add the current condition to the TableExprNode tree. Mask auto
+ // correlations if baselineType==CrossOnly
+ //
+ const TableExprNode* MSAntennaParse::setTEN(TableExprNode& condition,
+ BaselineListType
baselineType,
+ Bool negate)
+ {
+ if (baselineType==CrossOnly)
+ {
+ // TableExprNode noAutoCorr = (ms()->col(colName1) !=
ms()->col(colName2));
+ TableExprNode noAutoCorr = (column1AsTEN_p != column2AsTEN_p);
+ condition = noAutoCorr && condition;
+ }
+ // if (negate) cerr << "Generating a negation condition" << endl;
+ if (negate) condition = !condition;
+ if(node_p.isNull()) node_p = condition;
+ else
+ if (negate) node_p = node_p && condition;
+ else node_p = node_p || condition;
+
+ return &node_p;
+ }
+
+ const TableExprNode* MSAntennaParse::selectAntennaIds(const Vector<Int>&
antennaIds,
+ BaselineListType baselineType,
+ Bool negate)
+ {
+ TableExprNode condition;
+ if ((baselineType==AutoCorrAlso) || (baselineType==AutoCorrOnly))
+ {
+ Int n=antennaIds.nelements();
+ if (n)
+ {
+ // condition = ((ms()->col(colName1) == antennaIds[0]) &&
+ // (ms()->col(colName2) == antennaIds[0]));
+ condition = ((column1AsTEN_p == antennaIds[0]) &&
+ (column2AsTEN_p == antennaIds[0]));
+ for (Int i=1;i<n;i++)
+ {
+ condition = condition ||
+ ((column1AsTEN_p == antennaIds[i]) && (column2AsTEN_p ==
antennaIds[i]));
+ // ((ms()->col(colName1) == antennaIds[i]) &&
+ // (ms()->col(colName2) == antennaIds[i]));
+ }
+ }
+ }
+ else
+ {
+ condition =
+ // (ms()->col(colName1).in(antennaIds) ||
+ // ms()->col(colName2).in(antennaIds)); //&& ms()->col(colName1) !=
ms()->col(colName2);
+ (column1AsTEN_p.in(antennaIds) ||
+ column2AsTEN_p.in(antennaIds)); //&& ms()->col(colName1) !=
ms()->col(colName2);
+ }
+ {
+ Int nrows_p = subTable().nrow();//ms()->antenna().nrow();
+ Vector<Int> a2(nrows_p);
+ a2.resize(nrows_p);
+ indgen(a2);
+
+ makeAntennaList(ant1List, antennaIds,negate);
+ makeAntennaList(ant2List, a2);
+ if (negate)
makeBaselineList(-antennaIds,a2,baselineList,baselineType, negate);
+ else
makeBaselineList(antennaIds,a2,baselineList,baselineType, negate);
+ }
+ // setTEN(condition, AutoCorrAlso, negate);
+ return setTEN(condition, baselineType, negate);
+ }
+
+ void MSAntennaParse::makeAntennaList(Vector<Int>& antList,const
Vector<Int>& thisList,
+ Bool negate)
+ {
+ Vector<Int> a2;
+ if (negate) a2=-thisList;
+ else a2=thisList;
+
+ Vector<Int> tmp1(set_union(a2,antList));
+ antList.resize(tmp1.nelements());antList = tmp1;
+ }
+
+ const TableExprNode* MSAntennaParse::selectAntennaIds(const Vector<Int>&
antennaIds1,
+ const Vector<Int>& antennaIds2,
+ BaselineListType baselineType,
+ Bool negate)
+ {
+ TableExprNode condition;
+
+ if (antennaIds2.size())
+ {
+ condition =
+ // (ms()->col(colName1).in(antennaIds1) &&
ms()->col(colName2).in(antennaIds2)) ||
+ // (ms()->col(colName1).in(antennaIds2) &&
ms()->col(colName2).in(antennaIds1));
+ (column1AsTEN_p.in(antennaIds1) && column2AsTEN_p.in(antennaIds2)) ||
+ (column1AsTEN_p.in(antennaIds2) && column2AsTEN_p.in(antennaIds1));
+ }
+ else
+ {
+ condition =
+ // (ms()->col(colName1).in(antennaIds1) &&
ms()->col(colName2).in(antennaIds1));
+ (column1AsTEN_p.in(antennaIds1) && column2AsTEN_p.in(antennaIds1));
+ }
+ makeAntennaList(ant1List, antennaIds1,negate);
+ makeAntennaList(ant2List, antennaIds2,negate);
+
+ if (negate) makeBaselineList(-antennaIds1, -antennaIds2,baselineList,
baselineType, negate);
+ else makeBaselineList(antennaIds1, antennaIds2,baselineList,
baselineType, negate);
+
+ return setTEN(condition,baselineType,negate);
+ }
+
+ const TableExprNode* MSAntennaParse::selectNameOrStation(const
Vector<String>& antenna,
+ BaselineListType baselineType,
+ Bool negate)
+ {
+ // MSAntennaIndex msAI(ms()->antenna());
+ MSAntennaIndex msAI(subTable());
+
+ Vector<Int> ant=msAI.matchAntennaName(antenna);
+
+ // TableExprNode condition =(ms()->col(colName1).in(ant) ||
ms()->col(colName2).in(ant));
+ TableExprNode condition =(column1AsTEN_p.in(ant) ||
column2AsTEN_p.in(ant));
+
+ return setTEN(condition,baselineType,negate);
+ }
+
+ const TableExprNode* MSAntennaParse::selectNameOrStation(const
Vector<String>& antenna1,
+ const Vector<String>& antenna2,
+ BaselineListType baselineType,
+ Bool negate)
+ {
+ // MSAntennaIndex msAI(ms()->antenna());
+ MSAntennaIndex msAI(subTable());
+
+ Vector<Int> a1=msAI.matchAntennaName(antenna1),
+ a2 = msAI.matchAntennaName(antenna2);
+
+ // TableExprNode condition =
+ // (ms()->col(colName1).in(a1) && ms()->col(colName2).in(a2)) ||
+ // (ms()->col(colName1).in(a2) && ms()->col(colName2).in(a1));
+ TableExprNode condition =
+ (column1AsTEN_p.in(a1) && column2AsTEN_p.in(a2)) ||
+ (column1AsTEN_p.in(a2) && column2AsTEN_p.in(a1));
+
+ return setTEN(condition,baselineType,negate);
+ }
+
+ const TableExprNode* MSAntennaParse::selectNameOrStation(const String&
antenna1,
+ const String& antenna2,
+ BaselineListType baselineType,
+ Bool negate)
+ {
+ // TableExprNode condition =
+ // (ms()->col(colName1) >= antenna1 && ms()->col(colName2) <=
antenna2) ||
+ // (ms()->col(colName2) >= antenna1 && ms()->col(colName1) <=
antenna2);
+ TableExprNode condition =
+ (column1AsTEN_p >= antenna1 && column2AsTEN_p <= antenna2) ||
+ (column2AsTEN_p >= antenna1 && column1AsTEN_p <= antenna2);
+
+ return setTEN(condition,baselineType,negate);
+ }
+
+
+ const TableExprNode* MSAntennaParse::selectLength
+ (const std::vector<double>& lengths, Bool negate)
+ {
+ TableExprNode selAnt1, selAnt2;
+ Matrix<double> blength = getBaselineLengths();
+ Matrix<Bool> match(blength.shape());
+ match = False;
+ int nr=0;
+ for (Int j=0; j<blength.shape()[1]; ++j) {
+ for (Int i=0; i<blength.shape()[0]; ++i) {
+ double bl = blength(i,j);
+ for (uInt k=0; k<lengths.size(); k+=2) {
+ if (bl >= lengths[k] && bl <= lengths[k+1]) {
+ match(i,j) = True;
+ ++nr;
+ }
+ }
+ }
+ }
+ vector<Int> ant1, ant2;
+ for (Int i=0; i<blength.shape()[0]; ++i) {
+ for (Int j=0; j<blength.shape()[1]; ++j) {
+ if (match(i,j)) {
+ ant1.push_back (i);
+ ant2.push_back (j);
+ if (addBaseline (baselineList, i, j, AutoCorrAlso)) {
+ IPosition newSize = baselineList.shape();
+ int nb = newSize[0];
+ newSize[0] = nb+1;
+ baselineList.resize (newSize,True);
+ baselineList(nb,0) = i;
+ baselineList(nb,1) = j;
+ }
+ }
+ }
+ }
+ TableExprNode condition(False);
+ if (ant1.size() > 0) {
+ Array<Int> arrAnt1(IPosition(1,ant1.size()), &(ant1[0]), SHARE);
+ Array<Int> arrAnt2(IPosition(1,ant1.size()), &(ant2[0]), SHARE);
+ // condition = TableExprNode(any((ms()->col(colName1) == arrAnt1 &&
+ // ms()->col(colName2) == arrAnt2)));
+ condition = TableExprNode(any((column1AsTEN_p == arrAnt1 &&
+ column2AsTEN_p == arrAnt2)));
+ }
+ return setTEN (condition, AutoCorrAlso, negate);
+ }
+
+ Matrix<double> MSAntennaParse::getBaselineLengths()
+ {
+ // MSAntenna msant(ms()->antenna());
+ MSAntenna msant(subTable());
+ ROMSAntennaColumns antCols(msant);
+ // First get the antenna positions.
+ vector<Vector<double> > antVec;
+ antVec.reserve (msant.nrow());
+ for (uInt i=0; i<msant.nrow(); ++i) {
+ // Convert to ITRF and keep as x,y,z in m.
+ antVec.push_back
+ (MPosition::Convert(antCols.positionMeas()(i),
+ MPosition::ITRF)().getValue().getValue());
+ }
+ // Fill in the length of each baseline.
+ Matrix<double> blength(antVec.size(), antVec.size());
+ for (uInt j=0; j<antVec.size(); ++j) {
+ for (uInt i=0; i<antVec.size(); ++i) {
+ Array<double> diff(antVec[i] - antVec[j]);
+ blength(i,j) = sqrt(sum(diff*diff));
+ }
+ }
+ return blength;
+ }
+
+ double MSAntennaParse::getUnitFactor (const char* unit)
+ {
+ // Check if conversion is possible.
+ Unit u(unit);
+ Quantity q(1., "m");
+ if (! q.isConform (u)) {
+ throw MSSelectionAntennaParseError (String("Unit ") + unit +
+ " must be a distance unit (like
m)");
+ }
+ // Get conversion factor.
+ return q.getValue (unit);
+ }
+
+ Bool MSAntennaParse::addBaseline(const Matrix<Int>& baselist,
+ const Int ant1, const Int ant2,
+ BaselineListType baselineType)
+ {
+ Bool doAutoCorr;
+ doAutoCorr = (baselineType==AutoCorrAlso) ||
(baselineType==AutoCorrOnly);
+ if ((ant1 == ant2) && (!doAutoCorr)) return False;
+ if ((baselineType==AutoCorrOnly) && (ant1!=ant2)) return False;
+
+ Int n=baselist.shape()(0);
+ for (Int i=0;i<n;i++) {
+ if (((baselist(i,0)==ant1) && (baselist(i,1)==ant2)) ||
+ ((baselist(i,1)==ant1) && (baselist(i,0)==ant2))) {
+ return False;
+ }
+ }
+ return True;
+ }
+
+ //
+ // Method to make a list of unique baselines, given a list of
+ // antenna1 and antenna2. The baselines list is appended to the
+ // existing list. The required sizing could be done better.
+ //
+ void MSAntennaParse::makeBaselineList(const Vector<Int>& a1,
+ const Vector<Int>& a2,
+ Matrix<Int>& baselist,
+ BaselineListType baselineType,
+ Bool /*negate*/)
+ {
+ Int n1,n2,nb0;
+ n1=a1.nelements(); n2=a2.nelements();
+ nb0=baselist.shape()(0);
+ IPosition newSize(2,nb0,2);
+
+ for (Int i1=0;i1<n1;i1++) {
+ for (int i2=0;i2<n2;i2++) {
+ Int ant1, ant2;
+ ant1=a1[i1]; ant2=a2[i2];
+ if (addBaseline(baselist,ant1,ant2,baselineType)) {
+ nb0++;
+ newSize[0]=nb0;
+ baselist.resize(newSize,True);
+ baselist(nb0-1,0)=ant1;
+ baselist(nb0-1,1)=ant2;
+ }
+ }
+ }
+ }
+
+} //# NAMESPACE CASACORE - END
=======================================
--- /dev/null
+++ /branches/nov14/ms/MSSel/MSAntennaParse.h Wed Mar 25 14:33:54 2015 UTC
@@ -0,0 +1,183 @@
+//# MSAntennaParse.h: Classes to hold results from antenna grammar parser
+//# Copyright (C) 1994,1995,1997,1998,1999,2000,2001,2003
+//# Associated Universities, Inc. Washington DC, USA.
+//#
+//# This library is free software; you can redistribute it and/or modify it
+//# under the terms of the GNU Library General Public License as published
by
+//# the Free Software Foundation; either version 2 of the License, or (at
your
+//# option) any later version.
+//#
+//# This library is distributed in the hope that it will be useful, but
WITHOUT
+//# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+//# FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
+//# License for more details.
+//#
+//# You should have received a copy of the GNU Library General Public
License
+//# along with this library; if not, write to the Free Software Foundation,
+//# Inc., 675 Massachusetts Ave, Cambridge, MA 02139, USA.
+//#
+//# Correspondence concerning AIPS++ should be addressed as follows:
+//# Internet email:
aips2-...@nrao.edu.
+//# Postal address: AIPS++ Project Office
+//# National Radio Astronomy Observatory
+//# 520 Edgemont Road
+//# Charlottesville, VA 22903-2475 USA
+//#
+//# $Id$
+
+#ifndef MS_MSANTENNAPARSE_H
+#define MS_MSANTENNAPARSE_H
+
+//# Includes
+#include <casacore/casa/aips.h>
+#include <casacore/ms/MSSel/MSParse.h>
+#include <casacore/ms/MSSel/MSSelectionErrorHandler.h>
+#include <casacore/casa/Arrays/Matrix.h>
+#include <bitset>
+namespace casacore { //# NAMESPACE CASACORE - BEGIN
+
+ //# Forward Declarations
+
+ // <summary>
+ // Class to hold values from antenna grammar parser
+ // </summary>
+
+ // <use visibility=local>
+
+ // <reviewed reviewer="" date="" tests="">
+ // </reviewed>
+
+ // <prerequisite>
+ //# Classes you should understand before using this one.
+ // </prerequisite>
+
+ // <etymology>
+ // MSAntennaParse is the class used to parse a antenna command.
+ // </etymology>
+
+ // <synopsis>
+ // MSAntennaParse is used by the parser of antenna sub-expression
statements.
+ // The parser is written in Bison and Flex in files MSAntennaGram.y
and .l.
+ // The statements in there use the routines in this file to act
+ // upon a reduced rule.
+ // Since multiple tables can be given (with a shorthand), the table
+ // names are stored in a list. The variable names can be qualified
+ // by the table name and will be looked up in the appropriate table.
+ //
+ // The class MSAntennaParse only contains information about a table
+ // used in the table command. Global variables (like a list and a vector)
+ // are used in MSAntennaParse.cc to hold further information.
+ //
+ // Global functions are used to operate on the information.
+ // The main function is the global function msAntennaCommand.
+ // It executes the given STaQL command and returns the resulting ms.
+ // This is, in fact, the only function to be used by a user.
+ // </synopsis>
+
+ // <motivation>
+ // It is necessary to be able to give a ms command in ASCII.
+ // This can be used in a CLI or in the table browser to get a subset
+ // of a table or to sort a table.
+ // </motivation>
+
+ //# <todo asof="$DATE:$">
+ //# A List of bugs, limitations, extensions or planned refinements.
+ //# </todo>
+
+
+ class MSAntennaParse : public MSParse
+ {
+
+ public:
+ // Define the operator types (&&&, &&, and &).
+ enum BaselineListType {AutoCorrOnly=0, AutoCorrAlso, CrossOnly};
+ enum ComplexityLevels {RESET=0,ANTREGEX,ANTLIST,STATIONREGEX,
STATIONLIST, ANTATSTATIONLIST, BASELINELIST,HIGHESTLEVEL};
+
+ // Default constructor
+ MSAntennaParse();
+
+ // Associate the ms.
+ MSAntennaParse (const MeasurementSet* ms);
+
+ MSAntennaParse (const MSAntenna& antSubTable,
+ const TableExprNode& ant1AsTEN, const TableExprNode& ant2AsTEN);
+
+ ~MSAntennaParse()
{column1AsTEN_p=TableExprNode();column2AsTEN_p=TableExprNode();}
+
+ // Add the given antennae selection.
+ const TableExprNode* selectAntennaIds(const Vector<Int>& antennaIds,
+ BaselineListType baselineType=CrossOnly,
+ Bool negate=False);
+
+ // Add the given baseline selection.
+ const TableExprNode* selectAntennaIds(const Vector<Int>& antennaIds1,
+ const Vector<Int>& antennaIds2,
+ BaselineListType baselineType=CrossOnly,
+ Bool negate=False);
+
+ // Select by name or station number.
+ const TableExprNode* selectNameOrStation(const Vector<String>& antenna,
+ BaselineListType baselineType=CrossOnly,
+ Bool negate=False);
+ const TableExprNode* selectNameOrStation(const Vector<String>&
antenna1,
+ const Vector<String>&
antenna2,
+ BaselineListType baselineType=CrossOnly,
+ Bool negate=False);
+
+ const TableExprNode* selectNameOrStation(const String& antenna1,
+ const String& antenna2,
+ BaselineListType baselineType=CrossOnly,
+ Bool negate=False);
+
+ // Selection on baseline length
+ const TableExprNode* selectLength(const std::vector<double>& lengths,
+ Bool negate=False);
+
+ // Get a pointer to the table expression node object.
+ TableExprNode node() const
+ { return node_p; }
+ const Vector<Int>& selectedAnt1() const
+ { return ant1List; }
+ const Vector<Int>& selectedAnt2() const
+ { return ant2List; }
+ const Matrix<Int>& selectedBaselines() const
+ { return baselineList; }
+
+ // Get the factor to convert the given unit to m.
+ static double getUnitFactor (const char* unit);
+
+ void setComplexity(const ComplexityLevels& level=RESET)
+ {if (level==RESET) complexity.reset(); else
complexity.set(level,True);}
+ std::bitset<HIGHESTLEVEL> getComplexity() {return complexity;}
+ MSAntenna& subTable() {return msSubTable_p;}
+ private:
+ const TableExprNode* setTEN(TableExprNode& condition,
+ BaselineListType baselineType=CrossOnly,
+ Bool negate=False);
+ Matrix<double> getBaselineLengths();
+ void makeBaselineList(const Vector<Int>&a1, const Vector<Int>&a2,
Matrix<Int>&b,
+ BaselineListType baselineType=CrossOnly,
+ Bool negate=False);
+ void makeAntennaList(Vector<Int>& antList,const Vector<Int>& thisList,
+ Bool negate=False);
+ Bool addBaseline(const Matrix<Int>& baselist,
+ const Int ant1, const Int ant2,
+ BaselineListType baselineType=CrossOnly);
+
+ //# Data members.
+ public:
+ static MSAntennaParse* thisMSAParser;
+ static MSSelectionErrorHandler* thisMSAErrorHandler;
+ std::bitset<HIGHESTLEVEL> complexity;
+ private:
+ TableExprNode node_p;
+ const String colName1, colName2;
+ Vector<Int> ant1List, ant2List;
+ Matrix<Int> baselineList;
+ MSAntenna msSubTable_p;
+ static TableExprNode column1AsTEN_p,column2AsTEN_p;
+ };
+
+} //# NAMESPACE CASACORE - END
+
+#endif
=======================================
--- /dev/null
+++ /branches/nov14/ms/MSSel/MSArrayGram.cc Wed Mar 25 14:33:54 2015 UTC
@@ -0,0 +1,161 @@
+//# MSArrayGram.cc: Grammar for scan expressions
+//# Copyright (C) 1998,1999,2001,2003
+//# Associated Universities, Inc. Washington DC, USA.
+//#
+//# This library is free software; you can redistribute it and/or modify it
+//# under the terms of the GNU Library General Public License as published
by
+//# the Free Software Foundation; either version 2 of the License, or (at
your
+//# option) any later version.
+//#
+//# This library is distributed in the hope that it will be useful, but
WITHOUT
+//# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+//# FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
+//# License for more details.
+//#
+//# You should have received a copy of the GNU Library General Public
License
+//# along with this library; if not, write to the Free Software Foundation,
+//# Inc., 675 Massachusetts Ave, Cambridge, MA 02139, USA.
+//#
+//# Correspondence concerning AIPS++ should be addressed as follows:
+//# Internet email:
aips2-...@nrao.edu.
+//# Postal address: AIPS++ Project Office
+//# National Radio Astronomy Observatory
+//# 520 Edgemont Road
+//# Charlottesville, VA 22903-2475 USA
+//#
+//# $Id$
+
+// MSArrayGram; grammar for scan command lines
+
+// This file includes the output files of bison and flex for
+// parsing command lines.
+
+#include <casacore/tables/TaQL/ExprNode.h>
+#include <casacore/tables/TaQL/ExprNodeSet.h>
+#include <casacore/ms/MeasurementSets/MeasurementSet.h>
+#include <casacore/ms/MSSel/MSArrayGram.h>
+#include <casacore/ms/MSSel/MSArrayParse.h> // routines used by bison
actions
+#include <casacore/tables/TaQL/TableParse.h> // routines used by
bison actions
+#include <casacore/tables/Tables/TableError.h>
+
+//# stdlib.h is needed for bison 1.28 and needs to be included here
+//# (before the flex/bison files).
+#include <casacore/casa/stdlib.h>
+//# Define register as empty string to avoid warnings in C++11 compilers
+//# because keyword register is not supported anymore.
+#define register
+#include "MSArrayGram.ycc" // bison output
+#include "MSArrayGram.lcc" // flex output
+
+// Define the yywrap function for flex.
+int MSArrayGramwrap()
+{
+ return 1;
+}
+
+namespace casacore { //# NAMESPACE CASACORE - BEGIN
+
+//# Declare a file global pointer to a char* for the input string.
+static const char* strpMSArrayGram = 0;
+static Int posMSArrayGram = 0;
+
+
+//# Parse the command.
+//# Do a yyrestart(yyin) first to make the flex scanner reentrant.
+ TableExprNode msArrayGramParseCommand (const MeasurementSet* ms, const
String& command,
+ Vector<Int>& selectedIDs, Int maxArrays)
+{
+ try
+ {
+ MSArrayGramrestart (MSArrayGramin);
+ yy_start = 1;
+ strpMSArrayGram = command.chars(); // get pointer to command
string
+ posMSArrayGram = 0; // initialize string position
+ MSArrayParse parser(ms); // setup measurement set
+ MSArrayParse::thisMSAParser = &parser; // The global pointer to the
parser
+ parser.reset();
+ parser.setMaxArray(maxArrays);
+ MSArrayGramparse(); // parse command string
+
+ selectedIDs=parser.selectedIDs();
+ return parser.node();
+ }
+ catch (MSSelectionArrayError &x)
+ {
+ String newMesgs;
+ newMesgs = constructMessage(msArrayGramPosition(), command);
+ x.addMessage(newMesgs);
+ throw;
+ }
+}
+
+//# Give the table expression node
+// const TableExprNode* msArrayGramParseNode()
+// {
+// return MSArrayParse::thisMSAParser->node();
+// }
+// void msArrayGramParseDeleteNode()
+// {
+// return MSArrayParse::cleanup();
+// }
+
+//# Give the string position.
+Int& msArrayGramPosition()
+{
+ return posMSArrayGram;
+}
+
+//# Get the next input characters for flex.
+int msArrayGramInput (char* buf, int max_size)
+{
+ int nr=0;
+ while (*strpMSArrayGram != 0) {
+ if (nr >= max_size) {
+ break; // get max. max_size char.
+ }
+ buf[nr++] = *strpMSArrayGram++;
+ }
+ return nr;
+}
+
+void MSArrayGramerror (const char*)
+{
+ throw (MSSelectionArrayError ("Array Expression: Parse error at or
near '" +
+ String(MSArrayGramtext) + "'"));
+}
+
+// String msArrayGramRemoveEscapes (const String& in)
+// {
+// String out;
+// int leng = in.length();
+// for (int i=0; i<leng; i++) {
+// if (in[i] == '\\') {
+// i++;
+// }
+// out += in[i];
+// }
+// return out;
+// }
+
+// String msArrayGramRemoveQuotes (const String& in)
+// {
+// //# A string is formed as "..."'...''...' etc.
+// //# All ... parts will be extracted and concatenated into an output
string.
+// String out;
+// String str = in;
+// int leng = str.length();
+// int pos = 0;
+// while (pos < leng) {
+// //# Find next occurrence of leading ' or ""
+// int inx = str.index (str[pos], pos+1);
+// if (inx < 0) {
+// throw (AipsError ("MSArrayParse - Ill-formed quoted string: " +
+// str));
+// }
+// out +=
str.at (pos+1, inx-pos-1); // add substring
+// pos = inx+1;
+// }
+// return out;
+// }
+
+} //# NAMESPACE CASACORE - END
=======================================
--- /dev/null
+++ /branches/nov14/ms/MSSel/MSArrayGram.h Wed Mar 25 14:33:54 2015 UTC
@@ -0,0 +1,102 @@
+//# MSArrayGram.h: Grammar for ms scan sub-expressions
+//# Copyright (C) 1998
+//# Associated Universities, Inc. Washington DC, USA.
+//#
+//# This library is free software; you can redistribute it and/or modify it
+//# under the terms of the GNU Library General Public License as published
by
+//# the Free Software Foundation; either version 2 of the License, or (at
your
+//# option) any later version.
+//#
+//# This library is distributed in the hope that it will be useful, but
WITHOUT
+//# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+//# FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
+//# License for more details.
+//#
+//# You should have received a copy of the GNU Library General Public
License
+//# along with this library; if not, write to the Free Software Foundation,
+//# Inc., 675 Massachusetts Ave, Cambridge, MA 02139, USA.
+//#
+//# Correspondence concerning AIPS++ should be addressed as follows:
+//# Internet email:
aips2-...@nrao.edu.
+//# Postal address: AIPS++ Project Office
+//# National Radio Astronomy Observatory
+//# 520 Edgemont Road
+//# Charlottesville, VA 22903-2475 USA
+//#
+//# $Id$
+
+#ifndef MS_MSARRAYGRAM_H
+#define MS_MSARRAYGRAM_H
+
+
+//# Includes
+#include <casacore/casa/aips.h>
+#include <casacore/casa/BasicSL/String.h>
+
+namespace casacore { //# NAMESPACE CASACORE - BEGIN
+
+//# Forward Declarations
+class MeasurementSet;
+class TableExprNode;
+
+// <summary>
+// Global functions for flex/bison scanner/parser for MSArrayGram
+// </summary>
+
+// <use visibility=local>
+
+// <reviewed reviewer="" date="" tests="">
+// </reviewed>
+
+// <prerequisite>
+//# Classes you should understand before using this one.
+// <li> MSArrayGram.l and .y (flex and bison grammar)
+// </prerequisite>
+
+// <synopsis>
+// Global functions are needed to define the input of the flex scanner
+// and to start the bison parser.
+// The input is taken from a string.
+// </synopsis>
+
+// <motivation>
+// It is necessary to be able to give an image expression in ASCII.
+// This can be used in glish.
+// </motivation>
+// <todo asof="$DATE:$">
+//# A List of bugs, limitations, extensions or planned refinements.
+// </todo>
+
+
+// <group name=MSArrayGramFunctions>
+
+// Declare the bison parser (is implemented by bison command).
+ TableExprNode msArrayGramParseCommand (const MeasurementSet *ms, const
String& command,
+ Vector<Int>& idList, Int maxArrays=1000);
+
+// The yyerror function for the parser.
+// It throws an exception with the current token.
+void MSArrayGramerror (const char*);
+
+// Give the table expression node.
+// const TableExprNode *msArrayGramParseNode();
+// void msArrayGramParseDeleteNode();
+
+// Give the current position in the string.
+// This can be used when parse errors occur.
+Int& msArrayGramPosition();
+
+// Declare the input routine for flex/bison.
+int msArrayGramInput (char* buf, int max_size);
+
+// A function to remove escaped characters.
+//String msArrayGramRemoveEscapes (const String& in);
+
+// A function to remove quotes from a quoted string.
+//String msArrayGramRemoveQuotes (const String& in);
+
+// </group>
+
+} //# NAMESPACE CASACORE - END
+
+#endif
=======================================
--- /dev/null
+++ /branches/nov14/ms/MSSel/MSArrayGram.ll Wed Mar 25 14:33:54 2015 UTC
@@ -0,0 +1,84 @@
+/* -*- C -*-
+ MSArrayGram.l: Lexical analyzer for ms selection commands
+ Copyright (C) 1994,1995,1996,1997,1998,2001,2003
+ Associated Universities, Inc. Washington DC, USA.
+
+ This library is free software; you can redistribute it and/or modify it
+ under the terms of the GNU Library General Public License as published
by
+ the Free Software Foundation; either version 2 of the License, or (at
your
+ option) any later version.
+
+ This library is distributed in the hope that it will be useful, but
WITHOUT
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
+ License for more details.
+
+ You should have received a copy of the GNU Library General Public
License
+ along with this library; if not, write to the Free Software Foundation,
+ Inc., 675 Massachusetts Ave, Cambridge, MA 02139, USA.
+
+ Correspondence concerning AIPS++ should be addressed as follows:
+ Internet email:
aips2-...@nrao.edu.
+ Postal address: AIPS++ Project Office
+ National Radio Astronomy Observatory
+ 520 Edgemont Road
+ Charlottesville, VA 22903-2475 USA
+
+ $Id$
+*/
+
+/* yy_unput is not used, so let flex not generate it, otherwise picky
+ compilers will issue warnings. */
+%option nounput
+
+%{
+#undef YY_INPUT
+#define YY_INPUT(buf,result,max_size) result=msArrayGramInput(buf,max_size)
+
+#undef YY_DECL
+#define YY_DECL int MSArrayGramlex (YYSTYPE* lvalp)
+static string qstr;
+#include <casacore/ms/MSSel/MSSelectionTools.h>
+%}
+
+WHITE [ \t\n]*
+DIGIT [0-9]
+INT ({WHITE}{DIGIT}+{WHITE})
+
+/* rules */
+%%
+{INT} { msArrayGramPosition() += yyleng;
+ lvalp->str = (char *)malloc((strlen(MSArrayGramtext) + 1) *
sizeof(char));
+ strcpy(lvalp->str, stripWhite(MSArrayGramtext).c_str());
+ // cout << "INT = \"" << MSArrayGramtext << "\" \"" <<
lvalp->str << "\"" << endl;
+
+ return INT;
+ }
+
+"~" { msArrayGramPosition() += yyleng;
+ return DASH; }
+"," { msArrayGramPosition() += yyleng;
+ return COMMA;
+ }
+"<" { msArrayGramPosition() += yyleng;
+ return LT;
+ }
+">" { msArrayGramPosition() += yyleng;
+ return GT;
+ }
+"<=" { msArrayGramPosition() += yyleng;
+ return LE;
+ }
+">=" { msArrayGramPosition() += yyleng;
+ return GE;
+ }
+"&" { msArrayGramPosition() += yyleng;
+ return AMPERSAND;
+ }
+ /* Literals */
+
+"(" { msArrayGramPosition() += yyleng; return LPAREN; }
+")" { msArrayGramPosition() += yyleng; return RPAREN;}
+{WHITE} { msArrayGramPosition() += yyleng;} /* Eat white spaces */
+. { msArrayGramPosition() += yyleng;return MSArrayGramtext[0];}
+%%
=======================================
--- /dev/null
+++ /branches/nov14/ms/MSSel/MSArrayGram.yy Wed Mar 25 14:33:54 2015 UTC
@@ -0,0 +1,153 @@
+/* -*- C++ -*-
+ MSArrayGram.y: Parser for scan expressions
+ Copyright (C) 2004
+ Associated Universities, Inc. Washington DC, USA.
+
+ This library is free software; you can redistribute it and/or modify it
+ under the terms of the GNU Library General Public License as published
by
+ the Free Software Foundation; either version 2 of the License, or (at
your
+ option) any later version.
+
+ This library is distributed in the hope that it will be useful, but
WITHOUT
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
+ License for more details.
+
+ You should have received a copy of the GNU Library General Public
License
+ along with this library; if not, write to the Free Software Foundation,
+ Inc., 675 Massachusetts Ave, Cambridge, MA 02139, USA.
+
+ Correspondence concerning AIPS++ should be addressed as follows:
+ Internet email:
aips2-...@nrao.edu.
+ Postal address: AIPS++ Project Office
+ National Radio Astronomy Observatory
+ 520 Edgemont Road
+ Charlottesville, VA 22903-2475 USA
+
+ $Id$
+*/
+
+%{
+#include <errno.h>
+ using namespace casacore;
+%}
+
+%pure-parser /* make parser re-entrant */
+
+%union {
+ const TableExprNode* node;
+ Block<TableExprNode>* exprb;
+ TableExprNodeSetElem* elem;
+ TableExprNodeSet* settp;
+ Int ival[2];
+ char * str;
+ Double dval;
+ std::vector<Int>* iv; // std::vectors have push_back, insert, etc.
+ Vector<String>* is;
+}
+
+
+%token EQASS
+%token SQUOTE
+%token <str> IDENTIFIER
+%token COMMA
+
+%token LBRACKET
+%token LPAREN
+%token RBRACKET
+%token RPAREN
+%token LBRACE
+%token RBRACE
+%token WHITE
+
+%token <str> INT
+%token <str> QSTRING
+%token <str> REGEX
+
+%token COLON
+%token SEMICOLON
+
+%type <node> scanstatement
+%type <node> compoundexpr
+%type <node> scanboundsexpr
+%type <node> scanidbounds
+%type <iv> scanids
+
+%nonassoc EQ EQASS GT GE LT LE NE COMMA DASH AMPERSAND
+
+%{
+ int MSArrayGramlex (YYSTYPE*);
+%}
+
+%%
+scanstatement: compoundexpr {$$ =
MSArrayParse::thisMSAParser->selectArrayIds();}
+ ;
+// Here, for ID-list expressions (INT and INT DASH INT), we only
+// collect the list of IDs generated (accumulated internally in
+// MSArrayPrase). The accumulated IDs are used for selection in the
+// terminal node above. Bounds expressions are however used for
+// selection as they are parsed.
+compoundexpr: scanids {/*$$ =
MSArrayParse::thisMSAParser->node();*/}
+ | scanboundsexpr {$$=$1;}
+ | compoundexpr COMMA scanids {$$=$1;}
+ | compoundexpr COMMA scanboundsexpr {$$=$1;}
+ ;
+
+scanidbounds: LT INT // <ID
+ {
+ const Vector<Int> idv(1,atoi($2));
+ $$ = MSArrayParse::thisMSAParser->selectArrayIdsLT(idv);
+ free($2);
+ }
+ | GT INT // >ID
+ {
+ const Vector<Int> idv(1,atoi($2));
+ $$ = MSArrayParse::thisMSAParser->selectArrayIdsGT(idv);
+ free($2);
+ }
+ | LE INT // <=ID
+ {
+ const Vector<Int> idv(1,atoi($2));
+ $$ = MSArrayParse::thisMSAParser->selectArrayIdsLTEQ(idv);
+ free($2);
+ }
+ | GE INT // >=ID
+ {
+ const Vector<Int> idv(1,atoi($2));
+ $$ = MSArrayParse::thisMSAParser->selectArrayIdsGTEQ(idv);
+ free($2);
+ }
+ | GE INT AMPERSAND LE INT // >=ID & <=ID
+ {
+ Int n0=atoi($2), n1=atoi($5);
+ $$ = MSArrayParse::thisMSAParser->selectRangeGEAndLE(n0,n1);
+
+ free($2); free($5);
+ }
+ | GT INT AMPERSAND LT INT // >ID & <ID
+ {
+ Int n0=atoi($2), n1=atoi($5);
+ $$ = MSArrayParse::thisMSAParser->selectRangeGTAndLT(n0,n1);
+
+ free($2); free($5);
+ }
+ ;
+scanboundsexpr: scanidbounds {$$=$1;}
+//
+// Build a list of scan IDs. This can be a single ID or a range of
+// IDs converted to a list. Actual selection is done at the end of
+// parsing cycle (at the terminal node above).
+//
+scanids: INT
+ {
+ $$=&MSArrayParse::thisMSAParser->accumulateIDs(atoi($1));
+ free($1);
+ }
+ | INT DASH INT
+ {
+ $$=&MSArrayParse::thisMSAParser->accumulateIDs(atoi($1),atoi($3));
+ free($1); free($3);
+ }
+ ;
+%%
+
=======================================
--- /dev/null
+++ /branches/nov14/ms/MSSel/MSArrayParse.cc Wed Mar 25 14:33:54 2015 UTC
@@ -0,0 +1,192 @@
+//# MSArrayParse.cc: Classes to hold results from array grammar parser
+//# Copyright (C) 1994,1995,1997,1998,1999,2000,2001,2003
+//# Associated Universities, Inc. Washington DC, USA.
+//#
+//# This library is free software; you can redistribute it and/or modify it
+//# under the terms of the GNU Library General Public License as published
by
+//# the Free Software Foundation; either version 2 of the License, or (at
your
+//# option) any later version.
+//#
+//# This library is distributed in the hope that it will be useful, but
WITHOUT
+//# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+//# FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
+//# License for more details.
+//#
+//# You should have received a copy of the GNU Library General Public
License
+//# along with this library; if not, write to the Free Software Foundation,
+//# Inc., 675 Massachusetts Ave, Cambridge, MA 02139, USA.
+//#
+//# Correspondence concerning AIPS++ should be addressed as follows:
+//# Internet email:
aips2-...@nrao.edu.
+//# Postal address: AIPS++ Project Office
+//# National Radio Astronomy Observatory
+//# 520 Edgemont Road
+//# Charlottesville, VA 22903-2475 USA
+//#
+//# $Id$
+
+#include <casacore/ms/MSSel/MSArrayParse.h>
+#include <casacore/ms/MSSel/MSSelectionError.h>
+#include <casacore/ms/MeasurementSets/MSMainColumns.h>
+
+namespace casacore { //# NAMESPACE CASACORE - BEGIN
+
+ MSArrayParse* MSArrayParse::thisMSAParser = 0x0; // Global pointer to
the parser object
+ // TableExprNode* MSArrayParse::node_p = 0x0;
+ // std::vector<Int> MSArrayParse::parsedIDList_p;
+ // Vector<Int> MSArrayParse::idList;
+
+ //# Constructor
+ MSArrayParse::MSArrayParse ()
+ : MSParse(), colName(MS::columnName(MS::ARRAY_ID)), maxArrays_p(1000)
+ {
+ }
+
+ //# Constructor with given ms name.
+ MSArrayParse::MSArrayParse (const MeasurementSet* ms)
+ : MSParse(ms, "Array"), colName(MS::columnName(MS::ARRAY_ID)),
maxArrays_p(1000)
+ {
+ idList.resize(0);
+ parsedIDList_p.resize(0);
+ }
+
+ std::vector<Int>& MSArrayParse::accumulateIDs(const Int id0, const Int
id1)
+ {
+ Vector<Int> theIDs;
+ if (id1 < 0)
+ {
+ parsedIDList_p.push_back(id0);theIDs.resize(1);theIDs[0]=id0;
+ // Also accumulate IDs in the global ID list which contains IDs
+ // generated from all expressions (INT, INT DASH INT, and bounds
+ // expressions (>ID, <ID, etc.)).
+ }
+ else
+ {
+ // Enumerated list of IDs can be treated as a [ID0, ID1]
+ // (range inclusive of the bounds).
+ // cerr << "Selecting enumerated range: " << id0 << " " << id1 << endl;
+ selectRangeGEAndLE(id0,id1);
+ }
+ return parsedIDList_p;
+ }
+
+ void MSArrayParse::appendToIDList(const Vector<Int>& v)
+ {
+ Int currentSize = idList.nelements();
+ Int n = v.nelements() + currentSize;
+ Int j=0;
+
+ idList.resize(n, True);
+ for(Int i=currentSize;i<n;i++) idList[i] = v[j++];
+ }
+
+ const TableExprNode *MSArrayParse::selectRangeGTAndLT(const Int&
n0,const Int& n1)
+ {
+ TableExprNode condition = TableExprNode( (ms()->col(colName) > n0) &&
+ (ms()->col(colName) < n1));
+ if ((n0 < 0) || (n1 < 0) || (n1 <= n0))
+ {
+ ostringstream os;
+ os << "Array Expression: Malformed range bounds "
+ << n0 << " (lower bound) and "
+ << n1 << " (upper bound)";
+ throw(MSSelectionArrayParseError(os.str()));
+ }
+ Vector<Int> tmp(n1-n0-1);
+ Int j=n0+1;
+ for(uInt i=0;i<tmp.nelements();i++) tmp[i]=j++;
+ appendToIDList(tmp);
+ addCondition(node_p, condition);
+
+ return &node_p;
+ }
+
+ const TableExprNode *MSArrayParse::selectRangeGEAndLE(const Int&
n0,const Int& n1)
+ {
+ TableExprNode condition = TableExprNode( (ms()->col(colName) >= n0) &&
+ (ms()->col(colName) <= n1));
+ if ((n0 < 0) || (n1 < 0) || (n1 <= n0))
+ {
+ ostringstream os;
+ os << "Array Expression: Malformed range bounds "
+ << n0 << " (lower bound) and "
+ << n1 << " (upper bound)";
+ throw(MSSelectionArrayParseError(os.str()));
+ }
+ Vector<Int> tmp(n1-n0+1);
+ Int j=n0;
+ for(uInt i=0;i<tmp.nelements();i++) tmp[i]=j++;
+ appendToIDList(tmp);
+ addCondition(node_p, condition);
+
+ return &node_p;
+ }
+
+ const TableExprNode *MSArrayParse::selectArrayIds(const Vector<Int>&
arrayids)
+ {
+ if (arrayids.size() > 0)
+ {
+ TableExprNode condition = TableExprNode(ms()->col(colName).in(arrayids));
+
+ appendToIDList(arrayids);
+ addCondition(node_p, condition);
+ }
+ return &node_p;
+ }
+
+ const TableExprNode *MSArrayParse::selectArrayIdsGT(const Vector<Int>&
arrayids)
+ {
+ TableExprNode condition = TableExprNode(ms()->col(colName) >
arrayids[0]);
+
+ Int n=maxArrays_p-arrayids[0]+1,j;
+ Vector<Int> tmp(n);
+ j=arrayids[0]+1;
+ for(Int i=0;i<n;i++) tmp[i]=j++;
+ appendToIDList(tmp);
+ addCondition(node_p, condition);
+
+ return &node_p;
+ }
+
+ const TableExprNode *MSArrayParse::selectArrayIdsLT(const Vector<Int>&
arrayids)
+ {
+ TableExprNode condition = TableExprNode(ms()->col(colName) <
arrayids[0]);
+ Vector<Int> tmp(arrayids[0]);
+ for(Int i=0;i<arrayids[0];i++) tmp[i] = i;
+ appendToIDList(tmp);
+ addCondition(node_p, condition);
+
+ return &node_p;
+ }
+
+ const TableExprNode *MSArrayParse::selectArrayIdsGTEQ(const Vector<Int>&
arrayids)
+ {
+ TableExprNode condition = TableExprNode(ms()->col(colName) >=
arrayids[0]);
+
+ Int n=maxArrays_p-arrayids[0]+1,j;
+ Vector<Int> tmp(n);
+ j=arrayids[0];
+ for(Int i=0;i<n;i++) tmp[i]=j++;
+ appendToIDList(tmp);
+ addCondition(node_p, condition);
+
+ return &node_p;
+ }
+
+ const TableExprNode *MSArrayParse::selectArrayIdsLTEQ(const Vector<Int>&
arrayids)
+ {
+ TableExprNode condition = TableExprNode(ms()->col(colName) <=
arrayids[0]);
+ Vector<Int> tmp(arrayids[0]+1);
+ for(Int i=0;i<=arrayids[0];i++) tmp[i] = i;
+ appendToIDList(tmp);
+ addCondition(node_p, condition);
+
+ return &node_p;
+ }
+
+ const TableExprNode MSArrayParse::node()
+ {
+ return node_p;
+ }
+
+} //# NAMESPACE CASACORE - END
=======================================
--- /dev/null
+++ /branches/nov14/ms/MSSel/MSArrayParse.h Wed Mar 25 14:33:54 2015 UTC
@@ -0,0 +1,131 @@
+//# MSArrayParse.h: Classes to hold results from array grammar parser
+//# Copyright (C) 1994,1995,1997,1998,1999,2000,2001,2003
+//# Associated Universities, Inc. Washington DC, USA.
+//#
+//# This library is free software; you can redistribute it and/or modify it
+//# under the terms of the GNU Library General Public License as published
by
+//# the Free Software Foundation; either version 2 of the License, or (at
your
+//# option) any later version.
+//#
+//# This library is distributed in the hope that it will be useful, but
WITHOUT
+//# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+//# FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
+//# License for more details.
+//#
+//# You should have received a copy of the GNU Library General Public
License
+//# along with this library; if not, write to the Free Software Foundation,
+//# Inc., 675 Massachusetts Ave, Cambridge, MA 02139, USA.
+//#
+//# Correspondence concerning AIPS++ should be addressed as follows:
+//# Internet email:
aips2-...@nrao.edu.
+//# Postal address: AIPS++ Project Office
+//# National Radio Astronomy Observatory
+//# 520 Edgemont Road
+//# Charlottesville, VA 22903-2475 USA
+//#
+//# $Id$
+
+#ifndef MS_MSARRAYPARSE_H
+#define MS_MSARRAYPARSE_H
+
+//# Includes
+#include <casacore/casa/aips.h>
+#include <casacore/ms/MSSel/MSParse.h>
+#include <casacore/measures/Measures/MEpoch.h>
+
+namespace casacore { //# NAMESPACE CASACORE - BEGIN
+
+//# Forward Declarations
+
+// <summary>
+// Class to hold values from array grammar parser
+// </summary>
+
+// <use visibility=local>
+
+// <reviewed reviewer="" date="" tests="">
+// </reviewed>
+
+// <prerequisite>
+//# Classes you should understand before using this one.
+// </prerequisite>
+
+// <etymology>
+// MSArrayParse is the class used to parse a array command.
+// </etymology>
+
+// <synopsis>
+// MSArrayParse is used by the parser of array sub-expression statements.
+// The parser is written in Bison and Flex in files MSArrayGram.y and .l.
+// The statements in there use the routines in this file to act
+// upon a reduced rule.
+// Since multiple tables can be given (with a shorthand), the table
+// names are stored in a list. The variable names can be qualified
+// by the table name and will be looked up in the appropriate table.
+//
+// The class MSArrayParse only contains information about a table
+// used in the table command. Global variables (like a list and a vector)
+// are used in MSArrayParse.cc to hold further information.
+//
+// Global functions are used to operate on the information.
+// The main function is the global function msArrayCommand.
+// It executes the given STaQL command and returns the resulting ms.
+// This is, in fact, the only function to be used by a user.
+// </synopsis>
+
+// <motivation>
+// It is necessary to be able to give a ms command in ASCII.
+// This can be used in a CLI or in the table browser to get a subset
+// of a table or to sort a table.
+// </motivation>
+
+//# <todo asof="$DATE:$">
+//# A List of bugs, limitations, extensions or planned refinements.
+//# </todo>
+
+
+class MSArrayParse : public MSParse
+{
+
+public:
+ // Default constructor
+ MSArrayParse ();
+
+ // Associate the ms and the shorthand.
+ MSArrayParse (const MeasurementSet* ms);
+
+ // ~MSArrayParse() {if (node_p) delete node_p;node_p=0x0;}
+
+ const TableExprNode *selectRangeGTAndLT(const Int& n0, const Int& n1);
+ const TableExprNode *selectRangeGEAndLE(const Int& n0, const Int& n1);
+ const TableExprNode *selectArrayIds(const Vector<Int>& arrayids);
+ inline const TableExprNode *selectArrayIds() {return
selectArrayIds(parsedIDList_p);}
+ const TableExprNode *selectArrayIdsGT(const Vector<Int>& arrayids);
+ const TableExprNode *selectArrayIdsLT(const Vector<Int>& arrayids);
+ const TableExprNode *selectArrayIdsGTEQ(const Vector<Int>& arrayids);
+ const TableExprNode *selectArrayIdsLTEQ(const Vector<Int>& arrayids);
+ std::vector<Int>& accumulateIDs(const Int id0, const Int id1=-1);
+
+ // Get table expression node object.
+ const TableExprNode node();
+
+ Vector<Int> selectedIDs() {return idList;}
+ void reset(){idList.resize(0);parsedIDList_p.resize(0);}
+ void cleanup() {}
+
+ void setMaxArray(const Int& n) {maxArrays_p=n;}
+
+ static MSArrayParse* thisMSAParser;
+
+private:
+ TableExprNode node_p;
+ Vector<Int> idList;
+ std::vector<Int> parsedIDList_p;
+ const String colName;
+ void appendToIDList(const Vector<Int>& v);
+ Int maxArrays_p;
+};
+
+} //# NAMESPACE CASACORE - END
+
+#endif
=======================================
--- /dev/null
+++ /branches/nov14/ms/MSSel/MSCorrGram.cc Wed Mar 25 14:33:54 2015 UTC
@@ -0,0 +1,144 @@
+//# MSCorrGram.cc: Grammar for corr expressions
+//# Copyright (C) 1998,1999,2001,2003
+//# Associated Universities, Inc. Washington DC, USA.
+//#
+//# This library is free software; you can redistribute it and/or modify it
+//# under the terms of the GNU Library General Public License as published
by
+//# the Free Software Foundation; either version 2 of the License, or (at
your
+//# option) any later version.
+//#
+//# This library is distributed in the hope that it will be useful, but
WITHOUT
+//# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+//# FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
+//# License for more details.
+//#
+//# You should have received a copy of the GNU Library General Public
License
+//# along with this library; if not, write to the Free Software Foundation,
+//# Inc., 675 Massachusetts Ave, Cambridge, MA 02139, USA.
+//#
+//# Correspondence concerning AIPS++ should be addressed as follows:
+//# Internet email:
aips2-...@nrao.edu.
+//# Postal address: AIPS++ Project Office
+//# National Radio Astronomy Observatory
+//# 520 Edgemont Road
+//# Charlottesville, VA 22903-2475 USA
+//#
+//# $Id$
+
+// MSCorrGram; grammar for corr command lines
+
+// This file includes the output files of bison and flex for
+// parsing command lines operating on lattices.
+
+#include <casacore/tables/TaQL/ExprNode.h>
+#include <casacore/tables/TaQL/ExprNodeSet.h>
+#include <casacore/ms/MeasurementSets/MeasurementSet.h>
+#include <casacore/ms/MSSel/MSCorrGram.h>
+#include <casacore/ms/MSSel/MSCorrParse.h> // routines used by bison
actions
+#include <casacore/tables/TaQL/TableParse.h> // routines used by
bison actions
+#include <casacore/tables/Tables/TableError.h>
+
+//# stdlib.h is needed for bison 1.28 and needs to be included here
+//# (before the flex/bison files).
+#include <casacore/casa/stdlib.h>
+//# Define register as empty string to avoid warnings in C++11 compilers
+//# because keyword register is not supported anymore.
+#define register
+#include "MSCorrGram.ycc" // bison output
+#include "MSCorrGram.lcc" // flex output
+
+// Define the yywrap function for flex.
+int MSCorrGramwrap()
+{
+ return 1;
+}
+
+namespace casacore { //# NAMESPACE CASACORE - BEGIN
+
+//# Declare a file global pointer to a char* for the input string.
+static const char* strpMSCorrGram = 0;
+static Int posMSCorrGram = 0;
+
+
+//# Parse the command.
+//# Do a yyrestart(yyin) first to make the flex scanner reentrant.
+int msCorrGramParseCommand (const MeasurementSet* ms, const String&
command)
+{
+ MSCorrGramrestart (MSCorrGramin);
+ yy_start = 1;
+ strpMSCorrGram = command.chars(); // get pointer to command string
+ posMSCorrGram = 0; // initialize string position
+ MSCorrParse parser(ms); // setup measurement set
+ return MSCorrGramparse(); // parse command string
+}
+
+//# Give the table expression node
+const TableExprNode* msCorrGramParseNode()
+{
+ return MSCorrParse::node();
+}
+void msCorrGramParseDeleteNode()
+{
+ return MSCorrParse::cleanup();
+}
+
+//# Give the string position.
+Int& msCorrGramPosition()
+{
+ return posMSCorrGram;
+}
+
+//# Get the next input characters for flex.
+int msCorrGramInput (char* buf, int max_size)
+{
+ int nr=0;
+ while (*strpMSCorrGram != 0) {
+ if (nr >= max_size) {
+ break; // get max. max_size char.
+ }
+ buf[nr++] = *strpMSCorrGram++;
+ }
+ return nr;
+}
+
+void MSCorrGramerror (const char*)
+{
+ throw (AipsError ("Corr Expression: Parse error at or near '" +
+ String(MSCorrGramtext) + "'"));
+}
+
+String msCorrGramRemoveEscapes (const String& in)
+{
+ String out;
+ int leng = in.length();
+ for (int i=0; i<leng; i++) {
+ if (in[i] == '\\') {
+ i++;
+ }
+ out += in[i];
+ }
+ return out;
+}
+
+String msCorrGramRemoveQuotes (const String& in)
+{
+ //# A string is formed as "..."'...''...' etc.
+ //# All ... parts will be extracted and concatenated into an output
string.
+ String out;
+ String str = in;
+ int leng = str.length();
+ int pos = 0;
+ while (pos < leng) {
+ //# Find next occurrence of leading ' or ""
+ int inx = str.index (str[pos], pos+1);
+ if (inx < 0) {
+ throw (AipsError ("MSCorrParse - Ill-formed quoted string: " +
+ str));
+ }
+ out +=
str.at (pos+1, inx-pos-1); // add substring
+ pos = inx+1;
+ }
+ return out;
+}
+
+} //# NAMESPACE CASACORE - END
=======================================
--- /dev/null
+++ /branches/nov14/ms/MSSel/MSCorrGram.h Wed Mar 25 14:33:54 2015 UTC
@@ -0,0 +1,101 @@
+//# MSCorrGram.h: Grammar for ms corr sub-expressions
+//# Copyright (C) 1998
+//# Associated Universities, Inc. Washington DC, USA.
+//#
+//# This library is free software; you can redistribute it and/or modify it
+//# under the terms of the GNU Library General Public License as published
by
+//# the Free Software Foundation; either version 2 of the License, or (at
your
+//# option) any later version.
+//#
+//# This library is distributed in the hope that it will be useful, but
WITHOUT
+//# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+//# FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
+//# License for more details.
+//#
+//# You should have received a copy of the GNU Library General Public
License
+//# along with this library; if not, write to the Free Software Foundation,
+//# Inc., 675 Massachusetts Ave, Cambridge, MA 02139, USA.
+//#
+//# Correspondence concerning AIPS++ should be addressed as follows:
+//# Internet email:
aips2-...@nrao.edu.
+//# Postal address: AIPS++ Project Office
+//# National Radio Astronomy Observatory
+//# 520 Edgemont Road
+//# Charlottesville, VA 22903-2475 USA
+//#
+//# $Id$
+
+#ifndef MS_MSCORRGRAM_H
+#define MS_MSCORRGRAM_H
+
+
+//# Includes
+#include <casacore/casa/aips.h>
+#include <casacore/casa/BasicSL/String.h>
+
+namespace casacore { //# NAMESPACE CASACORE - BEGIN
+
+//# Forward Declarations
+class MeasurementSet;
+class TableExprNode;
+
+// <summary>
+// Global functions for flex/bison scanner/parser for MSCorrGram
+// </summary>
+
+// <use visibility=local>
+
+// <reviewed reviewer="" date="" tests="">
+// </reviewed>
+
+// <prerequisite>
+//# Classes you should understand before using this one.
+// <li> MSCorrGram.l and .y (flex and bison grammar)
+// </prerequisite>
+
+// <synopsis>
+// Global functions are needed to define the input of the flex scanner
+// and to start the bison parser.
+// The input is taken from a string.
+// </synopsis>
+
+// <motivation>
+// It is necessary to be able to give an image expression in ASCII.
+// This can be used in glish.
+// </motivation>
+// <todo asof="$DATE:$">
+//# A List of bugs, limitations, extensions or planned refinements.
+// </todo>
+
+
+// <group name=MSCorrGramFunctions>
+
+// Declare the bison parser (is implemented by bison command).
+int msCorrGramParseCommand (const MeasurementSet *ms, const String&
command);
+
+// The yyerror function for the parser.
+// It throws an exception with the current token.
+void MSCorrGramerror (const char*);
+
+// Give the table expression node.
+const TableExprNode *msCorrGramParseNode();
+void msCorrGramParseDeleteNode();
+
+// Give the current position in the string.
+// This can be used when parse errors occur.
+Int& msCorrGramPosition();
+
+// Declare the input routine for flex/bison.
+int msCorrGramInput (char* buf, int max_size);
+
+// A function to remove escaped characters.
+String msCorrGramRemoveEscapes (const String& in);
+
+// A function to remove quotes from a quoted string.
+String msCorrGramRemoveQuotes (const String& in);
+
+// </group>
+
+} //# NAMESPACE CASACORE - END
+
+#endif
=======================================
--- /dev/null
+++ /branches/nov14/ms/MSSel/MSCorrGram.ll Wed Mar 25 14:33:54 2015 UTC
@@ -0,0 +1,136 @@
+/*
+ MSCorrGram.l: Lexical analyzer for ms selection commands
+ Copyright (C) 1994,1995,1996,1997,1998,2001,2003
+ Associated Universities, Inc. Washington DC, USA.
+
+ This library is free software; you can redistribute it and/or modify it
+ under the terms of the GNU Library General Public License as published
by
+ the Free Software Foundation; either version 2 of the License, or (at
your
+ option) any later version.
+
+ This library is distributed in the hope that it will be useful, but
WITHOUT
+ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
+ License for more details.
+
+ You should have received a copy of the GNU Library General Public
License
+ along with this library; if not, write to the Free Software Foundation,
+ Inc., 675 Massachusetts Ave, Cambridge, MA 02139, USA.
+
+ Correspondence concerning AIPS++ should be addressed as follows:
+ Internet email:
aips2-...@nrao.edu.
+ Postal address: AIPS++ Project Office
+ National Radio Astronomy Observatory
+ 520 Edgemont Road
+ Charlottesville, VA 22903-2475 USA
+
+ $Id$
+*/
+
+/* yy_unput is not used, so let flex not generate it, otherwise picky
+ compilers will issue warnings. */
+%option nounput
+
+%{
+#undef YY_INPUT
+#define YY_INPUT(buf,result,max_size) result=msCorrGramInput(buf,max_size)
+
+#undef YY_DECL
+#define YY_DECL int MSCorrGramlex (YYSTYPE* lvalp)
+%}
+
+WHITE [ \t\n]*
+DIGIT [0-9]
+INT {DIGIT}+
+EXP [DdEe][+-]?{INT}
+FNUMBER {INT}"."{DIGIT}*
+TRUE T
+FALSE F
+
+QSTRING \"[^\"\n]*\"
+ASTRING \'[^\'\n]*\'
+UQSTRING \"[^\"\n]*\n
+UASTRING \'[^\'\n]*\n
+STRING ({QSTRING}|{ASTRING})+
+USTRING ({UQSTRING}|{UASTRING})+
+
+CORRTYPE [IQUV]{1}|[RL]{2}|[XY]{2}
+
+REGEX1 m"/"[^/]+"/"
+REGEX2 m%[^%]+%
+REGEX3 m#[^#]+#
+REGEX {REGEX1}|{REGEX2}|{REGEX3}
+
+ /* rules */
+
+%%
+
+"[" { msCorrGramPosition() += yyleng;
+ return LBRACKET;
+ }
+"(" { msCorrGramPosition() += yyleng;
+ return LPAREN;
+ }
+"]" { msCorrGramPosition() += yyleng;
+ return RBRACKET;
+ }
+")" { msCorrGramPosition() += yyleng;
+ return RPAREN;
+ }
+
+":" { msCorrGramPosition() += yyleng;
+ return COLON; }
+"==" { msCorrGramPosition() += yyleng;
+ return EQ; }
+"=" { msCorrGramPosition() += yyleng;
+ return EQASS; }
+"!=" { msCorrGramPosition() += yyleng;
+ return NE; }
+"<>" { msCorrGramPosition() += yyleng;
+ return NE; }
+">=" { msCorrGramPosition() += yyleng;
+ return GE; }
+">" { msCorrGramPosition() += yyleng;
+ return GT; }
+"<=" { msCorrGramPosition() += yyleng;
+ return LE; }
+"<" { msCorrGramPosition() += yyleng;
+ return LT; }
+"&&" { msCorrGramPosition() += yyleng;
+ return AND; }
+"||" { msCorrGramPosition() += yyleng;
+ return OR; }
+"!" { msCorrGramPosition() += yyleng;
+ return NOT; }
+"^" { msCorrGramPosition() += yyleng;
+ return POWER; }
+"*" { msCorrGramPosition() += yyleng;
+ return TIMES; }
+"/" { msCorrGramPosition() += yyleng;
+ return DIVIDE; }
+"%" { msCorrGramPosition() += yyleng;
+ return PERCENT; }
+"+" { msCorrGramPosition() += yyleng;
+ return PLUS; }
+"~" { msCorrGramPosition() += yyleng;
+ return DASH; }
+"{" { msCorrGramPosition() += yyleng;
+ return LBRACE; }
+"}" { msCorrGramPosition() += yyleng;
+ return RBRACE; }
+"'" { msCorrGramPosition() += yyleng;
+ return SQUOTE; }
+"," { msCorrGramPosition() += yyleng;
+ return COMMA;
+ }
+
+ /* Literals */
+
+{CORRTYPE} {
+ msCorrGramPosition() += yyleng;
+ lvalp->str = MSCorrGramtext;
+ return CORRTYPE;
+ }
+
+%%
+
=======================================
***Additional files exist in this changeset.***