################################################################################
#
# task_fixlowband.py
#
#
# Copyright (C) 2009
# Associated Universities, Inc. Washington DC, USA.
#
# This script 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 adressed as follows:
# Internet email: aips2-request@nrao.edu.
# Postal address: AIPS++ Project Office
# National Radio Astronomy Observatory
# 520 Edgemont Road
# Charlottesville, VA 22903-2475 USA
#
#
# Huib Intema (NRAO)
#
#
#
#
#
#
#
# fixlowband stands for fix JVLA low-band.
#
#
#
# task_fixlowband.py is a python script providing a task for automatically
# identifying and fixing two persistent data formatting problems in VLA low-band
# data. First, the polarizations have been systematically labelled as being
# circular (R,L) rather than linear (X,Y). Second, in some cases spectral windows
# have been labelled as being both circular and linear, of which linear is the
# only correct one.
#This task removes any duplicate entries from the DATA_DESCRIPTION table, and
#relabels VLA low-band data in the POLARIZATION table to have linear polarizations.
#It should be run directly after importing the data.
#two persistent data formatting problems in VLA
#
#
#
#
#
#
#
#
# To provide an easy fix to two common low-band data problems.
#
#
#
#
#
################################################################################
from taskinit import *
import os, shutil, numpy, math, pdb
################################################################################
def fixlowband( vis = '' ):
# initialize task
casalog.origin('fixlowband')
ms_tool, md_tool, tb_tool = gentools( [ 'ms', 'msmd', 'tb' ] )
# define stokes ids
stokes_dict = { 'I' : 1, 'Q' : 2, 'U' : 3, 'V' : 4,
'RR' : 5, 'RL' : 6, 'LR' : 7, 'LL' : 8,
'XX' : 9, 'XY' : 10, 'YX' : 11, 'YY' : 12 }
stokes_full_RL_list = [ stokes_dict[ x ] for x in [ 'RR', 'RL', 'LR', 'LL' ] ]
stokes_full_RL_list.sort()
stokes_half_RL_list = [ stokes_dict[ x ] for x in [ 'RR', 'LL' ] ]
stokes_half_RL_list.sort()
stokes_full_XY_list = [ stokes_dict[ x ] for x in [ 'XX', 'XY', 'YX', 'YY' ] ]
stokes_full_XY_list.sort()
stokes_half_XY_list = [ stokes_dict[ x ] for x in [ 'XX', 'YY' ] ]
stokes_half_XY_list.sort()
# handle input MS names
if ( ( len( vis ) == 0 ) or ( not os.path.exists( vis ) ) ):
casalog.post( 'Input MS does not exist.', 'SEVERE' )
return False
# find low-band spectral windows
tb_tool.open( vis + '/OBSERVATION', nomodify = True )
telescopes = tb_tool.getcol( 'TELESCOPE_NAME' )
obs_ids = tb_tool.rownumbers()[ telescopes == 'EVLA' ]
tb_tool.close()
if ( len( obs_ids ) == 0 ):
casalog.post( 'Input MS contains no EVLA observations.', 'SEVERE' )
return False
tb_tool.open( vis, nomodify = True )
data = tb_tool.getcol( 'OBSERVATION_ID' )
mask = numpy.in1d( data, obs_ids )
data = tb_tool.getcol( 'DATA_DESC_ID' )
evla_dd_ids = numpy.unique( data[ mask] )
tb_tool.close()
tb_tool.open( vis + '/DATA_DESCRIPTION', nomodify = True )
evla_spw_ids = numpy.unique( tb_tool.getcol( 'SPECTRAL_WINDOW_ID' )[ evla_dd_ids ] )
tb_tool.close()
tb_tool.open( vis + '/SPECTRAL_WINDOW', nomodify = True )
evla_spw_freqs = tb_tool.getcol( 'REF_FREQUENCY' )[ evla_spw_ids ]
evla_spw_freq_unit = tb_tool.getcolkeyword( 'REF_FREQUENCY', 'QuantumUnits' )[ 0 ]
tb_tool.close()
if ( evla_spw_freq_unit == 'Hz' ):
pass
elif ( evla_spw_freq_unit == 'kHz' ):
evla_spw_freqs = evla_spw_freqs * 1.e3
elif ( evla_spw_freq_unit == 'MHz' ):
evla_spw_freqs = evla_spw_freqs * 1.e6
elif ( evla_spw_freq_unit == 'GHz' ):
evla_spw_freqs = evla_spw_freqs * 1.e9
else:
casalog.post( 'Unknown frequency units %s in SPECTRAL_WINDOW table.' %
( evla_spw_freq_unit ), 'SEVERE' )
return False
lb_spw_ids = evla_spw_ids[ evla_spw_freqs < 0.6e9 ]
if ( len( lb_spw_ids ) == 0 ):
casalog.post( 'Input MS contains no EVLA low-band observations', 'SEVERE' )
return False
# remove inactive / duplicate data descriptors
tb_tool.open( vis, nomodify = True )
dd_ids = tb_tool.getcol( 'DATA_DESC_ID' )
active_dd_ids = numpy.unique( dd_ids )
tb_tool.open( vis + '/DATA_DESCRIPTION', nomodify = True )
inactive_dd_ids = numpy.delete( tb_tool.rownumbers(), active_dd_ids )
tb_tool.close()
if ( len( inactive_dd_ids ) > 0 ):
casalog.post( 'Removing inactive entries from DATA_DESCRIPTION table', 'WARN' )
for i in range( len( active_dd_ids ) ):
# if ( i != active_dd_ids[ i ] ):
# sel = ( dd_ids == active_dd_ids[ i ] )
# dd_ids[ sel ] = i
dd_ids[ dd_ids == active_dd_ids[ i ] ] = i
# modify MS
tb_tool.open( vis, nomodify = False )
tb_tool.lock()
tb_tool.putcol( 'DATA_DESC_ID', dd_ids )
tb_tool.unlock()
tb_tool.close()
# modify DD table
tb_tool.open( vis + '/DATA_DESCRIPTION', nomodify = False )
tb_tool.lock()
tb_tool.removerows( inactive_dd_ids )
tb_tool.unlock()
tb_tool.close()
# else:
# casalog.post( 'DATA_DESCRIPTION table contains no inactive entries', 'NORMAL' )
# fix low-band polarization labeling
tb_tool.open( vis + '/DATA_DESCRIPTION', nomodify = True )
mask = numpy.in1d( tb_tool.getcol( 'SPECTRAL_WINDOW_ID' ), lb_spw_ids )
lb_pol_ids = numpy.unique( tb_tool.getcol( 'POLARIZATION_ID' )[ mask ] )
tb_tool.close()
tb_tool.open( vis + '/POLARIZATION', nomodify = False )
corr_types = tb_tool.getcol( 'CORR_TYPE' )
something_changed = False
for i, corr_type in enumerate( corr_types.transpose() ):
if ( not i in lb_pol_ids ):
continue
corr_type = corr_type.tolist()
corr_type.sort()
if ( ( corr_type == stokes_full_RL_list ) or ( corr_type == stokes_half_RL_list ) ):
corr_types[ : , i ] = corr_types[ : , i ] + 4
something_changed = True
continue
if ( ( corr_type == stokes_full_XY_list ) or ( corr_type == stokes_half_XY_list ) ):
continue
casalog.post( 'P-band stokes labels are not recognized in POLARIZATION table', 'WARN' )
if something_changed:
tb_tool.putcol( 'CORR_TYPE', corr_types )
casalog.post( 'Changed P-band stokes labels from circular (RR,RL,LR,LL) to ' +
'linear (XX,XY,YX,YY) in POLARIZATION table', 'WARN' )
tb_tool.close()
tb_tool.open( vis + '/FEED', nomodify = False )
mask = numpy.in1d( tb_tool.getcol( 'SPECTRAL_WINDOW_ID' ), lb_spw_ids )
lb_feed_rows = tb_tool.rownumbers()[ mask ]
pol_types = tb_tool.getcol( 'POLARIZATION_TYPE' )
something_changed = False
for i, pol_type in enumerate( pol_types.transpose() ):
if ( not i in lb_feed_rows ):
continue
pol_type = pol_type.tolist()
if ( pol_type == [ 'R', 'L' ] ):
pol_types[ 0 , i ] = 'X'
pol_types[ 1 , i ] = 'Y'
something_changed = True
continue
if ( pol_type == [ 'L', 'R' ] ):
pol_types[ 0 , i ] = 'Y'
pol_types[ 1 , i ] = 'X'
something_changed = True
continue
if ( ( pol_type == [ 'X', 'Y' ] ) or ( pol_type == [ 'Y', 'X' ] ) ):
continue
casalog.post( 'P-band stokes labels are not recognized in FEED table', 'WARN' )
if something_changed:
tb_tool.putcol( 'POLARIZATION_TYPE', pol_types )
casalog.post( 'Changed P-band stokes labels from circular (R,L) to ' +
'linear (X,Y) in FEED table', 'WARN' )
tb_tool.close()
return True
################################################################################