def listobs_sum(msfile, config, config_raw, logger):
    """ 
    Write the listobs summary to file.
    
    Input:
    msfile = Path where the MS will be created. (String)
    """
    logger.info('Starting listobs summary.')
    sum_dir = './summary/'
    cf.makedir(sum_dir, logger)
    listobs_file = sum_dir + msfile + '.listobs.summary'
    cf.rmfile(listobs_file, logger)
    logger.info(
        'Writing listobs summary of data set to: {}'.format(listobs_file))
    listobs(vis=msfile, listfile=listobs_file)
    cf.check_casalog(config, config_raw, logger, casalog)
    logger.info('Completed listobs summary.')
def import_data(data_files, msfile, config, config_raw, logger):
    """ 
    Import VLA archive files from a location to a single MS.
    
    Input:
    data_files = Paths to the VLA archive files. (List/Array of Strings)
    msfile = Path where the MS will be created. (String)
    """
    logger.info('Starting import vla data')
    sum_dir = './summary/'
    cf.makedir(sum_dir, logger)
    cf.rmdir(msfile, logger)
    logger.info('Input files: {}'.format(data_files))
    logger.info('Output msfile: {}'.format(msfile))
    command = "importvla(archivefiles = {0}, vis = '{1}')".format(
        data_files, msfile)
    logger.info('Executing command: ' + command)
    exec(command)
    cf.check_casalog(config, config_raw, logger, casalog)
    logger.info('Completed import vla data')
def hanning_smooth(msfile, config, config_raw, config_file, logger):
    """
    Hanning smooths the dataset and replaces the previous version.
    
    Input:
    msfile = Path to the MS. (String)
    config = The parameters read from the configuration file. (Ordered dictionary)
    config_raw = The instance of the parser.
    config_file = Path to configuration file. (String)
    """
    logger.info('Starting Hanning smoothing.')
    importdata = config['importdata']
    command = "hanningsmooth(vis='{0}', outputvis='{0}_1')".format(msfile)
    logger.info('Executing command: ' + command)
    exec(command)
    cf.check_casalog(config, config_raw, logger, casalog)
    cf.rmdir(msfile + '.flagversions', logger)
    cf.makedir(msfile + '.flagversions', logger)
    cf.rmdir(msfile, logger)
    cf.mvdir(msfile + '_1', msfile, logger)
    logger.info('Completed Hanning smoothing.')
Beispiel #4
0
def image(config,config_raw,config_file,logger):
    """
    Generates a clean (continuum subtracted) image of each science target.
    Checks that the CLEANing scales and line emission channels are set (may prompt user if in interactive mode).
    Makes varies check on the ratio of pixel size to beam size and the scales and the maximum baseline (may prompt user if in interactive mode).
    Exports the final images as fits cubes (after regridding to J2000 if necessary).
    
    Input:
    config = The parameters read from the configuration file. (Ordered dictionary)
    config_raw = The instance of the parser.
    config_file = Path to configuration file. (String)
    """
    noises = noise_est(config,logger)
    cln_param = config['clean']
    if config_raw.has_option('clean','noise'):
        noises = cln_param['noise'][:]
        logger.info('Noise level(s) set manually as {0} Jy.'.format(noises))
    calib = config['calibration']
    contsub = config['continuum_subtraction']
    rest_freq = config['global']['rest_freq']
    targets = calib['target_names'][:]
    fields = calib['targets'][:]
    for i in range(len(targets)):
        target = targets[i]
        if 'spw' in target:
            inx = target.index('.spw')
            target_name = target[:inx]
            if target_name in calib['target_names'][i-1]:
                fields.insert(i,fields[i-1])
    if calib['mosaic']:
        targets = list(set(targets))
    src_dir = config['global']['src_dir']+'/'
    img_dir = config['global']['img_dir']+'/'
    cf.makedir('./'+img_dir,logger)
    logger.info('Starting generation of clean image(s).')
    reset_cln = False
    reset_cln = False
    if len(cln_param['line_ch']) == 0 or len(cln_param['line_ch']) != len(targets):
        if not interactive:
            logger.critical('The number of line channel ranges provided does not match the number of targets.')
            logger.info('Pixel sizes: {}'.format(cln_param['line_ch']))
            logger.info('Targets: {}'.format(targets))
            sys.exit(-1)
        reset_cln = True
        if len(cln_param['line_ch']) < len(targets):
            logger.warning('There are more target fields than channel ranges. Appending blank ranges.')
            while len(cln_param['line_ch']) < len(targets):
                cln_param['line_ch'].append('')
        elif len(cln_param['line_ch']) > len(targets):
            logger.warning('There are more channel ranges than target fields.')
            logger.info('Current channel ranges: {}'.format(cln_param['line_ch']))
            logger.warning('The channel range list will now be truncated to match the number of targets.')
            cln_param['line_ch'] = cln_param['line_ch'][:len(targets)]
    elif interactive:
        print('Current image channels set as:')
        for i in range(len(cln_param['line_ch'])):
            print('{0}: {1}'.format(targets[i],cln_param['line_ch'][i]))
        resp = str(raw_input('Do you want revise the channels that will be imaged (y/n): '))
        if resp.lower() in ['yes','ye','y']:
            reset_cln = True
    if reset_cln and interactive:
        print('For each target enter the channels you want to image in the following format:\nspwID:min_ch~max_ch')
        for i in range(len(targets)):
            print('Note: The continuum channels for this target were set to: {}'.format(contsub['linefree_ch'][i]))
            cln_param['line_ch'][i] = cf.uinput('Channels to image for {}: '.format(targets[i]), cln_param['line_ch'][i])
            logger.info('Setting image channels for {0} as: {1}.'.format(targets[i], cln_param['line_ch'][i]))
        logger.info('Updating config file to set channels to be imaged.')
        config_raw.set('clean','line_ch',cln_param['line_ch'])
        configfile = open(config_file,'w')
        config_raw.write(configfile)
        configfile.close()
    logger.info('Line emission channels set as: {}.'.format(cln_param['line_ch']))
    logger.info('For the targets: {}.'.format(targets))
    if numpy.any(cln_param['multiscale']):
        algorithm = 'multiscale'
        logger.info('Setting CLEAN algorithm to MS-CLEAN.')
        if not numpy.all(cln_param['multiscale']):
            logger.info('However, some targets will still use Hogbom CLEAN.')
        reset_cln = False
        if cln_param['beam_scales'] == []:
            reset_cln = True
            logger.warning('MS-CLEAN scales not set.')
        elif 0 not in cln_param['beam_scales']:
            logger.warning('MS-CLEAN scales do not include point sources. This is highly recommended.')
            if interactive:
                resp = str(raw_input('Do you want revise MS-CLEAN scales (y/n): '))
                if resp.lower() in ['yes','ye','y']:
                    reset_cln = True
            else:
                logger.info('Adding point source to MS-CLEAN scales.')
                cln_param['beam_scales'].append(0)
                reset_cln = True
        if reset_cln:
            if interactive:
                print('Current scales set to: {} beam diameters.'.format(cln_param['beam_scales']))
                cln_param['beam_scales'] = cf.uinput('Enter new scales: ', cln_param['beam_scales'])
            logger.info('Setting MS-CLEAN scales as {} beams.'.format(cln_param['beam_scales']))
            logger.info('Updating config file to set MS-CLEAN scales.')
            config_raw.set('clean','scales',cln_param['beam_scales'])
            configfile = open(config_file,'w')
            config_raw.write(configfile)
            configfile.close()
            reset_cln = False
        scales = cln_param['beam_scales']
    else:
        algorithm = 'hogbom'
        logger.info('Setting CLEAN algorithm to Hogbom.')
        scales = None
    for i in range(len(targets)):
        target = targets[i]
        field = fields[i]
        if numpy.all(cln_param['multiscale']):
            ms_clean = True
            algorithm = 'multiscale'
        elif type(cln_param['multiscale']) != type(True):
            ms_clean = cln_param['multiscale'][i]
            if ms_clean:
                algorithm = 'multiscale'
            else:
                algorithm = 'hogbom'
        else:
            ms_clean = False
            algorithm = 'hogbom'
        logger.info('Starting {} image.'.format(target))
        reset_cln = False
        ia.open(img_dir+target+'.dirty.image')
        rest_beam = ia.restoringbeam()
        ia.close()
        if rest_beam['minor']['unit'] not in cln_param['pix_size'][i]:
            logger.error('The pixel size and beam size have diffent units.')
            if ms_clean:
                logger.error('MS-CLEAN scales will likely be incorrect.')
            logger.info('Pixel size: {}'.format(cln_param['pix_size'][i]))
            logger.info('Beam size units: {}'.format(rest_beam['minor']['unit']))
        pix_size = cln_param['pix_size'][i]
        pix_size = float(pix_size[:pix_size.find(rest_beam['minor']['unit'])])
        if pix_size > 0.2*rest_beam['minor']['value']:
            logger.warning('There are fewer than 5 pixels across the beam minor axis. Consider decreasing the pixel size.')
            if interactive:
                print('Beam dimensions:')
                print('Major: {0:.2f} {1}'.format(rest_beam['major']['value'],rest_beam['major']['unit']))
                print('Minor: {0:.2f} {1}'.format(rest_beam['minor']['value'],rest_beam['minor']['unit']))
                print('Pixel size: {}'.format(cln_param['pix_size']))
                resp = str(raw_input('Do you want revise the pixel size (y/n): '))
                if resp.lower() in ['yes','ye','y']:
                    reset_cln = True
        if reset_cln and interactive:
            print('Enter the desired pixel size:')
            cln_param['pix_size'][i] = cf.uinput('Pixel size for {}: '.format(target), cln_param['pix_size'][i])
            logger.info('Setting pixel size for {0} as: {1}.'.format(target, cln_param['pix_size'][i]))
            resp = str(raw_input('Would you also like to revise the image size: '))
            if resp.lower() in ['yes','ye','y']:
                cln_param['im_size'][i] = cf.uinput('Image size for {}: '.format(target), cln_param['im_size'][i])
            logger.info('Setting image size for {0} as: {1}.'.format(target, cln_param['im_size'][i]))
            logger.info('Updating config file to set pixel (image) size.')
            config_raw.set('clean','pix_size',cln_param['pix_size'])
            config_raw.set('clean','im_size',cln_param['im_size'])
            configfile = open(config_file,'w')
            config_raw.write(configfile)
            configfile.close()
            reset_cln = False
        if cln_param['automask_sl'] == '':
            cln_param['automask_sl'] == 2.0
            logger.warning('Automasking sidelobe threshold not set. Using default value: {}'.format(cln_param['automask_sl']))
        if cln_param['automask_ns'] == '':
            cln_param['automask_ns'] == 4.25
            logger.warning('Automasking noise threshold not set. Using default value: {}'.format(cln_param['automask_ns']))
        if cln_param['automask_lns'] == '':
            cln_param['automask_lns'] == 1.5
            logger.warning('Automasking low noise threshold not set. Using default value: {}'.format(cln_param['automask_lns']))
        if cln_param['automask_mbf'] == '':
            cln_param['automask_mbf'] == 0.3
            logger.warning('Automasking minimum beam fraction not set. Using default value: {}'.format(cln_param['automask_mbf']))
        if cln_param['automask_neg'] == '':
            cln_param['automask_neg'] == 15.0
            logger.warning('Automasking negative threshold not set. Using default value: {}'.format(cln_param['automask_neg']))
        logger.info('Automasking parameters set as:')
        logger.info('sidelobethreshold = {}'.format(cln_param['automask_sl']))
        logger.info('noisethreshold = {}'.format(cln_param['automask_ns']))
        logger.info('lownoisethreshold = {}'.format(cln_param['automask_lns']))
        logger.info('minbeamfraction = {}'.format(cln_param['automask_mbf']))
        logger.info('negativethreshold = {}'.format(cln_param['automask_neg']))
        if ms_clean:
            pix_size = cln_param['pix_size'][i]
            pix_size = float(pix_size[:pix_size.find(rest_beam['minor']['unit'])])
            pix_per_beam = rest_beam['major']['value']/pix_size
            scales = cln_param['beam_scales']
            scales = list(numpy.array(numpy.array(scales)*pix_per_beam,dtype='int'))
            B_min = au.getBaselineLengths('{0}{1}.split.contsub'.format(src_dir,target), sort=True)[0][1]
            msmd.open('{0}{1}.split.contsub'.format(src_dir,target))
            spws = msmd.spwsforfield(field)
            f_min = None
            for spw in spws:
                if f_min == None or f_min > min(msmd.chanfreqs(spw=spw,unit='Hz')):
                    f_min = min(msmd.chanfreqs(spw=spw,unit='Hz'))
            msmd.close()
            max_scale = 180.*3600.*299792458./(1.2*numpy.pi*f_min*B_min)
            logger.info('The maximum recoverable scale for {0} is {1} arcsec.'.format(target,int(max_scale)))
            if 'arcsec' not in cln_param['pix_size'][i]:
                logger.warning('Pixel size not in arcsec. Maximum scale not checked.')
            else:
                pix_size = cln_param['pix_size'][i]
                pix_size = float(pix_size[:pix_size.find('arcsec')])
                if max(scales)*pix_size > max_scale:
                    logger.warning('Some MS-CLEAN scale(s) is (are) larger than largest recoverable angular scales.')
                    logger.info('Removing offending scales.')
                    scales = list(set(numpy.where(numpy.array(scales)*pix_size <= max_scale,scales,0)))
            logger.info('CLEANing with scales of {} pixels.'.format(scales))
        logger.info('CLEANing {0} to a threshold of {1} Jy.'.format(target,noises[i]*cln_param['thresh']))
        if cln_param['automask']:
            mask = 'auto-multithresh'
        else:
            mask = 'pb'
        gridder = 'wproject'
        if calib['mosaic']:
            for target_name in targets:
                inx = [j for j in range(len(calib['target_names'])) if target_name in calib['target_names'][j]]
                fields = numpy.array(calib['targets'],dtype='str')[inx]
            field = ','.join(fields)
            gridder = 'mosaic'
        command = "tclean(vis='{0}{1}'+'.split.contsub', field='{2}', spw='{3}', imagename='{4}{1}', cell='{5}', imsize=[{6},{6}], specmode='cube', outframe='bary', veltype='radio', restfreq='{7}', gridder='{8}', wprojplanes=-1, pblimit=0.1, normtype='flatnoise', deconvolver='{9}', scales={10}, restoringbeam='common', pbcor=True, weighting='briggs', robust={11}, niter=100000, gain=0.1, threshold='{12}Jy', usemask='{13}', phasecenter='{14}', sidelobethreshold={15}, noisethreshold={16}, lownoisethreshold={17}, minbeamfrac={18}, negativethreshold={19}, cyclefactor=2.0,interactive=False)".format(src_dir,target,field,cln_param['line_ch'][i],img_dir,cln_param['pix_size'][i],cln_param['im_size'][i],rest_freq,gridder,algorithm,scales,cln_param['robust'],noises[i]*cln_param['thresh'],mask,cln_param['phasecenter'],cln_param['automask_sl'],cln_param['automask_ns'],cln_param['automask_lns'],cln_param['automask_mbf'],cln_param['automask_neg'])
        logger.info('Executing command: '+command)
        exec(command)
        cf.check_casalog(config,config_raw,logger,casalog)
        logger.info('CLEANing finished. Image cube saved as {}.'.format(target+'.image'))
        ia.open(img_dir+target+'.dirty.image')
        coords = ia.coordsys()
        coord_chn = False
        if 'J2000' not in coords.referencecode()[0]:
            coord_chn = True
            logger.info('Coordinate system not J2000. Image will be regridded.')
            command = "imregrid(imagename='{0}{1}'+'.image', template='J2000', output='{0}{1}'+'.image.J2000', asvelocity=True, interpolation='linear', decimate=10, overwrite=True)".format(img_dir,target)
            logger.info('Executing command: '+command)
            exec(command)
            cf.check_casalog(config,config_raw,logger,casalog)
            logger.info('{} regridded in J2000 coordinates.'.format(target+'.image.J2000'))
            command = "imregrid(imagename='{0}{1}'+'.image.pbcor', template='J2000', output='{0}{1}'+'.image.pbcor.J2000', asvelocity=True, interpolation='linear', decimate=10, overwrite=True)".format(img_dir,target)
            logger.info('Executing command: '+command)
            exec(command)
            cf.check_casalog(config,config_raw,logger,casalog)
            logger.info('{} regridded in J2000 coordinates.'.format(target+'.image.pbcor.J2000'))
        coords.done()
        ia.close()
        fitsname = target+'_HI.fits'
        logger.info('Saving image cube as {}'.format(fitsname))
        if coord_chn:
            imagename = target+'.image.J2000'
        else:
            imagename = target+'.image'
        command = "exportfits(imagename='{0}{1}', fitsimage='{0}{2}', velocity=True,optical=False,overwrite=True,dropstokes=True,stokeslast=True,history=True,dropdeg=True)".format(img_dir,imagename,fitsname)
        logger.info('Executing command: '+command)
        exec(command)
        cf.check_casalog(config,config_raw,logger,casalog)
        fitsname = target+'_HI.pbcor.fits'
        logger.info('Saving primary beam corrected image cube as {}'.format(fitsname))
        if coord_chn:
            imagename = target+'.image.pbcor.J2000'
        else:
            imagename = target+'.image.pbcor'
        command = "exportfits(imagename='{0}{1}', fitsimage='{0}{2}', velocity=True,optical=False,overwrite=True,dropstokes=True,stokeslast=True,history=True,dropdeg=True)".format(img_dir,imagename,fitsname)
        logger.info('Executing command: '+command)
        exec(command)
        cf.check_casalog(config,config_raw,logger,casalog)
        coord_chn = False
    logger.info('Completed generation of clean image(s).')
Beispiel #5
0
msfiles = []
for proj in proj_IDs:
    msfile = '../{0}/sources/HCG{1}*.*split.contsub'.format(proj, str(HCG))
    new_files = glob.glob(msfile)
    if len(new_files) > 0:
        msfiles.extend(new_files)
        logger.info('MS file(s) added to combine list: {}'.format(new_files))
    else:
        logger.warning('MS not found: {}'.format(msfile))

logger.info('Setting relative weights of each MS.')
for msfile in msfiles:
    command = "initweights(vis='{0}', wtmode='nyq')".format(msfile)
    logger.info('Executing command: ' + command)
    exec(command)
    cf.check_casalog(config, config_raw, logger, casalog)

logger.info('Starting to make combined clean image.')

img_dir = 'HCG' + str(HCG)

img_param = config['image']
img_param['msfiles'] = msfiles
img_param['img_dir'] = img_dir
img_param['HCG'] = HCG
img_param['clean_thresh'] = 2.5 * img_param['rms']
if not config_raw.has_option('image', 'restoringbeam'):
    command = "tclean(vis={msfiles}, imagename='{img_dir}/HCG{HCG}', cell='{pix_size}', imsize={im_size}, spw='{im_chns}', specmode='cube', outframe='bary', veltype='radio', restfreq='{rest_freq}', gridder='mosaic', wprojplanes=128, pblimit=0.1, normtype='flatnoise', deconvolver='multiscale', scales={scales}, weighting='briggs', robust={robust}, restoringbeam='common', pbcor=True, niter=100000, gain=0.1, cyclefactor=2.0, interactive=False, threshold='{clean_thresh}mJy', usemask='auto-multithresh', phasecenter='{phasecenter}', sidelobethreshold={automask_sl}, noisethreshold={automask_ns}, lownoisethreshold={automask_lns}, minbeamfrac={automask_mbf}, negativethreshold={automask_neg})".format(
        **img_param)
else:
    command = "tclean(vis={msfiles}, imagename='{img_dir}/HCG{HCG}', cell='{pix_size}', imsize={im_size}, spw='{im_chns}', specmode='cube', outframe='bary', veltype='radio', restfreq='{rest_freq}', gridder='mosaic', wprojplanes=128, pblimit=0.1, normtype='flatnoise', deconvolver='multiscale', scales={scales}, weighting='briggs', robust={robust}, restoringbeam={restoringbeam}, pbcor=True, niter=100000, gain=0.1, cyclefactor=2.0, interactive=False, threshold='{clean_thresh}mJy', usemask='auto-multithresh', phasecenter='{phasecenter}', sidelobethreshold={automask_sl}, noisethreshold={automask_ns}, lownoisethreshold={automask_lns}, minbeamfrac={automask_mbf}, negativethreshold={automask_neg})".format(
def dirty_cont_image(config, config_raw, config_file, logger):
    """
    Generates a dirty image of each science target including the continuum emission.
    Checks that the pixel size and image size are set (will prompt user if in interactive mode).
    
    Input:
    config = The parameters read from the configuration file. (Ordered dictionary)
    config_raw = The instance of the parser.
    config_file = Path to configuration file. (String)
    """
    logger.info('Starting making dirty continuum image.')
    calib = config['calibration']
    rest_freq = config['global']['rest_freq']
    targets = calib['target_names'][:]
    fields = calib['targets'][:]
    for i in range(len(targets)):
        target = targets[i]
        if 'spw' in target:
            inx = target.index('.spw')
            target_name = target[:inx]
            if target_name in calib['target_names'][i - 1]:
                fields.insert(i, fields[i - 1])
    if calib['mosaic']:
        targets = list(set(calib['target_names']))
    cln_param = config['clean']
    src_dir = config['global']['src_dir'] + '/'
    img_dir = config['global']['img_dir'] + '/'
    cf.makedir('/.' + img_dir, logger)
    logger.info('Removing any existing dirty continuum images.')
    del_list = glob.glob(img_dir + '*cont.dirty*')
    for file_path in del_list:
        logger.info('Deleting: ' + file_path)
        shutil.rmtree(file_path)
    logger.info('Checking clean parameters for dirty image (inc. continuum).')
    reset_cln = False
    if (len(cln_param['pix_size'])
            == 0) or (len(cln_param['pix_size']) != len(targets)):
        if not interactive:
            logger.critical(
                'The number of pixel sizes provided does not match the number of targets.'
            )
            logger.info('Pixel sizes: {}'.format(cln_param['pix_size']))
            logger.info('Targets: {}'.format(targets))
            sys.exit(-1)
        reset_cln = True
        if len(cln_param['pix_size']) < len(targets):
            logger.warning(
                'There are more target fields than pixel sizes. Appending blanks.'
            )
            while len(cln_param['pix_size']) < len(targets):
                cln_param['pix_size'].append('')
        elif len(cln_param['pix_size']) > len(targets):
            logger.warning('There are more pixel sizes than target fields.')
            logger.info('Current pixel sizes: {}'.format(
                cln_param['pix_size']))
            logger.warning(
                'The pixel size list will now be truncated to match the number of targets.'
            )
            cln_param['pix_size'] = cln_param['pix_size'][:len(targets)]
    elif interactive:
        print('Current pixel sizes set as:')
        for i in range(len(cln_param['pix_size'])):
            print('{0}: {1}'.format(targets[i], cln_param['pix_size'][i]))
        resp = str(raw_input('Do you want revise the pixel sizes (y/n): '))
        if resp.lower() in ['yes', 'ye', 'y']:
            reset_cln = True
    if reset_cln and interactive:
        print('For each target enter the desired pixel size:')
        for i in range(len(targets)):
            cln_param['pix_size'][i] = cf.uinput(
                'Pixel size for {}: '.format(targets[i]),
                cln_param['pix_size'][i])
            logger.info('Setting pixel size for {0} as: {1}.'.format(
                targets[i], cln_param['pix_size'][i]))
        logger.info('Updating config file to set pixel sizes.')
        config_raw.set('clean', 'pix_size', cln_param['pix_size'])
        configfile = open(config_file, 'w')
        config_raw.write(configfile)
        configfile.close()
    logger.info('Pixel sizes set as: {}.'.format(cln_param['pix_size']))
    logger.info('For the targets: {}.'.format(targets))
    reset_cln = False
    if len(cln_param['im_size']) == 0 or len(
            cln_param['im_size']) != len(targets):
        if not interactive:
            logger.critical(
                'The number of image sizes provided does not match the number of targets.'
            )
            logger.info('Image sizes: {}'.format(cln_param['im_size']))
            logger.info('Targets: {}'.format(targets))
            sys.exit(-1)
        reset_cln = True
        if len(cln_param['im_size']) < len(targets):
            logger.warning(
                'There are more target fields than image sizes. Appending blanks.'
            )
            while len(cln_param['im_size']) < len(targets):
                cln_param['im_size'].append('')
        elif len(cln_param['im_size']) > len(targets):
            logger.warning('There are more image sizes than target fields.')
            logger.info('Current image sizes: {} pixels.'.format(
                cln_param['im_size']))
            logger.warning(
                'The image size list will now be truncated to match the number of targets.'
            )
            cln_param['im_size'] = cln_param['im_size'][:len(targets)]
    elif interactive:
        print('Current images sizes set as:')
        for i in range(len(cln_param['im_size'])):
            print('{0}: {1}'.format(targets[i], cln_param['im_size'][i]))
        resp = str(raw_input('Do you want revise the image sizes (y/n): '))
        if resp.lower() in ['yes', 'ye', 'y']:
            reset_cln = True
    if reset_cln and interactive:
        print('For each target enter the desired image size:')
        for i in range(len(targets)):
            print('Note: The pixel size for this target was set to: {}'.format(
                cln_param['pix_size'][i]))
            cln_param['im_size'][i] = cf.uinput(
                'Image size for {}: '.format(targets[i]),
                cln_param['im_size'][i])
            logger.info('Setting image size for {0} as: {1} x {2}.'.format(
                targets[i], cln_param['im_size'][i], cln_param['pix_size'][i]))
        logger.info('Updating config file to set image sizes.')
        config_raw.set('clean', 'im_size', cln_param['im_size'])
        configfile = open(config_file, 'w')
        config_raw.write(configfile)
        configfile.close()
    logger.info('Image sizes set as: {} pixels.'.format(cln_param['im_size']))
    logger.info('For the targets: {}.'.format(targets))
    for i in range(len(targets)):
        target = targets[i]
        field = fields[i]
        gridder = 'wproject'
        if calib['mosaic']:
            for target_name in targets:
                inx = [
                    j for j in range(len(calib['target_names']))
                    if target_name in calib['target_names'][j]
                ]
                fields = numpy.array(calib['targets'], dtype='str')[inx]
            field = ','.join(fields)
            gridder = 'mosaic'
        logger.info(
            'Making dirty image of {} (inc. continuum).'.format(target))
        command = "tclean(vis='{0}{1}.split', field='{2}', imagename='{3}{1}.cont.dirty', cell='{4}', imsize=[{5},{5}], specmode='cube', outframe='bary', veltype='radio', restfreq='{6}', gridder='{7}', wprojplanes=-1, pblimit=0.1, normtype='flatnoise', deconvolver='hogbom', weighting='briggs', robust={8}, niter=0, phasecenter='{9}', interactive=False)".format(
            src_dir, target, field, img_dir, cln_param['pix_size'][i],
            cln_param['im_size'][i], rest_freq, gridder, cln_param['robust'],
            cln_param['phasecenter'])
        logger.info('Executing command: ' + command)
        exec(command)
        cf.check_casalog(config, config_raw, logger, casalog)
    logger.info('Completed making dirty continuum image.')
def transform_data(msfile, config, config_raw, config_file, logger):
    """
    Allows the user to alter the data set by selection only specific observations, fields, and SPWs.
    
    Input:
    msfile = Path to the MS. (String)
    config = The parameters read from the configuration file. (Ordered dictionary)
    config_raw = The instance of the parser.
    config_file = Path to configuration file. (String)
    """
    logger.info('Starting data transform.')
    importdata = config['importdata']
    chanavg = False
    if not importdata['mstransform']:
        if interactive:
            print(
                'You may want to review the listobs summary of the imported data to decide if certain observations, SPWs, or fields should be removed.'
            )
            resp = ''
            while (resp.lower() not in [
                    'yes', 'ye', 'y'
            ]) and (resp.lower() not in ['no', 'n']):
                resp = str(
                    raw_input('Do you want to transform the data set (y/n): '))
            if resp.lower() in ['yes', 'ye', 'y']:
                importdata['mstransform'] = True
    if importdata['mstransform']:
        if interactive:
            print(
                'Select which observations, SPWs, and fields to keep in the MS.'
            )
            print('Blank strings mean all.')
            importdata['keep_obs'] = [
                cf.uinput('The following observations will be kept: ',
                          importdata['keep_obs'])
            ]
            importdata['keep_spws'] = [
                cf.uinput('The following SPWs will be kept: ',
                          importdata['keep_spws'])
            ]
            importdata['keep_fields'] = [
                cf.uinput('The following fields will be kept: ',
                          importdata['keep_fields'])
            ]
            resp = ''
            while (resp.lower() not in [
                    'yes', 'ye', 'y'
            ]) and (resp.lower() not in ['no', 'n']):
                resp = str(
                    raw_input(
                        'Do you want to perform channel averaging (y/n): '))
            if resp.lower() in ['yes', 'ye', 'y']:
                chanavg = True
                importdata['chanavg'] = int(
                    cf.uinput(
                        'Enter the number of channels to be averaged together: ',
                        importdata['chanavg']))
        command = "mstransform(vis='{0}', outputvis='{0}_1', field='{1}', spw='{2}', observation='{3}', datacolumn='data'".format(
            msfile, ','.join(importdata['keep_fields']),
            ','.join(importdata['keep_spws']),
            ','.join(importdata['keep_obs']))
        if config_raw.has_option('importdata', 'hanning'):
            if config['importdata']['hanning']:
                command += ', hanning=True'
        if config_raw.has_option('importdata', 'chanavg') or chanavg:
            if importdata['chanavg'] > 1:
                command += ', chanaverage=True, chanbin=' + str(
                    importdata['chanavg'])
        command += ')'
        logger.info('Executing command: ' + command)
        exec(command)
        cf.check_casalog(config, config_raw, logger, casalog)
        logger.info(
            'Updating config file ({0}) to set mstransform values.'.format(
                config_file))
        config_raw.set('importdata', 'keep_obs', importdata['keep_obs'])
        config_raw.set('importdata', 'keep_spws', importdata['keep_spws'])
        config_raw.set('importdata', 'keep_fields', importdata['keep_fields'])
        if config_raw.has_option('importdata', 'chanavg') or chanavg:
            config_raw.set('importdata', 'chanavg', importdata['chanavg'])
        configfile = open(config_file, 'w')
        config_raw.write(configfile)
        configfile.close()
        cf.rmdir(msfile + '.flagversions', logger)
        cf.makedir(msfile + '.flagversions', logger)
        cf.rmdir(msfile, logger)
        cf.mvdir(msfile + '_1', msfile, logger)
        logger.info('Completed data transformation.')
        listobs_sum(msfile, config, config_raw, logger)
    else:
        logger.info('No transformation made.')
def contsub(msfile, config, config_raw, config_file, logger):
    """
    Subtracts the continuum from each of the science target MSs.
    If the no line free range is set then the user is queried (in interactive mode) and the configuration file updated.
    
    Input:
    msfile = Path to the MS. (String)
    config = The parameters read from the configuration file. (Ordered dictionary)
    config_raw = The instance of the parser.
    config_file = Path to configuration file. (String)
    """
    logger.info('Starting continuum subtraction.')
    contsub = config['continuum_subtraction']
    calib = config['calibration']
    src_dir = config['global']['src_dir'] + '/'
    logger.info('Checking for line free channel ranges in parameters.')
    targets = calib['target_names'][:]
    fields = calib['targets'][:]
    for i in range(len(targets)):
        target = targets[i]
        if 'spw' in target:
            inx = target.index('.spw')
            target_name = target[:inx]
            if target_name in calib['target_names'][i - 1]:
                fields.insert(i, fields[i - 1])
    if calib['mosaic']:
        logger.info(
            'The parameters file indicates that this data set is a mosaic.')
        logger.info(
            'All fields in the mosaic will have the same continuum channels.')
        targets = list(set(targets))
    reset_ch = False
    if len(contsub['linefree_ch']) == 0 or len(
            contsub['linefree_ch']) != len(targets):
        reset_ch = True
        if len(contsub['linefree_ch']) < len(targets):
            logger.warning(
                'There are more target fields than channel ranges. Appending blank ranges.'
            )
            while len(contsub['linefree_ch']) < len(targets):
                contsub['linefree_ch'].append('')
        elif len(contsub['linefree_ch']) > len(targets):
            logger.warning('There are more channel ranges than target fields.')
            logger.info('Current channel ranges: {}'.format(
                contsub['linefree_ch']))
            logger.warning(
                'The channel range list will now be truncated to match the number of targets.'
            )
            contsub['linefree_ch'] = contsub['linefree_ch'][:len(targets)]
    elif interactive:
        print('Current line free channels set as:')
        for i in range(len(contsub['linefree_ch'])):
            print('{0}: {1}'.format(targets[i], contsub['linefree_ch'][i]))
        resp = str(
            raw_input('Do you want revise the line free channels (y/n): '))
        if resp.lower() in ['yes', 'ye', 'y']:
            reset_ch = True
    if reset_ch:
        if not interactive:
            logger.critical(
                'The number of line free channel ranges provided does not match the number of targets.'
            )
            logger.info('Line free change ranges: {}'.format(
                contsub['linefree_ch']))
            logger.info('Targets: {}'.format(targets))
            sys.exit(-1)
        else:
            print(
                'For each target enter the line free channels in the following format:\nspwID1:min_ch1~max_ch1;min_ch2~max_ch2,spwID2:min_ch3~max_ch3;min_ch4~max_ch4'
            )
            for i in range(len(targets)):
                contsub['linefree_ch'][i] = cf.uinput(
                    'Line free channels for {}: '.format(targets[i]),
                    contsub['linefree_ch'][i])
                logger.info(
                    'Setting line free channels for {0} as: {1}.'.format(
                        targets[i], contsub['linefree_ch'][i]))
                if type(contsub['fitorder']) == type(1):
                    order_set = False
                    while not order_set:
                        try:
                            order = int(
                                cf.uinput(
                                    'Set the fit order for {}: '.format(
                                        targets[i]), contsub['fitorder']))
                            if order >= 0:
                                order_set = True
                        except ValueError:
                            print 'Fit order must be an integer.'
                    if order != contsub['fitorder'] and len(targets) > 1:
                        order_list = list(
                            numpy.zeros(len(targets), dtype='int') +
                            contsub['fitorder'])
                        order_list[i] = order
                        order = order_list
                    contsub['fitorder'] = order
                else:
                    order_set = False
                    while not order_set:
                        try:
                            order = int(
                                cf.uinput(
                                    'Set the fit order for {}: '.format(
                                        targets[i]), contsub['fitorder'][i]))
                            if order >= 0:
                                order_set = True
                                contsub['fitorder'] = order
                        except ValueError:
                            print 'Fit order must be an integer.'
            logger.info(
                'Updating config file to set line free channels and fit orders.'
            )
            config_raw.set('continuum_subtraction', 'linefree_ch',
                           contsub['linefree_ch'])
            config_raw.set('continuum_subtraction', 'fitorder',
                           contsub['fitorder'])
            configfile = open(config_file, 'w')
            config_raw.write(configfile)
            configfile.close()
    logger.info('Line free channels set as: {}.'.format(
        contsub['linefree_ch']))
    logger.info('Fit order(s) set as: {}.'.format(contsub['fitorder']))
    logger.info('For the targets: {}.'.format(targets))
    for i in range(len(targets)):
        target = targets[i]
        field = fields[i]
        if calib['mosaic']:
            for target_name in targets:
                inx = [
                    j for j in range(len(calib['target_names']))
                    if target_name in calib['target_names'][j]
                ]
                fields = numpy.array(calib['targets'], dtype='str')[inx]
            field = ','.join(fields)
        chans = contsub['linefree_ch'][i]
        spws = chans.split(',')
        for j in range(len(spws)):
            spw = spws[j].strip()
            inx = spw.index(':')
            spw = spw[0:inx]
            spws[j] = spw
        logger.info('Subtracting the continuum from field: {}'.format(target))
        if type(contsub['fitorder']) == type(1):
            order = int(contsub['fitorder'])
        else:
            order = int(contsub['fitorder'][i])
        command = "uvcontsub(vis='{0}{1}'+'.split', field='{2}', fitspw='{3}', spw='{4}', excludechans=False, combine='spw', solint='int', fitorder={5}, want_cont={6})".format(
            src_dir, target, field, chans, ','.join(spws), order,
            contsub['save_cont'])
        logger.info('Executing command: ' + command)
        exec(command)
        cf.check_casalog(config, config_raw, logger, casalog)
    logger.info('Completed continuum subtraction.')
def moment0(config,config_raw,config_file,logger):
    """
    Generates a moment zero map of each science target.
    
    Input:
    config = The parameters read from the configuration file. (Ordered dictionary)
    config_raw = The instance of the parser.
    config_file = Path to configuration file. (String)
    """
    noises = noise_est(config,logger)
    cln_param = config['clean']
    calib = config['calibration']
    if config_raw.has_option('clean','noise'):
        noises = cln_param['noise'][:]
        logger.info('Noise level(s) set manually as {0} Jy.'.format(noises))
    moment = config['moment']
    thresh = moment['mom_thresh']
    chans = moment['mom_chans']
    targets = config['calibration']['target_names']
    if calib['mosaic']:
        targets = list(set(targets))
    img_dir = config['global']['img_dir']+'/'
    mom_dir = config['global']['mom_dir']+'/'
    cf.makedir('./'+mom_dir,logger)
    
    change_made = False
    if len(chans) == 0 or len(chans) != len(targets):
        if len(chans) < len(targets):
            logger.warning('There are more target fields than channel ranges for moments.')
            while len(chans) < len(targets):
                chans.append('')
        elif len(chans) > len(targets):
            logger.warning('There are more moment channel ranges than target fields.')
            logger.info('Current channel ranges: {}'.format(chans))
            logger.warning('The channel range list will now be truncated to match the number of targets.')
            chans = chans[:len(targets)]
        change_made = True
    if interactive:
        print('Current moment channel ranges set as:')
        print(chans)
        print('For the targets:')
        print(targets)
        resp = ''
        while (resp.lower() not in ['yes','ye','y']) and (resp.lower() not in ['no','n']) :
            resp = str(raw_input('Do you want to revise these channel ranges (y/n): '))
        if resp.lower() in ['yes','ye','y']:
            change_made = True
            print('Please specify the channel ranges in the format: chan1~chan2.')
            for i in range(len(chans)):
                chans[i] = cf.uinput('Enter channel range for target {}: '.format(targets[i]), chans[i])
        else:
            pass
    if change_made:
        logger.info('Updating config file to set new moment channel ranges.')
        config_raw.set('moment','mom_chans',chans)
        configfile = open(config_file,'w')
        config_raw.write(configfile)
        configfile.close()
        
    logger.info('Starting generation of moment map(s).')
    
    J2000 = False
    img_list = glob.glob(img_dir+'*.image.J2000')
    if len(img_list) > 0:
        J2000 = True
    for i in range(len(targets)):
        if J2000:
            imagename = targets[i]+'.image.J2000'
        else:
            imagename = targets[i]+'.image'
        command = "immoments(imagename='{0}{1}',includepix=[{2},{3}],chans='{4}',outfile='{5}{6}.mom0')".format(img_dir,imagename,thresh*noises[i],thresh*1E6*noises[i],chans[i],mom_dir,targets[i])
        logger.info('Executing command: '+command)
        exec(command)
        cf.check_casalog(config,config_raw,logger,casalog)
        command = "exportfits(imagename='{0}{1}.mom0', fitsimage='{0}{1}.mom0.fits',overwrite=True,dropstokes=True,stokeslast=True,history=True,dropdeg=True)".format(mom_dir,targets[i])
        logger.info('Executing command: '+command)
        exec(command)
        cf.check_casalog(config,config_raw,logger,casalog)
    logger.info('Completed generation of moment map(s).')