import datetime
import math
import numpy
import pipeline.infrastructure.logging as logging
from pipeline.infrastructure import casa_tools
# the logger for this module
LOG = logging.get_logger(__name__)
[docs]def buildscans(msfile, scd):
"""
buildscans: compile scan information for msfile
Created S.T. Myers 2012-05-07 v1.0
Updated S.T. Myers 2012-05-14 v1.1 add corrtype
Updated S.T. Myers 2012-06-27 v1.2 add corrdesc lookup
Updated S.T. Myers 2012-11-13 v2.0 STM casa 4.0 new calls
Usage:
from lib_EVLApipeutils import buildscans
Input:
msfile - name of MS
Output: scandict (return value)
Examples:
CASA <2>: from lib_EVLApipeutils import buildscans
CASA <3>: msfile = 'TRSR0045_sb600507.55900.ms'
CASA <4>: myscans = buildscans(msfile)
Getting scansummary from MS
Found 16 DataDescription IDs
Found 4 StateIds
Found 3422 times in DD=0
Found 3422 times in DD=1
Found 3422 times in DD=2
Found 3422 times in DD=3
Found 3422 times in DD=4
Found 3422 times in DD=5
Found 3422 times in DD=6
Found 3422 times in DD=7
Found 3422 times in DD=8
Found 3422 times in DD=9
Found 3422 times in DD=10
Found 3422 times in DD=11
Found 3422 times in DD=12
Found 3422 times in DD=13
Found 3422 times in DD=14
Found 3422 times in DD=15
Found total 54752 times
Found 175 scans min=1 max=180
Size of scandict in memory is 248 bytes
CASA <5>: myscans['Scans'][1]['intents']
Out[5]: 'CALIBRATE_AMPLI#UNSPECIFIED,UNSPECIFIED#UNSPECIFIED'
CASA <6>: myscans['Scans'][1]['dd']
Out[6]: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]
CASA <7>: myscans['DataDescription'][0]
Out[7]:
{'corrdesc': ['RR', 'RL', 'LR'', 'LL'],
'corrtype': [5, 6, 7, 8],
'ipol': 0,
'nchan': 64,
'npol': 4,
'reffreq': 994000000.0,
'spw': 0,
'spwname': 'Subband:0'}
CASA <8>: myscans['Scans'][1]['times'][0]
Out[8]:
[4829843281.500001,
4829843282.5,
4829843283.5,
4829843284.5,
...
4829843336.5]
The last of these returns the integration midpoints for scan 1 DD 0.
Note that to get spw and pol info you use the DD indexes from ['dd']
in the 'Scans' part to index into the 'DataDescription' info.
You can also list the keys available in the Scans sub-dictionary:
CASA <9>: myscans['Scans'][1].keys()
Out[9]:
['scan_mid',
'intents',
'field',
'dd',
'npol',
'rra',
'spw',
'scan_int',
'scan_start',
'times',
'scan_end',
'rdec']
"""
# dictionary with lookup for correlation strings
# from http://casa.nrao.edu/docs/doxygen/html/classcasa_1_1Stokes.html
cordesclist = ['Undefined',
'I',
'Q',
'U',
'V',
'RR',
'RL',
'LR',
'LL',
'XX',
'XY',
'YX',
'YY',
'RX',
'RY',
'LX',
'LY',
'XR',
'XL',
'YR',
'YL',
'PP',
'PQ',
'QP',
'QQ',
'RCircular',
'LCircular',
'Linear',
'Ptotal',
'Plinear',
'PFtotal',
'PFlinear',
'Pangle']
#
# Usage: find desc for an index, e.g. cordesclist[corrtype]
# find index for a desc, e.g. cordesclist.index(corrdesc)
#
# ms = casa_tools.ms()
tb = casa_tools.table()
print('CACHE')
print(tb.showcache())
# Access the MS
####################################
# try:
# ms.open(msfile,nomodify=True)
# except:
# print "ERROR: failed to open ms tool on file "+msfile
# exit(1)
####################################
# print 'Getting scansummary from MS'
# get the scan summary using ms.getscansummary method
# mysc = ms.getscansummary()
# Already open - uncomment to run getscansummary
# scd = ms.getscansummary()
# #nscans = len( mysc['summary'].keys() )
# nscans = len( scd.keys() )
# print 'Found '+str(nscans)+' scans'
#
# Find number of data description IDs
with casa_tools.TableReader(msfile + '/DATA_DESCRIPTION') as table:
ddspwarr=table.getcol("SPECTRAL_WINDOW_ID")
ddpolarr=table.getcol("POLARIZATION_ID")
ddspwlist = ddspwarr.tolist()
ddpollist = ddpolarr.tolist()
ndd = len(ddspwlist)
# print 'Found '+str(ndd)+' DataDescription IDs'
#
# The SPECTRAL_WINDOW table
with casa_tools.TableReader(msfile + '/SPECTRAL_WINDOW') as table:
nchanarr=table.getcol("NUM_CHAN")
spwnamearr=table.getcol("NAME")
reffreqarr=table.getcol("REF_FREQUENCY")
nspw = len(nchanarr)
spwlookup = {}
for isp in range(nspw):
spwlookup[isp] = {}
spwlookup[isp]['nchan'] = nchanarr[isp]
spwlookup[isp]['name'] = str( spwnamearr[isp] )
spwlookup[isp]['reffreq'] = reffreqarr[isp]
# print 'Extracted information for '+str(nspw)+' SpectralWindows'
#
# Now the polarizations (number of correlations in each pol id
with casa_tools.TableReader(msfile + '/POLARIZATION') as table:
ncorarr=table.getcol("NUM_CORR")
# corr_type is in general variable shape, have to read row-by-row
# or use getvarcol to return into dictionary, we will iterate manually
npols = len(ncorarr)
polindex = {}
poldescr = {}
for ip in range(npols):
cort = table.getcol("CORR_TYPE", startrow=ip, nrow=1)
(nct, nr) = cort.shape
cortypes = []
cordescs = []
for ict in range(nct):
cct = cort[ict][0]
cde = cordesclist[cct]
cortypes.append(cct)
cordescs.append(cde)
polindex[ip] = cortypes
poldescr[ip] = cordescs
# cortype is an array of npol, e.g. 5,6,7,8 is for RR,RL,LR,LL respectively
# for alma this would be 9,10,11,12 for XX,XY,YX,YY respectively
# cordesc are the strings associated with the types (enum for casa)
# print 'Extracted information for '+str(npols)+' Polarization Setups'
#
# Build the DD index
#
ddindex = {}
ncorlist=ncorarr.tolist()
for idd in range(ndd):
ddindex[idd] = {}
isp = ddspwlist[idd]
ddindex[idd]['spw'] = isp
ddindex[idd]['spwname'] = spwlookup[isp]['name']
ddindex[idd]['nchan'] = spwlookup[isp]['nchan']
ddindex[idd]['reffreq'] = spwlookup[isp]['reffreq']
ipol = ddpollist[idd]
ddindex[idd]['ipol'] = ipol
ddindex[idd]['npol'] = ncorlist[ipol]
ddindex[idd]['corrtype'] = polindex[ipol]
ddindex[idd]['corrdesc'] = poldescr[ipol]
#
# Now get raw scan intents from STATE table
with casa_tools.TableReader(msfile + '/STATE') as table:
intentarr = table.getcol("OBS_MODE")
subscanarr = table.getcol("SUB_SCAN")
intentlist = intentarr.tolist()
subscanlist = subscanarr.tolist()
nstates = intentlist.__len__()
# print 'Found '+str(nstates)+' StateIds'
#
# Now get FIELD table directions
with casa_tools.TableReader(msfile + '/FIELD') as table:
fnamearr = table.getcol("NAME")
fpdirarr = table.getcol("PHASE_DIR")
flist = fnamearr.tolist()
nfields = len(flist)
(nd1, nd2, npf) = fpdirarr.shape
fielddict = {}
for ifld in range(nfields):
fielddict[ifld] = {}
fielddict[ifld]['name'] = flist[ifld]
# these are numpy.float64
fielddict[ifld]['rra'] = fpdirarr[0, 0, ifld]
fielddict[ifld]['rdec'] = fpdirarr[1, 0, ifld]
#
# Now compile list of visibility times and info
#
# Extract times from the Main Table
# Build lookup for DDs by scan_number
timdict = {}
ddlookup = {}
ddscantimes = {}
ntottimes = 0
with casa_tools.MSReader(msfile) as ms:
for idd in range(ndd):
# Select this DD (after reset if needed)
if idd > 0:
ms.selectinit(reset=True)
ms.selectinit(idd)
# recf = ms.getdata(["flag"])
# (nx,nc,ni) = recf['flag'].shape
# get the times
rect = ms.getdata(["time", "field_id", "scan_number"], ifraxis=True)
nt = rect['time'].shape[0]
ntottimes += nt
print('Found {} times in DD={}'.format(nt, idd))
timdict[idd] = {}
timdict[idd]['time'] = rect['time']
timdict[idd]['field_id'] = rect['field_id']
timdict[idd]['scan_number'] = rect['scan_number']
for it in range(nt):
isc = rect['scan_number'][it]
tim = rect['time'][it]
if isc in ddlookup:
if ddlookup[isc].count(idd)<1:
ddlookup[isc].append(idd)
if idd in ddscantimes[isc]:
ddscantimes[isc][idd].append(tim)
else:
ddscantimes[isc][idd] = [tim]
else:
ddlookup[isc] = [idd]
ddscantimes[isc] = {}
ddscantimes[isc][idd] = [tim]
# print 'Found total '+str(ntottimes)+' times'
# ms.close()
# compile a list of scan times
#
# scd = mysc['summary']
scanlist = []
scanindex = {}
scl = list(scd.keys())
for sscan in scl:
isc = int(sscan)
scanlist.append(isc)
scanindex[isc]=sscan
scanlist.sort()
nscans = len(scanlist)
# print 'Found '+str(nscans)+' scans min='+str(min(scanlist))+' max='+str(max(scanlist))
scantimes = []
scandict = {}
# Put DataDescription lookup into dictionary
scandict['DataDescription'] = ddindex
# Put Scan information in dictionary
scandict['Scans'] = {}
for isc in scanlist:
sscan = scanindex[isc]
# sub-scans, differentiated by StateId
subs = list(scd[sscan].keys())
scan_start = -1.
scan_end = -1.
for ss in subs:
bt = scd[sscan][ss]['BeginTime']
et = scd[sscan][ss]['EndTime']
if scan_start > 0.:
if bt < scan_start:
scan_start = bt
else:
scan_start = bt
if scan_end > 0.:
if et > scan_end:
scan_end = et
else:
scan_end = et
scan_mid = 0.5*(scan_start + scan_end)
scan_int = scd[sscan]['0']['IntegrationTime']
scantimes.append(scan_mid)
scandict['Scans'][isc] = {}
scandict['Scans'][isc]['scan_start'] = scan_start
scandict['Scans'][isc]['scan_end'] = scan_end
scandict['Scans'][isc]['scan_mid'] = scan_mid
scandict['Scans'][isc]['scan_int'] = scan_int
ifld = scd[sscan]['0']['FieldId']
scandict['Scans'][isc]['field'] = ifld
scandict['Scans'][isc]['rra'] = fielddict[ifld]['rra']
scandict['Scans'][isc]['rdec'] = fielddict[ifld]['rdec']
spws = scd[sscan]['0']['SpwIds']
scandict['Scans'][isc]['spw'] = spws.tolist()
# state id of first sub-scan
stateid = scd[sscan]['0']['StateId']
# get intents from STATE table
intents = intentlist[stateid]
# this is a string with comma-separated intents
scandict['Scans'][isc]['intents'] = intents
# DDs for this scan
ddlist = ddlookup[isc]
scandict['Scans'][isc]['dd'] = ddlist
# number of polarizations for this list of dds
ddnpollist = []
for idd in ddlist:
npol = ddindex[idd]['npol']
ddnpollist.append(npol)
scandict['Scans'][isc]['npol'] = ddnpollist
# visibility times per dd in this scan
#
scandict['Scans'][isc]['times'] = {}
for idd in ddlist:
scandict['Scans'][isc]['times'][idd] = ddscantimes[isc][idd]
mysize = scandict.__sizeof__()
# print 'Size of scandict in memory is '+str(mysize)+' bytes'
# print('CACHE END')
# print(tb.showcache())
return scandict
[docs]class VLAScanHeuristics(object):
def __init__(self, vis):
self.vis = vis
[docs] def makescandict(self):
"""Run Steve's buildscans"""
with casa_tools.MSReader(self.vis) as ms:
self.scan_summary = ms.getscansummary()
self.ms_summary = ms.summary()
# self.scandict = buildscans(self.vis, self.scan_summary)
# self.startdate=float(self.ms_summary['BeginTime'])
# with casa_tools.TableReader(self.inputs.vis) as table:
# self.scanNums = sorted(numpy.unique(table.getcol('SCAN_NUMBER')))
# These will be needed later in the pipeline
self.gain_solint1 = {}
self.gain_solint2 = {}
self.shortsol1 = {}
self.shortsol2 = {}
self.longsolint = {}
self.short_solint = {}
self.new_gain_solint1 = {}
self.ignorerefant = []
self.fluxscale_sources = []
self.fluxscale_flux_densities = []
self.fluxscale_spws = []
self.flagspw1 = ''
self.flagspw1b = ''
self.flagspw2 = ''
"""
Prep string listing of correlations from dictionary created by method buildscans
For now, only use the parallel hands. Cross hands will be implemented later.
"""
# self.corrstring_list = self.scandict['DataDescription'][0]['corrdesc']
# self.removal_list = ['RL', 'LR', 'XY', 'YX']
# self.corrstring_list = list(set(self.corrstring_list).difference(set(self.removal_list)))
# self.corrstring = string.join(self.corrstring_list,',')
# Create dictionary of band names from spw ids
# self.spw2band = self.convertspw2band()
return True
[docs] def calibratorIntentsOld(self):
"""
# Identify scans and fields associated with different calibrator intents
# NB: the scan intent definitions changed in the OPT on Feb 21,
# 2012. So test on date:
"""
# tb = casa_tools.table()
# print 'CAL INTENT CACHE 1:'
# print tb.showcache()
with casa_tools.TableReader(self.vis + '/SPECTRAL_WINDOW') as table:
channels = table.getcol('NUM_CHAN')
numSpws = len(channels)
with casa_tools.MSReader(self.vis) as ms:
self.ms_summary = ms.summary()
startdate=float(self.ms_summary['BeginTime'])
with casa_tools.TableReader(self.vis + '/STATE') as table:
intents = table.getcol('OBS_MODE')
self.bandpass_state_IDs = []
self.delay_state_IDs = []
self.flux_state_IDs = []
self.polarization_state_IDs = []
self.phase_state_IDs = []
self.amp_state_IDs = []
self.calibrator_state_IDs = []
self.pointing_state_IDs = []
# print 'CAL INTENT CACHE 2:'
# print tb.showcache()
if startdate <= 55978.50:
for state_ID in range(0, len(intents)):
self.state_intents = intents[state_ID].rsplit(',')
for intent in range(0, len(self.state_intents)):
self.scan_intent = self.state_intents[intent].rsplit('#')[0]
self.subscan_intent = self.state_intents[intent].rsplit('#')[1]
if self.scan_intent == 'CALIBRATE_BANDPASS':
self.bandpass_state_IDs.append(state_ID)
self.calibrator_state_IDs.append(state_ID)
elif self.scan_intent == 'CALIBRATE_DELAY':
self.delay_state_IDs.append(state_ID)
self.calibrator_state_IDs.append(state_ID)
elif self.scan_intent == 'CALIBRATE_AMPLI':
self.flux_state_IDs.append(state_ID)
self.calibrator_state_IDs.append(state_ID)
elif self.scan_intent == 'CALIBRATE_POLARIZATION':
self.polarization_state_IDs.append(state_ID)
self.calibrator_state_IDs.append(state_ID)
elif self.scan_intent == 'CALIBRATE_PHASE':
self.phase_state_IDs.append(state_ID)
self.calibrator_state_IDs.append(state_ID)
elif self.scan_intent == 'CALIBRATE_POINTING':
self.pointing_state_IDs.append(state_ID)
self.calibrator_state_IDs.append(state_ID)
# casa_tools.table.open(self.vis)
if len(self.flux_state_IDs) == 0:
# QA_msinfo='Fail'
# logprint("ERROR: No flux density calibration scans found", logfileout='logs/msinfo.log')
raise Exception("No flux density calibration scans found")
else:
self.flux_state_select_string = ('STATE_ID in [%s'%self.flux_state_IDs[0])
for state_ID in range(1, len(self.flux_state_IDs)):
self.flux_state_select_string += (',%s')%self.flux_state_IDs[state_ID]
self.flux_state_select_string += ']'
# print 'CAL INTENT CACHE 3:'
# print tb.showcache()
with casa_tools.TableReader(self.vis) as table:
subtable = table.query(self.flux_state_select_string)
self.flux_scan_list = list(numpy.unique(subtable.getcol('SCAN_NUMBER')))
self.flux_scan_select_string = ','.join(["%s" % ii for ii in self.flux_scan_list])
# logprint ("Flux density calibrator(s) scans are "
# +flux_scan_select_string, logfileout='logs/msinfo.log')
self.flux_field_list = list(numpy.unique(subtable.getcol('FIELD_ID')))
self.flux_field_select_string = ','.join(["%s" % ii for ii in self.flux_field_list])
# logprint ("Flux density calibrator(s) are fields "
# +flux_field_select_string, logfileout='logs/msinfo.log')
subtable.close()
# print 'CAL INTENT CACHE 4:'
# print tb.showcache()
if len(self.bandpass_state_IDs) == 0:
# logprint ("No bandpass calibration scans defined, using flux density calibrator(s)")
self.bandpass_scan_select_string=self.flux_scan_select_string
# logprint ("Bandpass calibrator(s) scans are "
# +bandpass_scan_select_string, logfileout='logs/msinfo.log')
self.bandpass_field_select_string=self.flux_field_select_string
# logprint ("Bandpass calibrator(s) are fields "
# +bandpass_field_select_string, logfileout='logs/msinfo.log')
else:
self.bandpass_state_select_string = ('STATE_ID in [%s'%self.bandpass_state_IDs[0])
for state_ID in range(1, len(self.bandpass_state_IDs)):
self.bandpass_state_select_string += (',%s')%self.bandpass_state_IDs[state_ID]
self.bandpass_state_select_string += ']'
# print 'CAL INTENT CACHE 5:'
# print tb.showcache()
with casa_tools.TableReader(self.vis) as table:
subtable = table.query(self.bandpass_state_select_string)
self.bandpass_scan_list = list(numpy.unique(subtable.getcol('SCAN_NUMBER')))
self.bandpass_scan_select_string = ','.join(["%s" % ii for ii in self.bandpass_scan_list])
# logprint ("Bandpass calibrator(s) scans are "
# +bandpass_scan_select_string, logfileout='logs/msinfo.log')
self.bandpass_field_list = list(numpy.unique(subtable.getcol('FIELD_ID')))
self.bandpass_field_select_string = ','.join(["%s" % ii for ii in self.bandpass_field_list])
# logprint ("Bandpass calibrator(s) are fields "
# +bandpass_field_select_string, logfileout='logs/msinfo.log')
if len(self.bandpass_field_list) > 1:
# logprint ("WARNING: More than one field is defined as the bandpass calibrator.",
# logfileout='logs/msinfo.log')
# logprint ("WARNING: Models are required for all BP calibrators if multiple fields",
# logfileout='logs/msinfo.log')
# logprint ("WARNING: are to be used, not yet implemented; the pipeline will use",
# logfileout='logs/msinfo.log')
# logprint ("WARNING: only the first field.", logfileout='logs/msinfo.log')
self.bandpass_field_select_string = str(self.bandpass_field_list[0])
subtable.close()
# print 'CAL INTENT CACHE 6:'
# print tb.showcache()
if len(self.delay_state_IDs) == 0:
# logprint ("No delay calibration scans defined, using bandpass calibrator")
self.delay_scan_select_string = self.bandpass_scan_select_string
# logprint ("Delay calibrator(s) scans are "+delay_scan_select_string, logfileout='logs/msinfo.log')
self.delay_field_select_string = self.bandpass_field_select_string
# logprint ("Delay calibrator(s) are fields "+delay_field_select_string, logfileout='logs/msinfo.log')
else:
self.delay_state_select_string = ('STATE_ID in [%s'%self.delay_state_IDs[0])
for state_ID in range(1, len(self.delay_state_IDs)):
self.delay_state_select_string += (',%s') % self.delay_state_IDs[state_ID]
self.delay_state_select_string += ']'
with casa_tools.TableReader(self.vis) as table:
subtable = table.query(self.delay_state_select_string)
self.delay_scan_list = list(numpy.unique(subtable.getcol('SCAN_NUMBER')))
self.delay_scan_select_string = ','.join(["%s" % ii for ii in self.delay_scan_list])
# logprint ("Delay calibrator(s) scans are "+delay_scan_select_string, logfileout='logs/msinfo.log')
self.delay_field_list = list(numpy.unique(subtable.getcol('FIELD_ID')))
self.delay_field_select_string = ','.join(["%s" % ii for ii in self.delay_field_list])
# logprint ("Delay calibrator(s) are fields "+delay_field_select_string,
# logfileout='logs/msinfo.log')
if (len(self.delay_field_list) > 1):
# logprint ("WARNING: More than one field is defined as the delay calibrator.",
# logfileout='logs/msinfo.log')
# logprint ("WARNING: Models are required for all delay calibrators if multiple fields",
# logfileout='logs/msinfo.log')
# logprint ("WARNING: are to be used, not yet implemented; the pipeline will use",
# logfileout='logs/msinfo.log')
# logprint ("WARNING: only the first field.", logfileout='logs/msinfo.log')
self.delay_field_select_string = str(self.delay_field_list[0])
subtable.close()
# print 'CAL INTENT CACHE 7:'
# print tb.showcache()
if len(self.polarization_state_IDs) == 0:
# logprint ("No polarization calibration scans defined, no polarization calibration possible",
# logfileout='logs/msinfo.log')
self.polarization_scan_select_string=''
self.polarization_field_select_string=''
else:
# logprint ("Warning: polarization calibration scans found,
# but polarization calibration not yet implemented", logfileout='logs/msinfo.log')
self.polarization_state_select_string = ('STATE_ID in [%s'%self.polarization_state_IDs[0])
for state_ID in range(1, len(self.polarization_state_IDs)):
self.polarization_state_select_string += (',%s')%self.polarization_state_IDs[state_ID]
self.polarization_state_select_string += ']'
with casa_tools.TableReader(self.vis) as table:
subtable = table.query(self.polarization_state_select_string)
self.polarization_scan_list = list(numpy.unique(subtable.getcol('SCAN_NUMBER')))
self.polarization_scan_select_string = ','.join(["%s" % ii for ii in self.polarization_scan_list])
# logprint ("Polarization calibrator(s) scans are "+polarization_scan_select_string,
# logfileout='logs/msinfo.log')
self.polarization_field_list = list(numpy.unique(subtable.getcol('FIELD_ID')))
self.polarization_field_select_string = ','.join(["%s" % ii for ii in self.polarization_field_list])
# logprint ("Polarization calibrator(s) are fields "+polarization_field_select_string,
# logfileout='logs/msinfo.log'
subtable.close()
# print 'CAL INTENT CACHE 8:'
# print tb.showcache()
if len(self.phase_state_IDs) == 0:
# QA_msinfo='Fail'
# logprint("ERROR: No gain calibration scans found", logfileout='logs/msinfo.log')
raise Exception("No gain calibration scans found")
else:
self.phase_state_select_string = ('STATE_ID in [%s'%self.phase_state_IDs[0])
for state_ID in range(1, len(self.phase_state_IDs)):
self.phase_state_select_string += (',%s')%self.phase_state_IDs[state_ID]
self.phase_state_select_string += ']'
with casa_tools.TableReader(self.vis) as table:
subtable = table.query(self.phase_state_select_string)
self.phase_scan_list = list(numpy.unique(subtable.getcol('SCAN_NUMBER')))
self.phase_scan_select_string = ','.join(["%s" % ii for ii in self.phase_scan_list])
# logprint ("Phase calibrator(s) scans are "+phase_scan_select_string,
# logfileout='logs/msinfo.log')
self.phase_field_list = list(numpy.unique(subtable.getcol('FIELD_ID')))
self.phase_field_select_string = ','.join(["%s" % ii for ii in self.phase_field_list])
# logprint ("Phase calibrator(s) are fields "+phase_field_select_string,
# logfileout='logs/msinfo.log')
subtable.close()
# print 'CAL INTENT CACHE 9:'
# print tb.showcache()
# Find all calibrator scans and fields
self.calibrator_state_select_string = ('STATE_ID in [%s'%self.calibrator_state_IDs[0])
for state_ID in range(1, len(self.calibrator_state_IDs)):
self.calibrator_state_select_string += (',%s')%self.calibrator_state_IDs[state_ID]
self.calibrator_state_select_string += ']'
with casa_tools.TableReader(self.vis) as table:
subtable = table.query(self.calibrator_state_select_string)
self.calibrator_scan_list = list(numpy.unique(subtable.getcol('SCAN_NUMBER')))
self.calibrator_scan_select_string = ','.join(["%s" % ii for ii in self.calibrator_scan_list])
self.calibrator_field_list = list(numpy.unique(subtable.getcol('FIELD_ID')))
self.calibrator_field_select_string = ','.join(["%s" % ii for ii in self.calibrator_field_list])
subtable.close()
# print 'CAL INTENT CACHE 10:'
# print tb.showcache()
# casa_tools.table.close()
else:
for state_ID in range(0, len(intents)):
self.state_intents = intents[state_ID].rsplit(',')
for intent in range(0, len(self.state_intents)):
self.scan_intent = self.state_intents[intent].rsplit('#')[0]
self.subscan_intent = self.state_intents[intent].rsplit('#')[1]
if self.scan_intent == 'CALIBRATE_BANDPASS':
self.bandpass_state_IDs.append(state_ID)
self.calibrator_state_IDs.append(state_ID)
elif self.scan_intent == 'CALIBRATE_DELAY':
self.delay_state_IDs.append(state_ID)
self.calibrator_state_IDs.append(state_ID)
elif self.scan_intent == 'CALIBRATE_FLUX':
self.flux_state_IDs.append(state_ID)
self.calibrator_state_IDs.append(state_ID)
elif self.scan_intent == 'CALIBRATE_POLARIZATION':
self.polarization_state_IDs.append(state_ID)
self.calibrator_state_IDs.append(state_ID)
elif self.scan_intent == 'CALIBRATE_AMPLI':
self.amp_state_IDs.append(state_ID)
self.calibrator_state_IDs.append(state_ID)
elif self.scan_intent == 'CALIBRATE_PHASE':
self.phase_state_IDs.append(state_ID)
self.calibrator_state_IDs.append(state_ID)
elif self.scan_intent == 'CALIBRATE_POINTING':
self.pointing_state_IDs.append(state_ID)
self.calibrator_state_IDs.append(state_ID)
# casa_tools.table.open(self.vis)
if len(self.flux_state_IDs) == 0:
# QA_msinfo='Fail'
# logprint("ERROR: No flux density calibration scans found", logfileout='logs/msinfo.log')
raise Exception("No flux density calibration scans found")
else:
self.flux_state_select_string = ('STATE_ID in [%s'%self.flux_state_IDs[0])
for state_ID in range(1, len(self.flux_state_IDs)):
self.flux_state_select_string += (',%s')%self.flux_state_IDs[state_ID]
self.flux_state_select_string += ']'
with casa_tools.TableReader(self.vis) as table:
subtable = table.query(self.flux_state_select_string)
self.flux_scan_list = list(numpy.unique(subtable.getcol('SCAN_NUMBER')))
self.flux_scan_select_string = ','.join(["%s" % ii for ii in self.flux_scan_list])
# logprint ("Flux density calibrator(s) scans are "+flux_scan_select_string,
# logfileout='logs/msinfo.log')
self.flux_field_list = list(numpy.unique(subtable.getcol('FIELD_ID')))
self.flux_field_select_string = ','.join(["%s" % ii for ii in self.flux_field_list])
# logprint ("Flux density calibrator(s) are fields "+flux_field_select_string,
# logfileout='logs/msinfo.log')
subtable.close()
# print 'CAL INTENT CACHE 11:'
# print tb.showcache()
if len(self.bandpass_state_IDs) == 0:
# logprint ("No bandpass calibration scans defined, using flux density calibrator",
# logfileout='logs/msinfo.log')
self.bandpass_scan_select_string=self.flux_scan_select_string
# logprint ("Bandpass calibrator(s) scans are "+bandpass_scan_select_string,
# logfileout='logs/msinfo.log')
self.bandpass_field_select_string=self.flux_field_select_string
# logprint ("Bandpass calibrator(s) are fields "+bandpass_field_select_string,
# logfileout='logs/msinfo.log')
else:
self.bandpass_state_select_string = ('STATE_ID in [%s'%self.bandpass_state_IDs[0])
for state_ID in range(1, len(self.bandpass_state_IDs)):
self.bandpass_state_select_string += (',%s')%self.bandpass_state_IDs[state_ID]
self.bandpass_state_select_string += ']'
with casa_tools.TableReader(self.vis) as table:
subtable = table.query(self.bandpass_state_select_string)
self.bandpass_scan_list = list(numpy.unique(subtable.getcol('SCAN_NUMBER')))
self.bandpass_scan_select_string = ','.join(["%s" % ii for ii in self.bandpass_scan_list])
# logprint ("Bandpass calibrator(s) scans are "+bandpass_scan_select_string,
# logfileout='logs/msinfo.log')
self.bandpass_field_list = list(numpy.unique(subtable.getcol('FIELD_ID')))
self.bandpass_field_select_string = ','.join(["%s" % ii for ii in self.bandpass_field_list])
# logprint ("Bandpass calibrator(s) are fields "+bandpass_field_select_string,
# logfileout='logs/msinfo.log')
if len(self.bandpass_field_list) > 1:
# logprint ("WARNING: More than one field is defined as the bandpass calibrator.",
# logfileout='logs/msinfo.log')
# logprint ("WARNING: Models are required for all BP calibrators if multiple fields",
# logfileout='logs/msinfo.log')
# logprint ("WARNING: are to be used, not yet implemented; the pipeline will use",
# logfileout='logs/msinfo.log')
# logprint ("WARNING: only the first field.", logfileout='logs/msinfo.log')
self.bandpass_field_select_string = str(self.bandpass_field_list[0])
subtable.close()
# print 'CAL INTENT CACHE 12:'
# print tb.showcache()
if len(self.delay_state_IDs) == 0:
# logprint ("No delay calibration scans defined, using bandpass calibrator",
# logfileout='logs/msinfo.log')
self.delay_scan_select_string=self.bandpass_scan_select_string
# logprint ("Delay calibrator(s) scans are "+delay_scan_select_string, logfileout='logs/msinfo.log')
self.delay_field_select_string=self.bandpass_field_select_string
# logprint ("Delay calibrator(s) are fields "+delay_field_select_string, logfileout='logs/msinfo.log')
else:
self.delay_state_select_string = ('STATE_ID in [%s'%self.delay_state_IDs[0])
for state_ID in range(1, len(self.delay_state_IDs)):
self.delay_state_select_string += (',%s') % self.delay_state_IDs[state_ID]
self.delay_state_select_string += ']'
with casa_tools.TableReader(self.vis) as table:
subtable = table.query(self.delay_state_select_string)
self.delay_scan_list = list(numpy.unique(subtable.getcol('SCAN_NUMBER')))
self.delay_scan_select_string = ','.join(["%s" % ii for ii in self.delay_scan_list])
# logprint ("Delay calibrator(s) scans are "+delay_scan_select_string, logfileout='logs/msinfo.log')
self.delay_field_list = list(numpy.unique(subtable.getcol('FIELD_ID')))
self.delay_field_select_string = ','.join(["%s" % ii for ii in self.delay_field_list])
# logprint ("Delay calibrator(s) are fields "+delay_field_select_string,
# logfileout='logs/msinfo.log')
subtable.close()
# print 'CAL INTENT CACHE 13:'
# print tb.showcache()
if len(self.polarization_state_IDs) == 0:
# logprint ("No polarization calibration scans defined, no polarization calibration possible",
# logfileout='logs/msinfo.log')
self.polarization_scan_select_string=''
self.polarization_field_select_string=''
else:
# logprint ("Warning: polarization calibration scans found,
# but polarization calibration not yet implemented", logfileout='logs/msinfo.log')
self.polarization_state_select_string = ('STATE_ID in [%s' % self.polarization_state_IDs[0])
for state_ID in range(1, len(self.polarization_state_IDs)):
self.polarization_state_select_string += (',%s') % self.polarization_state_IDs[state_ID]
self.polarization_state_select_string += ']'
with casa_tools.TableReader(self.vis) as table:
subtable = table.query(self.polarization_state_select_string)
self.polarization_scan_list = list(numpy.unique(subtable.getcol('SCAN_NUMBER')))
self.polarization_scan_select_string = ','.join(["%s" % ii for ii in self.polarization_scan_list])
# logprint ("Polarization calibrator(s) scans are "+polarization_scan_select_string,
# logfileout='logs/msinfo.log')
self.polarization_field_list = list(numpy.unique(subtable.getcol('FIELD_ID')))
self.polarization_field_select_string = ','.join(["%s" % ii for ii in self.polarization_field_list])
# logprint ("Polarization calibrator(s) are fields "+polarization_field_select_string,
# logfileout='logs/msinfo.log')
subtable.close()
# print 'CAL INTENT CACHE 14:'
# print tb.showcache()
if len(self.phase_state_IDs) == 0:
# QA_msinfo='Fail'
# logprint("ERROR: No gain calibration scans found", logfileout='logs/msinfo.log')
raise Exception("No gain calibration scans found")
else:
self.phase_state_select_string = ('STATE_ID in [%s'%self.phase_state_IDs[0])
for state_ID in range(1, len(self.phase_state_IDs)):
self.phase_state_select_string += (',%s')%self.phase_state_IDs[state_ID]
self.phase_state_select_string += ']'
with casa_tools.TableReader(self.vis) as table:
subtable = table.query(self.phase_state_select_string)
self.phase_scan_list = list(numpy.unique(subtable.getcol('SCAN_NUMBER')))
self.phase_scan_select_string = ','.join(["%s" % ii for ii in self.phase_scan_list])
# logprint ("Phase calibrator(s) scans are "+phase_scan_select_string, logfileout='logs/msinfo.log')
self.phase_field_list = list(numpy.unique(subtable.getcol('FIELD_ID')))
self.phase_field_select_string = ','.join(["%s" % ii for ii in self.phase_field_list])
# logprint ("Phase calibrator(s) are fields "+phase_field_select_string,
# logfileout='logs/msinfo.log')
subtable.close()
# print 'CAL INTENT CACHE 15:'
# print tb.showcache()
if len(self.amp_state_IDs) == 0:
# logprint ("No amplitude calibration scans defined, will use phase calibrator",
# logfileout='logs/msinfo.log')
self.amp_scan_select_string=self.phase_scan_select_string
# logprint ("Amplitude calibrator(s) scans are "+amp_scan_select_string, logfileout='logs/msinfo.log')
self.amp_field_select_string=self.phase_scan_select_string
# logprint ("Amplitude calibrator(s) are fields "+amp_field_select_string, logfileout='logs/msinfo.log')
else:
self.amp_state_select_string = ('STATE_ID in [%s'%self.amp_state_IDs[0])
for state_ID in range(1, len(self.amp_state_IDs)):
self.amp_state_select_string += (',%s') % self.amp_state_IDs[state_ID]
self.amp_state_select_string += ']'
with casa_tools.TableReader(self.vis) as table:
subtable = table.query(self.amp_state_select_string)
self.amp_scan_list = list(numpy.unique(subtable.getcol('SCAN_NUMBER')))
self.amp_scan_select_string = ','.join(["%s" % ii for ii in self.amp_scan_list])
# logprint ("Amplitude calibrator(s) scans are "+amp_scan_select_string,
# logfileout='logs/msinfo.log')
self.amp_field_list = list(numpy.unique(subtable.getcol('FIELD_ID')))
self.amp_field_select_string = ','.join(["%s" % ii for ii in self.amp_field_list])
# logprint ("Amplitude calibrator(s) are fields "+amp_field_select_string,
# logfileout='logs/msinfo.log')
subtable.close()
# print 'CAL INTENT CACHE 16:'
# print tb.showcache()
# Find all calibrator scans and fields
self.calibrator_state_select_string = ('STATE_ID in [%s'%self.calibrator_state_IDs[0])
for state_ID in range(1, len(self.calibrator_state_IDs)):
self.calibrator_state_select_string += (',%s')%self.calibrator_state_IDs[state_ID]
self.calibrator_state_select_string += ']'
with casa_tools.TableReader(self.vis) as table:
subtable = table.query(self.calibrator_state_select_string)
self.calibrator_scan_list = list(numpy.unique(subtable.getcol('SCAN_NUMBER')))
self.calibrator_scan_select_string = ','.join(["%s" % ii for ii in self.calibrator_scan_list])
self.calibrator_field_list = list(numpy.unique(subtable.getcol('FIELD_ID')))
self.calibrator_field_select_string = ','.join(["%s" % ii for ii in self.calibrator_field_list])
subtable.close()
# print 'CAL INTENT CACHE 17:'
# print tb.showcache()
# casa_tools.table.close()
# If there are any pointing state IDs, subtract 2 from the number of
# science spws -- needed for QA scores
if len(self.pointing_state_IDs)>0:
self.numSpws2 = numSpws - 2
else:
self.numSpws2 = numSpws
if self.delay_scan_select_string == self.bandpass_scan_select_string:
self.testgainscans = self.bandpass_scan_select_string
else:
self.testgainscans = self.bandpass_scan_select_string + ',' + self.delay_scan_select_string
self.checkflagfields = ''
if self.bandpass_field_select_string == self.delay_field_select_string:
self.checkflagfields = self.bandpass_field_select_string
else:
self.checkflagfields = (self.bandpass_field_select_string + ',' + self.delay_field_select_string)
return True
[docs] def calibratorIntents(self):
"""
# Identify scans and fields associated with different calibrator intents
# NB: the scan intent definitions changed in the OPT on Feb 21,
# 2012. So test on date:
# Test Implementation: JSK April 11, 2016
"""
def buildSelectionString(selectionList):
return ','.join(["%s" % item for item in selectionList])
with casa_tools.MSMDReader(self.vis) as msmd:
# We used to use CALIBRATE_AMPLI rather than FLUX
# Note that in the current epoch we do not use the
# CALIBRATE_AMPLI intent for anything.
# There is an implicit assumption here that we only have one
# observation in the MS
# Changed April 2018 so that all flux scans and fields require FLUX,
# even prior to 2013.
if casa_tools.quanta.le(msmd.timerangeforobs(0)['begin']['m0'],
casa_tools.quanta.quantity("2012/02/21 12:00:00")):
self.flux_scan_select_string = \
buildSelectionString(msmd.scansforintent("CALIBRATE_FLUX*"))
self.flux_field_select_string = \
buildSelectionString(msmd.fieldsforintent("CALIBRATE_FLUX*"))
else:
self.flux_scan_select_string = \
buildSelectionString(msmd.scansforintent("CALIBRATE_FLUX*"))
self.flux_field_select_string = \
buildSelectionString(msmd.fieldsforintent("CALIBRATE_FLUX*"))
if (self.flux_field_select_string == ''):
LOG.warn("No flux density calibration fields found")
# Bandpass Cal Intent
self.bandpass_scan_select_string = \
buildSelectionString(msmd.scansforintent("CALIBRATE_BANDPASS*"))
bpfieldlist = msmd.fieldsforintent("CALIBRATE_BANDPASS*")
if len(bpfieldlist) > 1:
self.bandpass_field_select_string = \
buildSelectionString([bpfieldlist[0]])
LOG.warn("More than one field is defined as the bandpass calibrator.")
LOG.warn(" Models are required for all BP calibrators if multiple fields ")
LOG.warn(" are to be used, not yet implemented; the pipeline will use ")
LOG.warn(" only the first field.")
else:
self.bandpass_field_select_string = \
buildSelectionString(bpfieldlist)
if (self.bandpass_scan_select_string == '' or
self.bandpass_field_select_string == ''):
# Default to using the flux scan for bandpass
self.bandpass_scan_select_string = self.flux_scan_select_string
self.bandpass_field_select_string = self.flux_field_select_string
# Delay Cal Intent
self.delay_scan_select_string = \
buildSelectionString(msmd.scansforintent("CALIBRATE_DELAY*"))
delayfieldlist = msmd.fieldsforintent("CALIBRATE_DELAY*")
if len(delayfieldlist) > 1:
self.delay_field_select_string = \
buildSelectionString([delayfieldlist[0]])
LOG.warn("More than one field is defined as the delay calibrator.")
LOG.warn(" The pipeline will use only the first field.")
else:
self.delay_field_select_string = \
buildSelectionString(delayfieldlist)
if (self.delay_scan_select_string == '' or
self.delay_field_select_string == ''):
# Default to using the bandpass for the delay
self.delay_scan_select_string = self.bandpass_scan_select_string
self.delay_field_select_string = self.bandpass_field_select_string
# Polarization Cal Intent
self.polarization_scan_select_string = \
buildSelectionString(msmd.scansforintent("CALIBRATE_POLARIZATION*"))
self.polarization_field_select_string =\
buildSelectionString(msmd.fieldsforintent("CALIBRATE_POLARIZATION*"))
# Phase Cal Intent
self.phase_scan_select_string = \
buildSelectionString(msmd.scansforintent("CALIBRATE_PHASE*"))
self.phase_field_select_string = \
buildSelectionString(msmd.fieldsforintent("CALIBRATE_PHASE*"))
if (self.phase_scan_select_string == '' or
self.phase_field_select_string == ''):
LOG.warn("No gain calibration scans found")
# Find all calibrator scans and fields
self.calibrator_scan_select_string = \
buildSelectionString(msmd.scansforintent("CALIBRATE*"))
self.calibrator_field_select_string = \
buildSelectionString(msmd.fieldsforintent("CALIBRATE*"))
# JSK: Modifying the heuristic for dealing with the number of
# science SPWs after discussion with Claire 4/12/2016.
# New Heuristic is: from numSpws2 subtract the number of spws that
# only appear in pointing scans.
#
# Here is the Old hueristic
# If there are any pointing state IDs, subtract 2 from the number of
# science spws -- needed for QA scores
# if (len(self.pointing_state_IDs)>0):
# self.numSpws2 = numSpws - 2
# else:
# self.numSpws2 = numSpws
self.numSpws2 = msmd.nspw()
obsTargetSpws = msmd.spwsforintent("OBSERVE_TARGET*").tolist()
pointingSpws = msmd.spwsforintent("CALIBRATE_POINTING*").tolist()
for spw in pointingSpws:
if not obsTargetSpws.count(spw):
self.numSpws2 -= 1
# Here we pass through a set construct to get the unique union.
self.testgainscans= buildSelectionString(set
(msmd.scansforintent("CALIBRATE_BANDPASS*").tolist() +
msmd.scansforintent("CALIBRATE_DELAY*").tolist()))
self.checkflagfields= buildSelectionString(set
(msmd.fieldsforintent("CALIBRATE_BANDPASS*").tolist() +
msmd.fieldsforintent("CALIBRATE_DELAY*").tolist()))
return True
[docs] def find_3C84(self, positions):
MAX_SEPARATION = 60*2.0e-5
position_3C84 = casa_tools.measures.direction('j2000', '3h19m48.160', '41d30m42.106')
fields_3C84 = []
for ii in range(0, len(positions)):
position = casa_tools.measures.direction('j2000', str(positions[ii][0]) + 'rad', str(positions[ii][1]) + 'rad')
separation = casa_tools.measures.separation(position, position_3C84)['value'] * math.pi / 180.0
if separation < MAX_SEPARATION:
fields_3C84.append(ii)
return fields_3C84
[docs] def determine3C84(self):
"""
#Determine if 3C84 was used as a bandpass or delay calibrator
"""
self.positions = []
with casa_tools.TableReader(self.vis + '/FIELD') as table:
self.field_positions = table.getcol('PHASE_DIR')
for ii in range(0, len(self.field_positions[0][0])):
self.positions.append([self.field_positions[0][0][ii], self.field_positions[1][0][ii]])
self.fields_3C84 = self.find_3C84(self.positions)
self.cal3C84_d = False
self.cal3C84_bp = False
# uvrange3C84 = '0~1800klambda'
self.uvrange3C84 = ''
if self.fields_3C84 != []:
for field_int in self.fields_3C84:
if str(field_int) in self.delay_field_select_string:
self.cal3C84_d = True
# logprint("WARNING: 3C84 was observed as a delay calibrator, uvrange limits may be used",
# logfileout='logs/msinfo.log')
if str(field_int) in self.bandpass_field_select_string:
self.cal3C84_bp = True
# logprint("WARNING: 3C84 was observed as a BP calibrator, uvrange limits may be used",
# logfileout='logs/msinfo.log')
if (self.cal3C84_d == True) or (self.cal3C84_bp == True):
self.cal3C84 = True
else:
self.cal3C84 = False
return True
[docs]def testCalibratorIntents(vis):
# This is a temporary test program to see if the two methods of generating
# intents yield the same answers.
# To use:
# from pipeline.hifv.heuristics.vlascanheuristics import testCalibratorIntents
# testCalibratorIntents(<Name of MS>)
print("Testing Comparison of: {}".format(vis))
origObj = VLAScanHeuristics(vis)
newObj = VLAScanHeuristics(vis)
exceptionThrown = False
try:
start = datetime.datetime.now()
origObj.calibratorIntentsOld()
print('origObj: {}'.format(datetime.datetime.now()-start))
except Exception as e:
print(e)
exceptionThrown = True
try:
start = datetime.datetime.now()
newObj.calibratorIntents()
print('newObj: {}'.format(datetime.datetime.now()-start))
except Exception as e:
print(e)
exceptionThrown = True
# Now do the comparison:
if origObj.flux_scan_select_string != newObj.flux_scan_select_string:
print("flux_scan_select_strings Differ:")
print("\tOrig: {}".format(origObj.flux_scan_select_string))
print("\tNew: {}".format(newObj.flux_scan_select_string))
if origObj.flux_field_select_string != newObj.flux_field_select_string:
print("flux_field_select_strings Differ:")
print("\tOrig: {}".format(origObj.flux_field_select_string))
print("\tNew: {}".format(newObj.flux_field_select_string))
if origObj.bandpass_scan_select_string != newObj.bandpass_scan_select_string:
print("bandpass_scan_select_strings Differ:")
print("\tOrig: {}".format(origObj.bandpass_scan_select_string))
print("\tNew: {}".format(newObj.bandpass_scan_select_string))
if origObj.bandpass_field_select_string != newObj.bandpass_field_select_string:
print("bandpass_field_select_strings Differ:")
print("\tOrig: {}".format(origObj.bandpass_field_select_string))
print("\tNew: {}".format(newObj.bandpass_field_select_string))
if origObj.delay_scan_select_string != newObj.delay_scan_select_string:
print("delay_scan_select_strings Differ:")
print("\tOrig: {}".format(origObj.delay_scan_select_string))
print("\tNew: {}".format(newObj.delay_scan_select_string))
if origObj.delay_field_select_string != newObj.delay_field_select_string:
print("delay_field_select_strings Differ:")
print("\tOrig: {}".format(origObj.delay_field_select_string))
print("\tNew: {}".format(newObj.delay_field_select_string))
if origObj.polarization_scan_select_string != newObj.polarization_scan_select_string:
print("polarization_scan_select_strings Differ:")
print("\tOrig: {}".format(origObj.polarization_scan_select_string))
print("\tNew: {}".format(newObj.polarization_scan_select_string))
if origObj.polarization_field_select_string != newObj.polarization_field_select_string:
print("polarization_field_select_strings Differ:")
print("\tOrig: {}".format(origObj.polarization_field_select_string))
print("\tNew: {}".format(newObj.polarization_field_select_string))
if origObj.phase_scan_select_string != newObj.phase_scan_select_string:
print("phase_scan_select_strings Differ:")
print("\tOrig: {}".format(origObj.phase_scan_select_string))
print("\tNew: {}".format(newObj.phase_scan_select_string))
if origObj.phase_field_select_string != newObj.phase_field_select_string:
print("phase_field_select_strings Differ:")
print("\tOrig: {}".format(origObj.phase_field_select_string))
print("\tNew: {}".format(newObj.phase_field_select_string))
if origObj.calibrator_scan_select_string != newObj.calibrator_scan_select_string:
print("calibrator_scan_select_strings Differ:")
print("\tOrig: {}".format(origObj.calibrator_scan_select_string))
print("\tNew: {}".format(newObj.calibrator_scan_select_string))
if origObj.calibrator_field_select_string != newObj.calibrator_field_select_string:
print("calibrator_field_select_strings Differ:")
print("\tOrig: {}".format(origObj.calibrator_field_select_string))
print("\tNew: {}".format(newObj.calibrator_field_select_string))
if origObj.testgainscans != newObj.testgainscans:
print("testgainscanss Differ:")
print("\tOrig: {}".format(origObj.testgainscans))
print("\tNew: {}".format(newObj.testgainscans))
if origObj.checkflagfields != newObj.checkflagfields:
print("checkflagfieldss Differ:")
print("\tOrig: {}".format(origObj.checkflagfields))
print("\tNew: {}".format(newObj.checkflagfields))
if origObj.numSpws2 != newObj.numSpws2:
print("numSpws2 Differ:")
print("\tOrig: {}".format(origObj.numSpws2))
print("\tNew: {}".format(newObj.numSpws2))