Пример #1
0
def file_mime_detection(katfile):
    """Function to instantiate the correct metadata extraction class. The
    following file extensions are are currently detected: '.h5' and '.rdb'.

    Parameters:
    ----------
    katfile: string : name of file for mime detecetion.
    """
    file_ext = os.path.splitext(katfile)[1]
    if file_ext == '.h5':
        katdata = katdal.open(katfile)
        # 'katdata.ants' are sorted alphabetically.
        # KAT7 antennas start with 'ant'. MeerKAT (AR1 and onwards) antennas start with 'm'.
        # If the first antenna starts with 'ant' consider it KAT7 data.
        if katdata.ants[0].name.startswith('ant'):
            return KatFileProductMetExtractor(katdata)
        # if 'proposal_id' mention RTS at least once then it's an RTS file.
        elif 'proposal_id' in katdata.obs_params and katdata.obs_params[
                'proposal_id'].count('RTS') >= 1:
            return RTSTelescopeProductMetExtractor(katdata)
        # everything else that is .h5 must be MeerKAT AR1 and onwards
        else:
            return MeerKATAR1TelescopeProductMetExtractor(katdata)
    # vis trawler uses os.environ['SITENAME'] to differentiate instruments when extracting metadata.
    elif file_ext == '.rdb':
        if 'sdp_l0' in katfile:
            return MeerKATTelescopeProductMetExtractor(katfile)
        elif 'sdp_l1_flags' in katfile:
            return MeerKATFlagProductMetExtractor(katfile)
    raise MetExtractorException("File extension not supported %s" % (file_ext))
Пример #2
0
def main() -> None:
    parser = argparse.ArgumentParser()
    parser.add_argument('dataset', type=str, help='Input dataset')
    parser.add_argument('output_dir', type=str, help='Parent directory for output')
    parser.add_argument('prefix', type=str, help='Prefix for output directories and filenames')
    parser.add_argument('stream', type=str, help='Stream name for telescope state inputs')
    parser.add_argument('--log-level', type=str, metavar='LEVEL',
                        help='Logging level [INFO]')
    args = parser.parse_args()
    katsdpservices.setup_logging()
    if args.log_level is not None:
        logging.getLogger().setLevel(args.log_level.upper())

    dataset = katdal.open(args.dataset, chunk_store=None, upgrade_flags=False)
    telstate = dataset.source.telstate.wrapped.root()
    telstate = telstate.view(telstate.join(dataset.source.capture_block_id, args.stream))

    output_dir = '{}_{}'.format(args.prefix, uuid.uuid4())
    output_dir = os.path.join(args.output_dir, output_dir)
    filename = args.prefix + '_report.html'
    tmp_dir = output_dir + '.writing'
    os.mkdir(tmp_dir)
    try:
        common_stats, target_stats = report.get_stats(dataset, telstate)
        report.write_report(common_stats, target_stats, os.path.join(tmp_dir, filename))
        report.write_metadata(dataset, common_stats, target_stats,
                              os.path.join(tmp_dir, 'metadata.json'))
        os.rename(tmp_dir, output_dir)
    except Exception:
        # Make a best effort to clean up
        shutil.rmtree(tmp_dir, ignore_errors=True)
        raise
Пример #3
0
def build_offline_pipeline(data, **kwargs):
    """
    Decide based on the type of data how to
    build an offline pipeline instance and do it.

    Parameters
    ----------
    data : str or :class:`katdal.Dataset`
        file location or katdal Dataset object
        TODO: Allow for different types of data (eg UVFITS)
              so that this function actually does something.

    Returns
    -------
    :class:`Pipeline`
        A pipeline instance
    """
    if isinstance(data, DataSet):
        return KatdalOfflinePipeline(data, **kwargs)
    if isinstance(data, str):
        try:
            ds = katdal.open(data)
        except (IOError, DataSourceNotFound):
            pass
        else:
            return KatdalOfflinePipeline(ds, **kwargs)
    raise ValueError('Data type of %s not recognised for %s' % (type(data), data))
Пример #4
0
    def _test_data(self, *, options=(), channel0=36, channel1=72, max_chunk_vis=None,
                   missing=set(), channel_mask=None):
        loader = LoaderKatdal('file:///fake_filename.rdb', options, 24, None)
        bls = len(ANTENNAS) * (len(ANTENNAS) - 1) // 2    # Excludes auto-correlations
        vis, weights, uvw, feed_angle1, feed_angle2, chunks = \
            self._collect(loader.data_iter(channel0, channel1, max_chunk_vis=max_chunk_vis))

        dataset = katdal.open('file:///fake_filename.rdb')
        dataset.select(corrprods='cross', channels=np.s_[36:72], scans='track')
        if channel_mask is not None:
            channel_mask = channel_mask[channel0:channel1]
        e_vis, e_weights, e_uvw, e_feed_angle1, e_feed_angle2, e_polarizations = \
            self._get_expected(dataset, channel_mask)

        # Check the shapes before trying to shuffle data.
        N = self.shape[0] * bls
        C = e_vis.shape[1]
        P = 4
        assert_equal(vis.shape, (C, N, P))
        assert_equal(weights.shape, (C, N, P))
        assert_equal(uvw.shape, (N, 3))
        assert_equal(feed_angle1.shape, (N,))
        assert_equal(feed_angle2.shape, (N,))

        # The expected visibilities are all unique, so we can use them to
        # determine the permutation applied. We map each complex visibility to
        # its time-frequency-baseline coordinates.
        vis_map = {value: index for index, value in np.ndenumerate(e_vis)}
        for channel in range(C):
            for i in range(N):
                # Handling for missing correlation products assumes that the
                # first polarization product of a baseline will always be
                # present.
                baseline = dataset.corr_products[vis_map[vis[channel, i, 0]][2]]
                ant1 = baseline[0][:-1]
                ant2 = baseline[1][:-1]
                for j in range(P):
                    key = (ant1, ant2, loader.polarizations()[j])
                    if key in missing:
                        # Doesn't matter what the values are; it just has to be flagged
                        assert_equal(weights[channel, i, j], 0.0)
                        continue
                    # pop ensures that we don't see the same visibility twice
                    idx = vis_map.pop(vis[channel, i, j])
                    assert_equal(idx[1], channel)
                    assert_equal(loader.polarizations()[j], e_polarizations[idx[2]])
                    assert_equal(vis[channel, i, j], e_vis[idx])
                    assert_equal(weights[channel, i, j], e_weights[idx])
                    np.testing.assert_allclose(
                        uvw[i].to_value(u.m),
                        e_uvw[idx[0], idx[2]].to_value(u.m), rtol=1e-7
                    )
                    # Won't match exactly because the loader converts to float32
                    np.testing.assert_allclose(
                        feed_angle1[i], e_feed_angle1[idx[0], idx[2]], rtol=1e-6)
                    np.testing.assert_allclose(
                        feed_angle2[i], e_feed_angle2[idx[0], idx[2]], rtol=1e-6)
        assert_equal(len(vis_map), 0)
        loader.close()
        return chunks
Пример #5
0
def get_data(file, vSwitch):
    """Read hdf5 data and obtain relevant metadata information."""
    h5 = katdal.open(file)
    obs = h5.description
    sensors = h5.sensor.keys()
    tvals = h5.timestamps - h5.timestamps[0]  # get updated timestamps (s)
    descr = '\n'.join(
        h5.__str__().split('\n')[:23])  # human-friendly header information
    if (vSwitch == 1):
        print '\n', descr  # print header
    return h5, obs, tvals, sensors
Пример #6
0
 def __init__(self,
              filename,
              servers=None,
              bchan=0,
              echan=None,
              n_substreams=1):
     super().__init__(filename, servers, bchan, echan, n_substreams)
     try:
         self.file = katdal.open(filename, upgrade_flags=False)
     except IOError as error:
         raise WrongFileType(str(error)) from error
     self.file.select(channels=slice(bchan, echan))
     self.num_scans = len(self.file.scan_indices)
Пример #7
0
def readfile(path):
    """
    Read in the RDB file.

    Parameters
    ----------
    path : str
        RDB file

    Returns
    -------
    output_file : katdal.visdatav4.VisibilityDataV4
       katdal data object
    """
    vis = katdal.open(path)
    return vis
Пример #8
0
def select_and_average(filename, average_time):
    # Read a file into katdal, and average the data to the prescribed averaging time
    # Returns the weather data and timestamps with the correct averaging interval
    data = katdal.open(filename)

    raw_timestamps = data.sensor.timestamps
    raw_wind_speed = data.wind_speed
    raw_temperature = data.temperature
    raw_dumptime = data.dump_period

    # Get azel of each antenna and separation of each antenna
    sun = katpoint.Target('Sun, special', antenna=data.ants[0])
    alltimestamps = data.timestamps[:]
    solar_seps = np.zeros_like(alltimestamps)
    for dumpnum, timestamp in enumerate(alltimestamps):
        azeltarget = katpoint.construct_azel_target(
            katpoint.deg2rad(data.az[dumpnum, 0]),
            katpoint.deg2rad(data.el[dumpnum, 0]))
        azeltarget.antenna = data.ants[0]
        solar_seps[dumpnum] = katpoint.rad2deg(
            azeltarget.separation(sun, timestamp))
    #Determine number of dumps to average
    num_average = max(int(np.round(average_time / raw_dumptime)), 1)

    #Array of block indices
    indices = list(
        range(min(num_average, raw_timestamps.shape[0]),
              raw_timestamps.shape[0] + 1,
              min(num_average, raw_timestamps.shape[0])))

    timestamps = np.average(np.array(np.split(raw_timestamps, indices)[:-1]),
                            axis=1)
    wind_speed = np.average(np.array(np.split(raw_wind_speed, indices)[:-1]),
                            axis=1)
    temperature = np.average(np.array(np.split(raw_temperature, indices)[:-1]),
                             axis=1)

    dump_time = raw_dumptime * num_average

    return (timestamps, alltimestamps, wind_speed, temperature, dump_time,
            solar_seps, data.ants[0])
Пример #9
0
def readOBS(filename, ant, pol, fc, fnull):
    try:
        h5 = katdal.open(filename, quicklook=True)
    except Exception as err_msg:
        raise SystemExit('An error has occured:\n%s' % err_msg)
    h5.select(reset='T')
    h5.select(ants=ant, pol=pol, corrprods='auto', scans='track')
    visibilities = h5.vis[:]
    scan_indices = h5.scan_indices
    passband = h5.channel_freqs
    chan_bw = (h5.spectral_windows[0]).channel_width
    the_pointings = []
    for idx in scan_indices:
        h5.select(reset='T')
        h5.select(ants=ant, pol=pol, corrprods='auto', scans=idx)
        the_pointings.append(h5.shape[0])

    # Channel indices for passband baseline
    min_idx = numpy.argmin(numpy.abs(passband - f_start))
    max_idx = numpy.argmin(numpy.abs(passband - f_stop))
    baseline_idx = list(range(min_idx, max_idx))

    # Extract passband only
    visibilities = visibilities[:, baseline_idx, :]
    passband = passband[baseline_idx]
    # Channel indices over target
    min_idx = numpy.argmin(numpy.abs(passband - (fc - dft / 2.)))
    max_idx = numpy.argmin(numpy.abs(passband - (fc + dft / 2.)))
    target_range = list(range(min_idx, max_idx))
    # channel indices for null
    min_idx = numpy.argmin(numpy.abs(passband - (fnull - dfn / 2)))
    max_idx = numpy.argmin(numpy.abs(passband - (fnull + dfn / 2)))
    null_range = list(range(min_idx, max_idx))

    return [
        the_pointings, visibilities, chan_bw, passband, target_range,
        null_range
    ]
Пример #10
0
def analyse_spectrum(input_file,
                     output_dir='.',
                     polarisation='HH,VV',
                     baseline=None,
                     target=None,
                     freqav=None,
                     timeav=None,
                     freq_chans=None,
                     correct='spline',
                     flags_file=None,
                     smooth=3):
    """
    Plot the mean and standard deviation of the bandpass amplitude for a given target in a file

    Inputs
    ======
    polarisation: Comma separated list of polarisations to produce spectrum of, options are I, HH, VV, HV, VH. Default is I.
    baseline: Baseline to load (e.g. 'ant1,ant1' for antenna 1 auto-corr), default is first single-dish baseline in file.
    target: Target to plot spectrum of, default is the first target in the file.
    freqav: Frequency averaging interval in MHz. Default is a bin size that will produce 100 frequency channels.
    timeav: Time averageing interval in minutes. Default is the shortest scan length on the selected target.
    freq_chans: Range of frequency channels to keep (zero-based, specified as 'start,end', default is 90% of the bandpass.
    correct: Method to use to correct the spectrum in each average timestamp. Options are 'spline' - fit a cubic spline,'channels' - use the average at each channel Default: 'spline'
    output_dir: Output directory for pdfs. Default is cwd.
    flags_file: Name of .h5 file containg flags calculated from 'rfi_report.py'.
    debug: make a debug file containing all of the background fits to the dumps
    """

    h5data = katdal.open(input_file)
    #Get Baseline
    if baseline == None:
        baseline = h5data.ants[0].name + ',' + h5data.ants[0].name
    #Set up plotting.
    if type(input_file) == type(list()):
        fileprefix = os.path.join(
            output_dir,
            os.path.splitext(input_file[0].split('/')[-1])[0])
    else:
        fileprefix = os.path.join(
            output_dir,
            os.path.splitext(input_file.split('/')[-1])[0])
    basename = fileprefix + '_SpecBase_' + baseline.replace(',', '')
    pdf = PdfPages(basename + '.pdf')
    for this_pol in polarisation.split(','):
        print(this_pol, "polarisation.")
        # Get data from h5 file and use 'select' to obtain a useable subset of it.
        visdata, weightdata, h5data = \
            read_and_select_file(h5data, baseline, target=target, channels=freq_chans, polarisation=this_pol, flags_file=flags_file)
        # Correct the visibilities by subtracting the average of the channels at each timestamp
        #and the average of the timestamps at each channel.
        if correct == 'channels':
            corr_vis = correct_by_mean(visdata, axis="Channel")
            corr_vis = correct_by_mean(corr_vis, axis="Time")
        # Correct the background in each time bin by fitting a cubic spline.
        else:
            bg = onedbackground(smoothing=smooth, background_method=correct)
            #Knots will have to satisfy Schoenberg-Whitney conditions for spline else revert to straight mean of channels
            try:
                print("Fitting background using " + correct + " smoothing.")
                corr_vis = np.ma.masked_invalid(
                    np.ma.masked_array(
                        [data - bg.getbackground(data) for data in visdata],
                        mask=visdata.mask,
                        fill_value=0.0))
                #Fill masked values with zero (these will not contribute to the average - and deals with nans returned from the spline fit creeping into the average)
                removed_dumps = np.all(corr_vis.mask, axis=1)
                print(np.sum(removed_dumps), "out of", len(removed_dumps),
                      "dumps have been rejected during fitting.")
            except ValueError:
                print(
                    "Background fitting failed- using mean deviation instead.")
                corr_vis = correct_by_mean(visdata, axis="Channel")
                corr_vis = correct_by_mean(corr_vis, axis="Time")

        #Get the number of dumps to average
        dumpav = max(1, int(np.round(timeav * 60.0 / h5data.dump_period)))
        if dumpav > len(h5data.timestamps):
            dumpav = 1
            print(
                "Time averaging interval of %4.1fmin is longer than the observation length. No time averaging will be applied."
                % (timeav))
            timeav = dumpav * (h5data.dump_period / 60.0)
        print("Averaging time to %3d x %4.1fmin (%d dump) intervals." %
              (len(h5data.timestamps) // dumpav, timeav, dumpav))

        #Get the number of channels to average
        chanav = max(1, int(np.round(freqav * 1e6 / h5data.channel_width)))
        if chanav > len(h5data.channel_freqs):
            chanav = 1
            print(
                "Frequency averaging interval of %4.1fMHz is wider than available bandwidth. No frequency averaging will be applied."
                % (freqav))
            freqav = h5data.channel_width / 1e6
        print("Averaging frequency to %d x %4.1fMHz intervals." %
              (len(h5data.channel_freqs) // chanav, freqav))

        #Average the data over all time in chanav channels
        av_visdata = averager.average_visibilities(visdata.data,
                                                   weightdata,
                                                   visdata.mask,
                                                   h5data.timestamps,
                                                   h5data.channel_freqs,
                                                   timeav=len(
                                                       h5data.timestamps),
                                                   chanav=chanav)

        #Average the background subtracted data in dumpav times and chanav channels
        av_corr_vis = averager.average_visibilities(corr_vis.filled(),
                                                    weightdata,
                                                    corr_vis.mask,
                                                    h5data.timestamps,
                                                    h5data.channel_freqs,
                                                    timeav=dumpav,
                                                    chanav=chanav)

        #Get the averaged weights and channel frequencies
        av_weightdata = av_corr_vis[1]
        av_channel_freqs = av_corr_vis[4]

        #Make a masked array out of the averaged visdata
        av_visdata = np.ma.masked_array(np.squeeze(av_visdata[0]),
                                        mask=np.squeeze(av_visdata[2]))

        #Make a masked array out of the averaged background subtracted data
        av_corr_vis = np.ma.masked_array(av_corr_vis[0], mask=av_corr_vis[2])

        #get weighted standard deviation of background subtracted data
        corr_vis_mean, corr_vis_std = weighted_avg_and_std(av_corr_vis,
                                                           av_weightdata,
                                                           axis=0)

        obs_duration = np.str(
            np.round((h5data.end_time.to_mjd() - h5data.start_time.to_mjd()) *
                     24 * 60, 2)) + ' min'
        h5name = h5data.name.split('/')[-1]
        obs_details = h5name + ', start ' + h5data.start_time.to_string(
        ) + ', duration ' + obs_duration
        plot_std_results(corr_vis_std, np.squeeze(av_visdata),
                         av_channel_freqs, av_corr_vis.mask, baseline,
                         this_pol, freqav, timeav, obs_details, pdf)

    pdf.close()
Пример #11
0
#!/usr/bin/env python
import katdal
import sys
#
filename=sys.argv[1]
#
h5=katdal.open(filename,refant='m063')
#x=h5.sensor.get('CorrelatorBeamformer/auto-delay')
#print "number of autodelays",x.events[1]
#print "min",min(x),"max",max(x)

for nn in h5.catalogue.targets:
    print nn.name
print len(h5.scan_indices), "Scans"
print "antennas",h5.inputs
print "min elevation",h5.el.min()
print "max elevation",h5.el.max()
print "dump period",h5.dump_period
print "band",h5.channel_freqs.min()/1e9,"to",h5.channel_freqs.max()/1e9,"GHz"
print "start",h5.start_time.local(),"end",h5.end_time.local(),\
"duration",(h5.end_time-h5.start_time)/3600,"hrs"
channel_mask = opts.channel_mask  #

output_fields = '%(dataset)s, %(target)s, %(timestamp_ut)s, %(azimuth).7f, %(elevation).7f, ' \
                '%(delta_azimuth).7f, %(delta_azimuth_std).7f, %(delta_elevation).7f, %(delta_elevation_std).7f, ' \
                '%(data_unit)s, %(beam_height_I).7f, %(beam_height_I_std).7f, %(beam_width_I).7f, ' \
                '%(beam_width_I_std).7f, %(baseline_height_I).7f, %(baseline_height_I_std).7f, %(refined_I).7f, ' \
                '%(beam_height_HH).7f, %(beam_width_HH).7f, %(baseline_height_HH).7f, %(refined_HH).7f, ' \
                '%(beam_height_VV).7f, %(beam_width_VV).7f, %(baseline_height_VV).7f, %(refined_VV).7f, ' \
                '%(frequency).7f, %(flux).4f, %(temperature).2f, %(pressure).2f, %(humidity).2f, %(wind_speed).2f, ' \
                '%(wind_direction).2f , %(sun_az).7f, %(sun_el).7f, %(timestamp)i, %(valid_solutions)i \n'

output_field_names = [
    name.partition(')')[0] for name in output_fields[2:].split(', %(')
]

h5 = katdal.open(args[0])
ant_list = [ant.name for ant in h5.ants]  # Temp list for input options
if opts.ants is not None:
    ant_list = opts.ants.split(',')
if opts.ex_ants is not None:
    for ant in opts.ex_ants.split(','):
        if ant in ant_list:
            ant_list.remove(ant)
h5 = katdal.open(args[0], ref_ant=ant_list[0])
print("Using %s as the reference antenna " % (ant_list[0]))
h5.select(compscans='interferometric_pointing', ants=ant_list)

h5.antlist = [a.name for a in h5.ants]
h5.bls_lookup = calprocs.get_bls_lookup(h5.antlist, h5.corr_products)
if opts.outfilebase is None:
    outfilebase = "%s_%s" % (h5.name.split('/')[-1].split('.')[0],
Пример #13
0
(opts, args) = parser.parse_args()

if len(args) ==0:
    raise RuntimeError('Please specify an h5 file to load.')
    


# frequency channels to keep
start_freq_channel = int(opts.freq_keep.split(',')[0])
end_freq_channel = int(opts.freq_keep.split(',')[1])
start_freq_channel = 200
end_freq_channel = 800


h5 = katdal.open(args)
#h5 = katdal.open('1387000585.h5')
nice_filename =  args[0]+ '_phase_stability'
pp = PdfPages(nice_filename+'.pdf')
for pol in ('h','v'):
    h5.select(channels=slice(start_freq_channel,end_freq_channel),pol=pol,corrprods='cross',scans='track',dumps=slice(1,600)) 
    # loop over both polarisations
    if np.all(h5.sensor['DBE/auto-delay'] == '0') :
        print "Need to do fringe stopping "
        vis = fringe_stopping(h5)
    else:
        print "Fringe stopping done in the correlator"
        vis = h5.vis[:,:,:]

    flaglist = ~h5.flags()[:,:,:].any(axis=0).any(axis=-1)
    #flaglist[0:start_freq_channel] = False
Пример #14
0
    help=
    "The nuber of bins to use when evaluation the different seperations', default = '%default'"
)
parser.add_option(
    "--ant",
    default='ant4',
    help="The antenna to do the reduction for', default = '%default'")

(opts, args) = parser.parse_args()

if len(args) < 1:
    raise RuntimeError('Please specify the data file to reduce')
height = 1.0
bins = opts.bins

h5 = katdal.open(args[0])
#1392246099.h5

nice_filename = args[0].split('/')[-1] + '_' + opts.ant + '_jitter_test'
pp = PdfPages(nice_filename + '.pdf')

h5.select(scans='track',
          ants=opts.ant,
          channels=slice((h5.channels.shape[0]) // 4,
                         (h5.channels.shape[0] * 3) // 4))
pos1, pos2 = np.radians(
    (h5.az[:, 0],
     h5.el[:, 0])), np.array(h5.catalogue.targets[1].azel(h5.timestamps[:]))

hpbw = fwhm = np.degrees(1.02 * (c / h5.channel_freqs) / h5.ants[0].diameter)
pos1, pos2 = np.radians(
Пример #15
0
def MKContPipeline(files, outputdir, **kwargs):
    """MeerKAT Continuum pipeline.

    Parameters
    ----------
    files : list
        h5 filenames (note: support for multiple h5 files 
        i.e. ConcatenatedDataSet is not currently supported)
    outputdir : string
        Directory location to write output data, 
    scratchdir : string, optional
        The directory location of the aips disk
    parmFile : string, optional
        Overwrite the default imaging parameters using this parameter file.
    """
    if len(files) == 1:
        h5file = files[0]
    else:
        h5file = files
    ############### Initialize katfile object #########################
    OK = False
    # Open the h5 file as a katfile object
    try:
        #open katfile and perform selection according to kwargs
        katdal_ref_ant = kwargs.get('katdal_refant', '')
        katdal_retries = kwargs.get('katdal_retries', 2)
        katdal_timeout = kwargs.get('katdal_timeout', 300)
        katdata = katfile.open(h5file,
                               ref_ant=katdal_ref_ant,
                               timeout=katdal_timeout,
                               retries=katdal_retries)
        OK = True
    except Exception as exception:
        print(exception)
    if not OK:
        raise KATUnimageableError("Unable to read MVF data in " + str(h5file))

    # If we are doing polcal- search for the most recent delaycal observation
    if kwargs.get('polcal'):
        if kwargs.get('delaycal_mvf') is None:
            # Automatically determine delay_cal CBID
            delay_katdata = KATGetDelayCal(h5file,
                                           katdata,
                                           timeout=katdal_timeout,
                                           retries=katdal_retries)
        else:
            # Use the user supplied one
            delay_katdata = KATGetDelayCal(kwargs.get('delaycal_mvf'))
        kwargs["delay_katdata"] = delay_katdata

    # Die gracefully if we cannot write to the output area...
    if not os.path.exists(outputdir):
        print('Specified output directory: ' + outputdir + 'does not exist.')
        exit(-1)

    # Obit error logging
    err = OErr.OErr()

    #################### Initialize filenames #######################################################
    nameRoot = katdata.obs_params.get('capture_block_id',
                                      katdata.experiment_id)
    if type(nameRoot) == list:
        nameRoot = nameRoot[0]
    fileRoot = os.path.join(outputdir, nameRoot)  # root of file name
    logFile = fileRoot + ".log"  # Processing log file
    avgClass = ("UVAv")[0:6]  # Averaged data AIPS class
    manifestfile = outputdir + '/manifest.pickle'

    ############################# Initialize OBIT and AIPS ##########################################
    noScrat = []
    # Logging directly to logFile
    OErr.PInit(err, 2, logFile)
    EVLAAddOutFile(os.path.basename(logFile), 'project', 'Pipeline log file')
    if kwargs.get('reuse'):
        ObitSys = AIPSSetup.AIPSSetup(err,
                                      configfile=kwargs.get('configFile'),
                                      scratchdir=kwargs.get('scratchdir'),
                                      aipsdisk=kwargs.get('aipsdisk'),
                                      overwrite=False)
    else:
        ObitSys = AIPSSetup.AIPSSetup(err,
                                      configfile=kwargs.get('configFile'),
                                      scratchdir=kwargs.get('scratchdir'),
                                      aipsdisk=kwargs.get('aipsdisk'))

    # Get the set up AIPS environment.
    AIPS_ROOT = os.environ['AIPS_ROOT']
    AIPS_VERSION = os.environ['AIPS_VERSION']

    nThreads = 72
    user = OSystem.PGetAIPSuser()
    AIPS.userno = user
    disk = 1
    fitsdisk = 1
    nam = nameRoot[:10]
    clss = "Raw"
    seq = 1

    ############### Condition data #########################
    #Get calibrator models
    fluxcals = katpoint.Catalogue(
        open(FITSDir.FITSdisks[1] + "/PERLEY_BUTLER_2013.csv"))
    #Condition data (get bpcals, update names for aips conventions etc)
    KATh5Condition(katdata, fluxcals, err)

    ############################# Initialise Parameters ##########################################
    ####### Initialize parameters dictionary #####
    parms = KATInitContParms()
    parms['PolCal'] = kwargs.get('polcal')
    parms['XYtarg'] = kwargs.get('XYtarg')
    # Get default XYtarg if it is not set
    targs = [targ.name for targ in katdata.catalogue.targets]
    if parms['PolCal']:
        if parms['XYtarg'] is None:
            GOTTARG = False
            for targ in ['1934-638', '0408-65']:
                if targ in targs:
                    parms['XYtarg'] = targ
                    GOTTARG = True
                    break
            if not GOTTARG:
                raise RuntimeError(
                    'No default targets (1934-638, 0408-65) for XYFix. Cannot run in PolCal mode.'
                )
        else:
            if parms['XYtarg'] not in targs:
                raise RuntimeError(
                    'XYtarg target %s not in observation. Cannot run in PolCal mode.'
                    % (parms['XYtarg']))
    ####### User defined parameters ######
    if kwargs.get('parmFile'):
        print("parmFile", kwargs.get('parmFile'))
        exec(open(kwargs.get('parmFile')).read())
        EVLAAddOutFile(os.path.basename(kwargs.get('parmFile')), 'project',
                       'Pipeline input parameters')

    ###################### Data selection and static edits ############################################
    # Select data based on static imageable parameters
    KATh5Select(katdata, parms, err, **kwargs)

    # General AIPS data parameters at script level
    dataClass = ("UVDa")[0:6]  # AIPS class of raw uv data
    delayClass = "DELA"
    band = katdata.spectral_windows[0].product  #Correlator product
    project = os.path.basename(os.path.splitext(files[0])[0])[
        0:10]  # Project name (12 char or less, used as AIPS Name)
    outIClass = parms["outIClass"]  # image AIPS class
    debug = parms["debug"]
    check = parms["check"]

    ####################### Import data into AIPS #####################################################
    # Reuse or nay?
    sw = katdata.spectral_windows[katdata.spw]
    # Pick up static flags
    if sw.band == 'L':
        sflags = FetchObject(ObitTalkUtil.FITSDir.FITSdisks[fitsdisk] +
                             'maskred.pickle')
        if kwargs.get('flag', None):
            mess = 'Using static RFI mask in file %s for L-band' % (
                ObitTalkUtil.FITSDir.FITSdisks[fitsdisk] + 'maskred.pickle', )
            printMess(mess, logFile)
    elif sw.band == 'UHF':
        sflags = FetchObject(ObitTalkUtil.FITSDir.FITSdisks[fitsdisk] +
                             'maskredUHF.pickle')
        if kwargs.get('flag', None):
            mess = 'Using static RFI mask in file %s for UHF-band' % (
                ObitTalkUtil.FITSDir.FITSdisks[fitsdisk] +
                'maskredUHF.pickle', )
            printMess(mess, logFile)
    else:
        sflags = np.zeros(sw.num_chans, dtype=np.bool)
    sflags = sflags[katdata.channels]
    # Construct a template uvfits file from master template
    mastertemplate = ObitTalkUtil.FITSDir.FITSdisks[
        fitsdisk] + 'MKATTemplate.uvtab.gz'
    outtemplate = nam + '.uvtemp'
    if kwargs.get('reuse'):
        uv = UV.newPAUV("AIPS UV DATA", EVLAAIPSName(project), dataClass, disk,
                        seq, True, err)
        obsdata = KATH5toAIPS.GetKATMeta(katdata, err)
        # Extract AIPS parameters of the uv data to the metadata
        obsdata["Aproject"] = uv.Aname
        obsdata["Aclass"] = uv.Aclass
        obsdata["Aseq"] = uv.Aseq
        obsdata["Adisk"] = disk
        obsdata["calInt"] = katdata.dump_period
        obsdata["fitsdisk"] = fitsdisk
        # TODO: Check if the input data has been Hanned.
        doneHann = True
    else:
        mess = '\nLoading UV data with CBID: %s' % (
            katdata.obs_params['capture_block_id'], )
        printMess(mess, logFile)
        KATH5toAIPS.MakeTemplate(mastertemplate, outtemplate, katdata)
        uv = OTObit.uvlod(outtemplate, 0, EVLAAIPSName(project), clss, disk,
                          seq, err)
        obsdata = KATH5toAIPS.KAT2AIPS(katdata,
                                       uv,
                                       disk,
                                       fitsdisk,
                                       err,
                                       calInt=katdata.dump_period,
                                       static=sflags,
                                       **kwargs)
        MakeIFs.UVMakeIF(uv, 8, err, solInt=katdata.dump_period)
        os.remove(outtemplate)

    if parms["PolCal"]:
        mess = '\nLoading delay calibration with CBID: %s' % (
            delay_katdata.obs_params['capture_block_id'], )
        printMess(mess, logFile)
        # Load the delay cal observation
        KATH5toAIPS.MakeTemplate(mastertemplate, outtemplate, katdata)
        delay_uv = OTObit.uvlod(outtemplate, 0, EVLAAIPSName(project),
                                delayClass, disk, seq, err)
        KATH5toAIPS.KAT2AIPS(delay_katdata,
                             delay_uv,
                             disk,
                             fitsdisk,
                             err,
                             calInt=katdata.dump_period,
                             static=sflags,
                             flag=False)
        MakeIFs.UVMakeIF(delay_uv, 8, err, solInt=katdata.dump_period)
        os.remove(outtemplate)

    # Print the uv data header to screen.
    uv.Header(err)
    ############################# Set Project Processing parameters ###################################
    # Parameters derived from obsdata and katdata
    KATGetObsParms(obsdata, katdata, parms, logFile)

    ###### Initialise target parameters #####
    KATInitTargParms(katdata, parms, err)

    # Load the outputs pickle jar
    EVLAFetchOutFiles()

    OSystem.PAllowThreads(nThreads)  # Allow threads in Obit/oython
    retCode = 0
    doBand = -1
    BPVer = 0
    maxgap = max(parms["CalAvgTime"], 160. * katdata.dump_period) / 60.
    ################### Start processing ###############################################################

    mess = "Start project "+parms["project"]+" AIPS user no. "+str(AIPS.userno)+\
           ", KAT7 configuration "+parms["KAT7Cfg"]
    printMess(mess, logFile)
    if debug:
        pydoc.ttypager = pydoc.plainpager  # don't page task input displays
        mess = "Using Debug mode "
        printMess(mess, logFile)
    if check:
        mess = "Only checking script"
        printMess(mess, logFile)

    # Log parameters
    printMess("Parameter settings", logFile)
    for p in parms:
        mess = "  " + p + ": " + str(parms[p])
        printMess(mess, logFile)
    clist = []
    for DCal in parms["DCals"]:
        if DCal["Source"] not in clist:
            clist.append(DCal["Source"])
    for PCal in parms["PCals"]:
        if PCal["Source"] not in clist:
            clist.append(PCal["Source"])
    for ACal in parms["ACals"]:
        if ACal["Source"] not in clist:
            clist.append(ACal["Source"])
    if kwargs.get('targets') is not None:
        targets = [
            targ.name for targ in katdata.catalogue
            if (targ.name not in clist) and (
                targ.name in kwargs.get('targets').split(','))
        ]
    else:
        targets = [
            targ.name for targ in katdata.catalogue if (targ.name not in clist)
        ]

    refAnt = kwargs.get('refant')
    if refAnt is not None:
        try:
            SaveObject(obsdata['antLookup'][refAnt],
                       fileRoot + ".refAnt.pickle", True)
        except:
            mess = "Select reference antenna " + refAnt + " not in antenna table."
            printMess(mess, logFile)
            print(mess)
    refAnt = FetchObject(fileRoot + ".refAnt.pickle")

    # Save parameters to pickle jar, manifest
    ParmsPicklefile = fileRoot + ".Parms.pickle"  # Where results saved
    SaveObject(parms, ParmsPicklefile, True)
    EVLAAddOutFile(os.path.basename(ParmsPicklefile), 'project',
                   'Processing parameters used')
    loadClass = dataClass

    # Hanning - only if not reusing
    doneHann = False
    if not kwargs.get('reuse'):
        if parms["doHann"]:
            uv = KATHann(uv, EVLAAIPSName(project), dataClass, disk, seq, err, \
                      doDescm=parms["doDescm"], flagVer=-1, logfile=logFile, zapin=True, check=check, debug=debug)
            doneHann = True

    if parms["PolCal"] and parms["doHann"]:
        mess = "Hanning delay calibration scan"
        printMess(mess, logFile)
        delay_uv = KATHann(delay_uv, EVLAAIPSName(project), delayClass, disk, seq + 1, err, \
                        doDescm=parms["doDescm"], flagVer=-1, logfile=logFile, zapin=True, check=check, debug=debug)

    if doneHann:
        # Halve channels after hanning.
        parms["selChan"] = int(parms["selChan"] / 2)
        parms["BChDrop"] = int(parms["BChDrop"] / 2)
        parms["EChDrop"] = int(parms["EChDrop"] / 2)
        if uv == None and not check:
            raise RuntimeError("Cannot Hann data ")

    # Clear any old calibration/editing
    if parms["doClearTab"] or kwargs.get('reuse'):
        mess = "Clear previous calibration"
        printMess(mess, logFile)
        EVLAClearCal(uv,
                     err,
                     doGain=parms["doClearGain"],
                     doFlag=parms["doClearFlag"],
                     doBP=parms["doClearBP"],
                     check=check)
        OErr.printErrMsg(err, "Error resetting calibration")

    # Copy FG 1 to FG 2
    if parms["doCopyFG"]:
        mess = "Copy FG 1 to FG 2"
        printMess(mess, logFile)
        retCode = KATCopyFG(uv, err, logfile=logFile, check=check, debug=debug)
        if retCode != 0:
            raise RuntimeError("Error Copying FG table")

    # Flag antennas shadowed by others?
    if parms["doShad"]:
        retCode = EVLAShadow (uv, err, shadBl=parms["shadBl"], \
                              logfile=logFile, check=check, debug=debug)
        if retCode != 0:
            raise RuntimeError("Error Shadow flagging data")

    # Median window time editing, for RFI impulsive in time
    if parms["doMednTD1"]:
        mess = "Median window time editing, for RFI impulsive in time:"
        printMess(mess, logFile)
        retCode = EVLAMedianFlag (uv, clist, err, noScrat=noScrat, nThreads=nThreads, \
                                  avgTime=parms["mednAvgTime"], avgFreq=parms["mednAvgFreq"],  chAvg= parms["mednChAvg"], \
                                  timeWind=parms["mednTimeWind"],flagVer=2, flagTab=2,flagSig=parms["mednSigma"], \
                                  logfile=logFile, check=check, debug=False)
        if retCode != 0:
            raise RuntimeError("Error in MednFlag")

    # Median window frequency editing, for RFI impulsive in frequency
    if parms["doFD1"]:
        mess = "Median window frequency editing, for RFI impulsive in frequency:"
        printMess(mess, logFile)
        retCode = EVLAAutoFlag (uv, clist, err, flagVer=2, flagTab=2, doCalib=-1, doBand=-1,   \
                                timeAvg=parms["FD1TimeAvg"], \
                                doFD=True, FDmaxAmp=1.0e20, FDmaxV=1.0e20, FDwidMW=parms["FD1widMW"],  \
                                FDmaxRMS=[1.0e20,0.1], FDmaxRes=parms["FD1maxRes"],  \
                                FDmaxResBL= parms["FD1maxRes"],  FDbaseSel=parms["FD1baseSel"],\
                                nThreads=nThreads, logfile=logFile, check=check, debug=debug)
        if retCode != 0:
            raise RuntimeError("Error in AutoFlag")

    # Parallactic angle correction?
    if parms["doPACor"]:
        retCode = EVLAPACor(uv, err, \
                                logfile=logFile, check=check, debug=debug)
        if retCode != 0:
            raise RuntimeError("Error in Parallactic angle correction")

    # Need to find a reference antenna?  See if we have saved it?
    if (parms["refAnt"] <= 0):
        refAnt = FetchObject(fileRoot + ".refAnt.pickle")
        if refAnt:
            parms["refAnt"] = refAnt

    # Use bandpass calibrator and center half of each spectrum
    if parms["refAnt"] <= 0:
        mess = "Find best reference antenna: run Calib on BP Cal(s) "
        printMess(mess, logFile)
        parms["refAnt"] = EVLAGetRefAnt(uv, parms["BPCals"], err, flagVer=0, \
                                        solInt=parms["bpsolint1"], nThreads=nThreads, \
                                        logfile=logFile, check=check, debug=debug)
        if err.isErr:
            raise RuntimeError("Error finding reference antenna")
        if parms["refAnts"][0] <= 0:
            parms["refAnts"][0] = parms["refAnt"]
        mess = "Picked reference antenna " + str(parms["refAnt"])
        printMess(mess, logFile)
        # Save it
        ParmsPicklefile = fileRoot + ".Parms.pickle"  # Where results saved
        SaveObject(parms, ParmsPicklefile, True)
        refAntPicklefile = fileRoot + ".refAnt.pickle"  # Where results saved
        SaveObject(parms["refAnt"], refAntPicklefile, True)

    # Plot Raw, edited data?
    if parms["doRawSpecPlot"] and parms["plotSource"]:
        mess = "Raw Spectral plot for: " + ' '.join(parms["BPCal"])
        printMess(mess, logFile)
        plotFile = fileRoot + "_RawSpec.ps"
        retCode = EVLASpectrum(uv, parms["BPCal"], parms["plotTime"], maxgap, plotFile, parms["refAnt"], err, \
                               Stokes=["RR","LL"], doband=-1,          \
                               check=check, debug=debug, logfile=logFile )
        if retCode != 0:
            raise RuntimeError("Error in Plotting spectrum")
        EVLAAddOutFile(plotFile, 'project', 'Pipeline log file')

    if parms["PolCal"]:
        mess = "XYphase bandpass calibration"
        printMess(mess, logFile)
        retCode = KATXPhase(delay_uv,
                            uv,
                            err,
                            logfile=logFile,
                            check=check,
                            debug=debug,
                            doCalib=-1,
                            flagVer=0,
                            doBand=-1,
                            refAnt=parms['refAnt'])
        doBand = 1
        BPVer += 1
        if retCode != 0:
            raise RuntimeError("Error in Xphase calibration")

    # delay calibration
    if parms["doDelayCal"] and parms["DCals"] and not check:
        plotFile = fileRoot + "_DelayCal.ps"
        retCode = EVLADelayCal(uv, parms["DCals"], err,  \
                               BChan=parms["delayBChan"], EChan=parms["delayEChan"], \
                               doCalib=-1, flagVer=0, doBand=doBand, BPVer=BPVer, \
                               solInt=parms["delaySolInt"], smoTime=parms["delaySmoo"],  \
                               refAnts=[parms["refAnt"]], doTwo=parms["doTwo"],
                               doZeroPhs=parms["delayZeroPhs"], \
                               doAvgIF=parms["delayAvgIF"], doAvgPol=parms["delayAvgPol"], \
                               doPlot=parms["doSNPlot"], plotFile=plotFile, \
                               nThreads=nThreads, noScrat=noScrat, \
                               logfile=logFile, check=check, debug=debug)
        if retCode != 0:
            raise RuntimeError("Error in delay calibration")

        # Plot corrected data?
        if parms["doSpecPlot"] and parms["plotSource"]:
            plotFile = fileRoot + "_DelaySpec.ps"
            retCode = EVLASpectrum(uv, parms["BPCal"], parms["plotTime"], maxgap, \
                                   plotFile, parms["refAnt"], err, \
                                   Stokes=["RR","LL"], doband=doBand,          \
                                   check=check, debug=debug, logfile=logFile )
            if retCode != 0:
                raise RuntimeError("Error in Plotting spectrum")

    # Bandpass calibration
    if parms["doBPCal"] and parms["BPCals"]:
        retCode = KATBPCal(uv, parms["BPCals"], err, doBand=doBand, BPVer=BPVer, newBPVer=0,
                            noScrat=noScrat, solInt1=parms["bpsolint1"], \
                            solInt2=parms["bpsolint2"], solMode=parms["bpsolMode"], \
                            BChan1=parms["bpBChan1"], EChan1=parms["bpEChan1"], \
                            BChan2=parms["bpBChan2"], EChan2=parms["bpEChan2"], ChWid2=parms["bpChWid2"], \
                            doCenter1=parms["bpDoCenter1"], refAnt=parms["refAnt"], \
                            UVRange=parms["bpUVRange"], doCalib=2, gainUse=0, flagVer=0, doPlot=False, \
                            nThreads=nThreads, logfile=logFile, check=check, debug=debug)
        if retCode != 0:
            raise RuntimeError("Error in Bandpass calibration")

        # Plot corrected data?
        if parms["doSpecPlot"] and parms["plotSource"]:
            plotFile = fileRoot + "_BPSpec.ps"
            retCode = EVLASpectrum(uv, parms["BPCal"], parms["plotTime"], maxgap, plotFile, \
                                   parms["refAnt"], err, Stokes=["RR","LL"], doband=1,          \
                                   check=check, debug=debug, logfile=logFile )
            if retCode != 0:
                raise RuntimeError("Error in Plotting spectrum")

    # Amp & phase Calibrate
    if parms["doAmpPhaseCal"]:
        plotFile = fileRoot + "_APCal.ps"
        retCode = KATCalAP (uv, [], parms["ACals"], err, PCals=parms["PCals"],
                             doCalib=2, doBand=1, BPVer=0, flagVer=0, \
                             BChan=parms["ampBChan"], EChan=parms["ampEChan"], \
                             solInt=parms["solInt"], solSmo=parms["solSmo"], ampScalar=parms["ampScalar"], \
                             doAmpEdit=parms["doAmpEdit"], ampSigma=parms["ampSigma"], \
                             ampEditFG=parms["ampEditFG"], avgPol=parms["PolCal"], \
                             doPlot=parms["doSNPlot"], plotFile=plotFile,  refAnt=parms["refAnt"], \
                             nThreads=nThreads, noScrat=noScrat, logfile=logFile, check=check, debug=debug)

        if retCode != 0:
            raise RuntimeError("Error calibrating")

    # More editing
    if parms["doAutoFlag"]:
        mess = "Post calibration editing:"
        printMess(mess, logFile)
        # if going to redo then only calibrators
        if parms["doRecal"]:
            # Only calibrators
            clist = []
            for DCal in parms["DCals"]:
                if DCal["Source"] not in clist:
                    clist.append(DCal["Source"])
            for PCal in parms["PCals"]:
                if PCal["Source"] not in clist:
                    clist.append(PCal["Source"])
            for ACal in parms["ACals"]:
                if ACal["Source"] not in clist:
                    clist.append(ACal["Source"])
        else:
            clist = []

        retCode = EVLAAutoFlag (uv, clist, err, flagVer=0, flagTab =2, \
                                doCalib=2, gainUse=0, doBand=1, BPVer=BPVer,  \
                                IClip=parms["IClip"], minAmp=parms["minAmp"], timeAvg=parms["timeAvg"], \
                                doFD=parms["doFirstAFFD"], FDmaxAmp=parms["FDmaxAmp"], FDmaxV=parms["FDmaxV"], \
                                FDwidMW=parms["FDwidMW"], FDmaxRMS=parms["FDmaxRMS"], \
                                FDmaxRes=parms["FDmaxRes"],  FDmaxResBL=parms["FDmaxResBL"], \
                                FDbaseSel=parms["FDbaseSel"], \
                                nThreads=nThreads, logfile=logFile, check=check, debug=debug)
        if retCode != 0:
            raise RuntimeError("Error in AutoFlag")

    # Redo the calibration using new flagging?
    if parms["doBPCal2"] == None:
        parms["doBPCal2"] = parms["doBPCal"]
    if parms["doDelayCal2"] == None:
        parms["doDelayCal2"] = parms["doDelayCal2"]
    if parms["doAmpPhaseCal2"] == None:
        parms["doAmpPhaseCal2"] = parms["doAmpPhaseCal"]
    if parms["doAutoFlag2"] == None:
        parms["doAutoFlagCal2"] = parms["doAutoFlag"]
    if parms["doRecal"]:
        mess = "Redo calibration:"
        printMess(mess, logFile)
        EVLAClearCal(uv,
                     err,
                     doGain=True,
                     doFlag=False,
                     doBP=True,
                     check=check,
                     logfile=logFile)
        OErr.printErrMsg(err, "Error resetting calibration")
        BPVer = 0
        # Parallactic angle correction?
        if parms["doPACor"]:
            retCode = EVLAPACor(uv, err, \
                                logfile=logFile, check=check, debug=debug)
            if retCode != 0:
                raise RuntimeError("Error in Parallactic angle correction")

        # Run MKXPhase on delaycal data and attach BP table to UV data
        if parms["PolCal"]:
            mess = "XYphase bandpass calibration"
            printMess(mess, logFile)
            retCode = KATXPhase(delay_uv,
                                uv,
                                err,
                                logfile=logFile,
                                check=check,
                                debug=debug,
                                doCalib=-1,
                                flagVer=0,
                                doBand=-1,
                                refAnt=parms['refAnt'])
            BPVer += 1
        if retCode != 0:
            raise RuntimeError("Error in Xphase calibration")

        # Delay recalibration
        if parms["doDelayCal2"] and parms["DCals"] and not check:
            plotFile = fileRoot + "_DelayCal2.ps"
            retCode = EVLADelayCal(uv, parms["DCals"], err, \
                                   BChan=parms["delayBChan"], EChan=parms["delayEChan"], \
                                   doCalib=-1, flagVer=0, doBand=doBand, BPVer=BPVer, \
                                   solInt=parms["delaySolInt"], smoTime=parms["delaySmoo"],  \
                                   refAnts=[parms["refAnt"]], doTwo=parms["doTwo"], \
                                   doZeroPhs=parms["delayZeroPhs"], \
                                   doAvgIF=parms["delayAvgIF"], doAvgPol=parms["delayAvgPol"], \
                                   doPlot=parms["doSNPlot"], plotFile=plotFile, \
                                   nThreads=nThreads, noScrat=noScrat, \
                                   logfile=logFile, check=check, debug=debug)
            if retCode != 0:
                raise RuntimeError("Error in delay calibration")

            # Plot corrected data?
            if parms["doSpecPlot"] and parms["plotSource"]:
                plotFile = fileRoot + "_DelaySpec2.ps"
                retCode = EVLASpectrum(uv, parms["BPCal"], parms["plotTime"], maxgap, plotFile, parms["refAnt"], err, \
                                       Stokes=["RR","LL"], doband=doband,          \
                                       check=check, debug=debug, logfile=logFile )
                if retCode != 0:
                    raise RuntimeError("Error in Plotting spectrum")

        # Bandpass calibration
        if parms["doBPCal2"] and parms["BPCals"]:
            retCode = KATBPCal(uv, parms["BPCals"], err, doBand=doBand, BPVer=BPVer, newBPVer=0, \
                            noScrat=noScrat, solInt1=parms["bpsolint1"], \
                            solInt2=parms["bpsolint2"], solMode=parms["bpsolMode"], \
                            BChan1=parms["bpBChan1"], EChan1=parms["bpEChan1"], \
                            BChan2=parms["bpBChan2"], EChan2=parms["bpEChan2"], ChWid2=parms["bpChWid2"], \
                            doCenter1=parms["bpDoCenter1"], refAnt=parms["refAnt"], \
                            UVRange=parms["bpUVRange"], doCalib=2, gainUse=0, flagVer=0, doPlot=False, \
                            nThreads=nThreads, logfile=logFile, check=check, debug=debug)
            if retCode != 0:
                raise RuntimeError("Error in Bandpass calibration")

            # Plot corrected data?
            if parms["doSpecPlot"] and parms["plotSource"]:
                plotFile = fileRoot + "_BPSpec2.ps"
                retCode = EVLASpectrum(uv, parms["BPCal"], parms["plotTime"], maxgap, plotFile, parms["refAnt"], err, \
                                   Stokes=["RR","LL"], doband=1,          \
                                   check=check, debug=debug, logfile=logFile )
            if retCode != 0:
                raise RuntimeError("Error in Plotting spectrum")

        # Amp & phase Recalibrate
        if parms["doAmpPhaseCal2"]:
            plotFile = fileRoot + "_APCal2.ps"
            retCode = KATCalAP (uv, [], parms["ACals"], err, PCals=parms["PCals"], \
                                 doCalib=2, doBand=1, BPVer=0, flagVer=0, \
                                 BChan=parms["ampBChan"], EChan=parms["ampEChan"], \
                                 solInt=parms["solInt"], solSmo=parms["solSmo"], ampScalar=parms["ampScalar"], \
                                 doAmpEdit=True, ampSigma=parms["ampSigma"], \
                                 ampEditFG=parms["ampEditFG"], avgPol=parms["PolCal"], \
                                 doPlot=parms["doSNPlot"], plotFile=plotFile, refAnt=parms["refAnt"], \
                                 noScrat=noScrat, nThreads=nThreads, logfile=logFile, check=check, debug=debug)
            if retCode != 0:
                raise RuntimeError("Error calibrating")

        # More editing
        if parms["doAutoFlag2"]:
            mess = "Post recalibration editing:"
            printMess(mess, logFile)
            retCode = EVLAAutoFlag (uv, [], err, flagVer=0, flagTab=2, \
                                    doCalib=2, gainUse=0, doBand=1, BPVer=0,  \
                                    IClip=parms["IClip"], minAmp=parms["minAmp"], timeAvg=parms["timeAvg"], \
                                    doFD=parms["doSecAFFD"], FDmaxAmp=parms["FDmaxAmp"], FDmaxV=parms["FDmaxV"], \
                                    FDwidMW=parms["FDwidMW"], FDmaxRMS=parms["FDmaxRMS"], \
                                    FDmaxRes=parms["FDmaxRes"],  FDmaxResBL= parms["FDmaxResBL"], \
                                    FDbaseSel=parms["FDbaseSel"], \
                                    nThreads=nThreads, logfile=logFile, check=check, debug=debug)
            if retCode != 0:
                raise RuntimeError("Error in AutoFlag")
    # end recal
    # Calibrate and average data
    # Overwrite avgStokes from command line
    if kwargs.get('halfstokes'):
        parms["avgStokes"] = 'HALF'
    if parms["doCalAvg"] == 'Splat':
        retCode = KATCalAvg (uv, avgClass, parms["seq"], parms["CalAvgTime"], err, \
                              flagVer=2, doCalib=2, gainUse=0, doBand=1, BPVer=0, doPol=False, \
                              avgFreq=parms["avgFreq"], chAvg=parms["chAvg"], Stokes=parms["avgStokes"], \
                              BChan=1, EChan=parms["selChan"] - 1, doAuto=parms["doAuto"], \
                              BIF=parms["CABIF"], EIF=parms["CAEIF"], Compress=parms["Compress"], \
                              nThreads=nThreads, logfile=logFile, check=check, debug=debug)
        if retCode != 0:
            raise RuntimeError("Error in CalAvg")
    elif parms["doCalAvg"] == 'BL':
        retCode = KATBLCalAvg (uv, avgClass, parms["seq"], err, \
                              flagVer=2, doCalib=2, gainUse=0, doBand=1, BPVer=0, doPol=False, \
                              avgFreq=parms["avgFreq"], chAvg=parms["chAvg"], FOV=parms['FOV'], \
                              maxInt=min(parms["solPInt"],parms["solAInt"]), Stokes=parms["avgStokes"], \
                              BChan=1, EChan=parms["selChan"] - 1, timeAvg=parms["CalAvgTime"], \
                              BIF=parms["CABIF"], EIF=parms["CAEIF"], Compress=parms["Compress"], \
                              logfile=logFile, check=check, debug=debug)
        if retCode != 0:
            raise RuntimeError("Error in BLCalAvg")

    if parms["doSaveTab"]:
        filename = project + ".CalTab.uvtab"
        _ = EVLAUVFITSTab(uv, filename, 0, err, logfile=logFile)

    #Zap unaveraged data if requested
    if kwargs.get('zapraw'):
        uv.Zap(err)

    # Get calibrated/averaged data
    if not check:
        uv = UV.newPAUV("AIPS UV DATA", EVLAAIPSName(project), avgClass[0:6], \
                        disk, parms["seq"], True, err)
        if err.isErr:
            OErr.printErrMsg(err, "Error creating cal/avg AIPS data")

    plotFile = fileRoot + "_Spec.ps"
    retCode = EVLASpectrum(uv, parms["BPCal"], parms["plotTime"], maxgap, \
                               plotFile, parms["refAnt"], err, \
                               Stokes=["I"], doband=-1, docalib=-1,      \
                               check=check, debug=debug, logfile=logFile )
    if retCode != 0:
        raise RuntimeError("Error in Plotting spectrum")

    # KATUVFITS(uv, 'preimage.uvfits', 0, err, exclude=["AIPS HI", "AIPS SL", "AIPS PL"],
    # include=["AIPS AN", "AIPS FQ"], compress=parms["Compress"], logfile=logFile)
    KATUVFITab(uv, project + '.uvtab', 0, err)
    #Gzip the data?
    if kwargs.get('gzip'):
        os.system('pigz -p %d %s' % (nThreads, project + '.uvtab'))
        os.system('rm -f %s' % (project + '.uvtab'))
Пример #16
0
def main():
    tag_to_intent = {
        'gaincal': 'CALIBRATE_PHASE,CALIBRATE_AMPLI',
        'bpcal': 'CALIBRATE_BANDPASS,CALIBRATE_FLUX',
        'target': 'TARGET'
    }

    usage = "%prog [options] <dataset> [<dataset2>]*"
    description = "Convert MVF dataset(s) to CASA MeasurementSet. The datasets may " \
                  "be local filenames or archive URLs (including access tokens). " \
                  "If there are multiple datasets they will be concatenated via " \
                  "katdal before conversion."
    parser = optparse.OptionParser(usage=usage, description=description)
    parser.add_option("-o",
                      "--output-ms",
                      default=None,
                      help="Name of output MeasurementSet")
    parser.add_option(
        "-c",
        "--circular",
        action="store_true",
        default=False,
        help="Produce quad circular polarisation. (RR, RL, LR, LL) "
        "*** Currently just relabels the linear pols ****")
    parser.add_option(
        "-r",
        "--ref-ant",
        help="Override the reference antenna used to pick targets "
        "and scans (default is the 'array' antenna in MVFv4 "
        "and the first antenna in older formats)")
    parser.add_option("-t",
                      "--tar",
                      action="store_true",
                      default=False,
                      help="Tar-ball the MS")
    parser.add_option(
        "-f",
        "--full_pol",
        action="store_true",
        default=False,
        help="Produce a full polarisation MS in CASA canonical order "
        "(HH, HV, VH, VV). Default is to produce HH,VV only.")
    parser.add_option("-v",
                      "--verbose",
                      action="store_true",
                      default=False,
                      help="More verbose progress information")
    parser.add_option("-w",
                      "--stop-w",
                      action="store_true",
                      default=False,
                      help="Use W term to stop fringes for each baseline")
    parser.add_option("-p",
                      "--pols-to-use",
                      default=None,
                      help="Select polarisation products to include in MS as "
                      "comma-separated list (from: HH, HV, VH, VV). "
                      "Default is all available from (HH, VV).")
    parser.add_option(
        "-u",
        "--uvfits",
        action="store_true",
        default=False,
        help="Print command to convert MS to miriad uvfits in casapy")
    parser.add_option("-a",
                      "--no-auto",
                      action="store_true",
                      default=False,
                      help="MeasurementSet will exclude autocorrelation data")
    parser.add_option(
        "-s",
        "--keep-spaces",
        action="store_true",
        default=False,
        help="Keep spaces in source names, default removes spaces")
    parser.add_option(
        "-C",
        "--channel-range",
        help="Range of frequency channels to keep (zero-based inclusive "
        "'first_chan,last_chan', default is all channels)")
    parser.add_option("-e",
                      "--elevation-range",
                      help="Flag elevations outside the range "
                      "'lowest_elevation,highest_elevation'")
    parser.add_option(
        "-m",
        "--model-data",
        action="store_true",
        default=False,
        help="Add MODEL_DATA and CORRECTED_DATA columns to the MS. "
        "MODEL_DATA initialised to unity amplitude zero phase, "
        "CORRECTED_DATA initialised to DATA.")
    flag_names = ', '.join(name for name in FLAG_NAMES
                           if not name.startswith('reserved'))
    parser.add_option("--flags",
                      default="all",
                      help="List of online flags to apply "
                      "(from " + flag_names + ") "
                      "default is all flags, '' will apply no flags)")
    parser.add_option("--dumptime",
                      type=float,
                      default=0.0,
                      help="Output time averaging interval in seconds, "
                      "default is no averaging")
    parser.add_option("--chanbin",
                      type=int,
                      default=0,
                      help="Bin width for channel averaging in channels, "
                      "default is no averaging")
    parser.add_option(
        "--flagav",
        action="store_true",
        default=False,
        help="If a single element in an averaging bin is flagged, "
        "flag the averaged bin")
    parser.add_option("--caltables",
                      action="store_true",
                      default=False,
                      help="Create calibration tables from gain solutions in "
                      "the dataset (if present)")
    parser.add_option("--quack",
                      type=int,
                      default=1,
                      metavar='N',
                      help="Discard the first N dumps "
                      "(which are frequently incomplete)")
    parser.add_option("--applycal",
                      default="",
                      help="List of calibration solutions to apply to data as "
                      "a string of comma-separated names, e.g. 'l1' or "
                      "'K,B,G'. Use 'default' for L1 + L2 and 'all' for "
                      "all available products.")
    (options, args) = parser.parse_args()

    # Loading is I/O-bound, so give more threads than CPUs
    dask.config.set(
        pool=multiprocessing.pool.ThreadPool(4 * multiprocessing.cpu_count()))

    if len(args) < 1:
        parser.print_help()
        raise RuntimeError(
            "Please provide one or more MVF dataset names as arguments")

    if options.elevation_range and len(options.elevation_range.split(',')) < 2:
        raise RuntimeError(
            "You have selected elevation flagging. Please provide elevation "
            "limits in the form 'lowest_elevation,highest_elevation'.")

    if len(args) > 1:
        print("Concatenating multiple datasets into single MS.")

    def antenna_indices(na, no_auto_corr):
        """Get default antenna1 and antenna2 arrays."""
        return np.triu_indices(na, 1 if no_auto_corr else 0)

    def corrprod_index(dataset):
        """The correlator product index (with -1 representing missing indices)."""
        corrprod_to_index = {
            tuple(cp): n
            for n, cp in enumerate(dataset.corr_products)
        }

        # ==========================================
        # Generate per-baseline antenna pairs and
        # correlator product indices
        # ==========================================

        def _cp_index(a1, a2, pol):
            """Create correlator product index from antenna pair and pol."""
            a1 = a1.name + pol[0].lower()
            a2 = a2.name + pol[1].lower()
            return corrprod_to_index.get((a1, a2), -1)

        # Generate baseline antenna pairs
        ant1_index, ant2_index = antenna_indices(len(dataset.ants),
                                                 options.no_auto)
        # Order as similarly to the input as possible, which gives better performance
        # in permute_baselines.
        bl_indices = list(zip(ant1_index, ant2_index))
        bl_indices.sort(key=lambda ants: _cp_index(dataset.ants[ants[
            0]], dataset.ants[ants[1]], pols_to_use[0]))
        # Undo the zip
        ant1_index[:] = [bl[0] for bl in bl_indices]
        ant2_index[:] = [bl[1] for bl in bl_indices]
        ant1 = [dataset.ants[a1] for a1 in ant1_index]
        ant2 = [dataset.ants[a2] for a2 in ant2_index]

        # Create actual correlator product index
        cp_index = [
            _cp_index(a1, a2, p) for a1, a2 in zip(ant1, ant2)
            for p in pols_to_use
        ]
        cp_index = np.array(cp_index, dtype=np.int32)

        CPInfo = namedtuple(
            "CPInfo", ["ant1_index", "ant2_index", "ant1", "ant2", "cp_index"])
        return CPInfo(ant1_index, ant2_index, ant1, ant2, cp_index)

    # Open dataset
    open_args = args[0] if len(args) == 1 else args
    # katdal can handle a list of datasets, which get virtually concatenated internally
    dataset = katdal.open(open_args,
                          ref_ant=options.ref_ant,
                          applycal=options.applycal)
    if dataset.applycal_products:
        print('The following calibration products will be applied:',
              ', '.join(dataset.applycal_products))
    else:
        print('No calibration products will be applied')

    # Get list of unique polarisation products in the dataset
    pols_in_dataset = np.unique([(cp[0][-1] + cp[1][-1]).upper()
                                 for cp in dataset.corr_products])

    # Which polarisation do we want to write into the MS
    # select all possible pols if full-pol selected, otherwise the selected polarisations via pols_to_use
    # otherwise finally select any of HH,VV present (the default).
    pols_to_use = ['HH', 'HV', 'VH', 'VV'] if (options.full_pol or options.circular) else \
        list(np.unique(options.pols_to_use.split(','))) if options.pols_to_use else \
        [pol for pol in ['HH', 'VV'] if pol in pols_in_dataset]

    # Check we have the chosen polarisations
    if np.any([pol not in pols_in_dataset for pol in pols_to_use]):
        raise RuntimeError(
            f"Selected polarisation(s): {', '.join(pols_to_use)} not available. "
            f"Available polarisation(s): {','.join(pols_in_dataset)}")

    # Set full_pol if this is selected via options.pols_to_use
    if set(pols_to_use) == {'HH', 'HV', 'VH', 'VV'} and not options.circular:
        options.full_pol = True

    # Extract one MS per spectral window in the dataset(s)
    for win in range(len(dataset.spectral_windows)):
        dataset.select(reset='T')

        centre_freq = dataset.spectral_windows[win].centre_freq
        print(
            f'Extract MS for spw {win}: centre frequency {int(centre_freq)} Hz'
        )

        # If no output MS directory name supplied, infer it from dataset(s)
        if options.output_ms is None:
            if len(dataset.spectral_windows) > 1:
                # Use frequency label to disambiguate multiple spectral windows
                ms_name = default_ms_name(args, centre_freq)
            else:
                ms_name = default_ms_name(args)
        else:
            ms_name = options.output_ms
        basename = os.path.splitext(ms_name)[0]

        # Discard first N dumps which are frequently incomplete
        dataset.select(spw=win,
                       scans='track',
                       flags=options.flags,
                       dumps=slice(options.quack, None))

        # The first step is to copy the blank template MS to our desired output
        # (making sure it's not already there)
        if os.path.exists(ms_name):
            raise RuntimeError(
                f"MS '{ms_name}' already exists - please remove it "
                "before running this script")

        print("Will create MS output in " + ms_name)

        # Instructions to flag by elevation if requested
        if options.elevation_range is not None:
            emin, emax = options.elevation_range.split(',')
            print(
                "\nThe MS can be flagged by elevation in casapy v3.4.0 or higher, with the command:"
            )
            print(
                f"      tflagdata(vis='{ms_name}', mode='elevation', lowerlimit={emin}, "
                f"upperlimit={emax}, action='apply')\n")

        # Instructions to create uvfits file if requested
        if options.uvfits:
            uv_name = basename + ".uvfits"
            print(
                "\nThe MS can be converted into a uvfits file in casapy, with the command:"
            )
            print(
                f"      exportuvfits(vis='{ms_name}', fitsfile='{uv_name}', datacolumn='data')\n"
            )

        if options.full_pol:
            print(
                "\n#### Producing a full polarisation MS (HH,HV,VH,VV) ####\n")
        else:
            print(
                f"\n#### Producing MS with {','.join(pols_to_use)} polarisation(s) ####\n"
            )

        # if fringe stopping is requested, check that it has not already been done in hardware
        if options.stop_w:
            print(
                "W term in UVW coordinates will be used to stop the fringes.")
            try:
                autodelay = [
                    int(ad) for ad in dataset.sensor['DBE/auto-delay']
                ]
                if all(autodelay):
                    print("Fringe-stopping already performed in hardware... "
                          "do you really want to stop the fringes here?")
            except KeyError:
                pass

        # Select frequency channel range
        if options.channel_range is not None:
            channel_range = [
                int(chan_str) for chan_str in options.channel_range.split(',')
            ]
            first_chan, last_chan = channel_range[0], channel_range[1]

            if (first_chan < 0) or (last_chan >= dataset.shape[1]):
                raise RuntimeError(
                    "Requested channel range outside data set boundaries. "
                    f"Set channels in the range [0,{dataset.shape[1] - 1}]")
            if first_chan > last_chan:
                raise RuntimeError(
                    f"First channel ({first_chan}) bigger than last channel "
                    f"({last_chan}) - did you mean it the other way around?")

            chan_range = slice(first_chan, last_chan + 1)
            print(f"\nChannel range {first_chan} through {last_chan}.")
            dataset.select(channels=chan_range)

        # Are we averaging?
        average_data = False

        # Determine the number of channels
        nchan = len(dataset.channels)

        # Work out channel average and frequency increment
        if options.chanbin > 1:
            average_data = True
            # Check how many channels we are dropping
            chan_remainder = nchan % options.chanbin
            avg_nchan = int(nchan / min(nchan, options.chanbin))
            print(
                f"Averaging {options.chanbin} channels, output ms will have {avg_nchan} channels."
            )
            if chan_remainder > 0:
                print(
                    f"The last {chan_remainder} channels in the data will be dropped "
                    f"during averaging ({options.chanbin} does not divide {nchan})."
                )
            chan_av = options.chanbin
            nchan = avg_nchan
        else:
            # No averaging in channel
            chan_av = 1

        # Get the frequency increment per averaged channel
        channel_freq_width = dataset.channel_width * chan_av

        # Work out dump average and dump increment
        # Is the desired time bin greater than the dump period?
        if options.dumptime > dataset.dump_period:
            average_data = True
            dump_av = int(np.round(options.dumptime / dataset.dump_period))
            time_av = dump_av * dataset.dump_period
            print(
                f"Averaging {dataset.dump_period} second dumps to {time_av} seconds."
            )
        else:
            # No averaging in time
            dump_av = 1
            time_av = dataset.dump_period

        # Print a message if extending flags to averaging bins.
        if average_data and options.flagav and options.flags != '':
            print("Extending flags to averaging bins.")

        # Optionally keep only cross-correlation products
        if options.no_auto:
            dataset.select(corrprods='cross')
            print("\nCross-correlations only.")

        print(
            f"\nUsing {dataset.ref_ant} as the reference antenna. All targets and scans "
            "will be based on this antenna.\n")
        # MS expects timestamps in MJD seconds
        start_time = dataset.start_time.to_mjd() * 24 * 60 * 60
        end_time = dataset.end_time.to_mjd() * 24 * 60 * 60
        # MVF version 1 and 2 datasets are KAT-7; the rest are MeerKAT
        telescope_name = 'KAT-7' if dataset.version[0] in '12' else 'MeerKAT'

        # increment scans sequentially in the ms
        scan_itr = 1
        print("\nIterating through scans in dataset(s)...\n")

        cp_info = corrprod_index(dataset)
        nbl = cp_info.ant1_index.size
        npol = len(pols_to_use)

        field_names, field_centers, field_times = [], [], []
        obs_modes = ['UNKNOWN']
        total_size = 0

        # Create the MeasurementSet
        table_desc, dminfo = ms_extra.kat_ms_desc_and_dminfo(
            nbl=nbl, nchan=nchan, ncorr=npol, model_data=options.model_data)
        ms_extra.create_ms(ms_name, table_desc, dminfo)

        ms_dict = {}
        ms_dict['ANTENNA'] = ms_extra.populate_antenna_dict(
            [ant.name for ant in dataset.ants],
            [ant.position_ecef
             for ant in dataset.ants], [ant.diameter for ant in dataset.ants])
        ms_dict['FEED'] = ms_extra.populate_feed_dict(len(dataset.ants),
                                                      num_receptors_per_feed=2)
        ms_dict['DATA_DESCRIPTION'] = ms_extra.populate_data_description_dict()
        ms_dict['POLARIZATION'] = ms_extra.populate_polarization_dict(
            ms_pols=pols_to_use, circular=options.circular)
        ms_dict['OBSERVATION'] = ms_extra.populate_observation_dict(
            start_time, end_time, telescope_name, dataset.observer,
            dataset.experiment_id)

        # before resetting ms_dict, copy subset to caltable dictionary
        if options.caltables:
            caltable_dict = {}
            caltable_dict['ANTENNA'] = ms_dict['ANTENNA']
            caltable_dict['OBSERVATION'] = ms_dict['OBSERVATION']

        print("Writing static meta data...")
        ms_extra.write_dict(ms_dict, ms_name, verbose=options.verbose)

        # Pre-allocate memory buffers
        tsize = dump_av
        in_chunk_shape = (tsize, ) + dataset.shape[1:]
        scan_vis_data = np.empty(in_chunk_shape, dataset.vis.dtype)
        scan_weight_data = np.empty(in_chunk_shape, dataset.weights.dtype)
        scan_flag_data = np.empty(in_chunk_shape, dataset.flags.dtype)

        ms_chunk_shape = (SLOTS, tsize // dump_av, nbl, nchan, npol)
        raw_vis_data = ms_async.RawArray(ms_chunk_shape, scan_vis_data.dtype)
        raw_weight_data = ms_async.RawArray(ms_chunk_shape,
                                            scan_weight_data.dtype)
        raw_flag_data = ms_async.RawArray(ms_chunk_shape, scan_flag_data.dtype)
        ms_vis_data = raw_vis_data.asarray()
        ms_weight_data = raw_weight_data.asarray()
        ms_flag_data = raw_flag_data.asarray()

        # Need to limit the queue to prevent overwriting slots before they've
        # been processed. The -2 allows for the one we're writing and the one
        # the writer process is reading.
        work_queue = multiprocessing.Queue(maxsize=SLOTS - 2)
        result_queue = multiprocessing.Queue()
        writer_process = multiprocessing.Process(
            target=ms_async.ms_writer_process,
            args=(work_queue, result_queue, options, dataset.ants, cp_info,
                  ms_name, raw_vis_data, raw_weight_data, raw_flag_data))
        writer_process.start()

        try:
            slot = 0
            for scan_ind, scan_state, target in dataset.scans():
                s = time.time()
                scan_len = dataset.shape[0]
                prefix = f'scan {scan_ind:3d} ({scan_len:4d} samples)'
                if scan_state != 'track':
                    if options.verbose:
                        print(f"{prefix} skipped '{scan_state}' - not a track")
                    continue
                if scan_len < 2:
                    if options.verbose:
                        print(f'{prefix} skipped - too short')
                    continue
                if target.body_type != 'radec':
                    if options.verbose:
                        print(
                            f"{prefix} skipped - target '{target.name}' not RADEC"
                        )
                    continue
                print(
                    f"{prefix} loaded. Target: '{target.name}'. Writing to disk..."
                )

                # Get the average dump time for this scan (equal to scan length
                # if the dump period is longer than a scan)
                dump_time_width = min(time_av, scan_len * dataset.dump_period)

                # Get UTC timestamps
                utc_seconds = dataset.timestamps[:]
                # Update field lists if this is a new target
                if target.name not in field_names:
                    # Since this will be an 'radec' target, we don't need antenna
                    # or timestamp to get the (astrometric) ra, dec
                    ra, dec = target.radec()

                    field_names.append(target.name)
                    field_centers.append((ra, dec))
                    field_times.append(
                        katpoint.Timestamp(utc_seconds[0]).to_mjd() * 60 * 60 *
                        24)
                    if options.verbose:
                        print(
                            f"Added new field {len(field_names) - 1}: '{target.name}' {ra} {dec}"
                        )
                field_id = field_names.index(target.name)

                # Determine the observation tag for this scan
                obs_tag = ','.join(tag_to_intent[tag] for tag in target.tags
                                   if tag in tag_to_intent)

                # add tag to obs_modes list
                if obs_tag and obs_tag not in obs_modes:
                    obs_modes.append(obs_tag)
                # get state_id from obs_modes list if it is in the list, else 0 'UNKNOWN'
                state_id = obs_modes.index(
                    obs_tag) if obs_tag in obs_modes else 0

                # Iterate over time in some multiple of dump average
                ntime = utc_seconds.size
                ntime_av = 0

                for ltime in range(0, ntime - tsize + 1, tsize):
                    utime = ltime + tsize
                    tdiff = utime - ltime
                    out_freqs = dataset.channel_freqs

                    # load all visibility, weight and flag data
                    # for this scan's timestamps.
                    # Ordered (ntime, nchan, nbl*npol)
                    load(dataset, np.s_[ltime:utime, :, :], scan_vis_data,
                         scan_weight_data, scan_flag_data)

                    # This are updated as we go to point to the current storage
                    vis_data = scan_vis_data
                    weight_data = scan_weight_data
                    flag_data = scan_flag_data

                    out_utc = utc_seconds[ltime:utime]

                    # Overwrite the input visibilities with averaged visibilities,
                    # flags, weights, timestamps, channel freqs
                    if average_data:
                        vis_data, weight_data, flag_data, out_utc, out_freqs = \
                            averager.average_visibilities(vis_data, weight_data, flag_data,
                                                          out_utc, out_freqs, timeav=dump_av,
                                                          chanav=chan_av, flagav=options.flagav)

                        # Infer new time dimension from averaged data
                        tdiff = vis_data.shape[0]

                    # Select correlator products and permute axes
                    cp_index = cp_info.cp_index.reshape((nbl, npol))
                    vis_data, weight_data, flag_data = permute_baselines(
                        vis_data, weight_data, flag_data, cp_index,
                        ms_vis_data[slot], ms_weight_data[slot],
                        ms_flag_data[slot])

                    # Increment the number of averaged dumps
                    ntime_av += tdiff

                    # Check if writer process has crashed and abort if so
                    try:
                        result = result_queue.get_nowait()
                        raise result
                    except queue.Empty:
                        pass

                    work_queue.put(
                        ms_async.QueueItem(slot=slot,
                                           target=target,
                                           time_utc=out_utc,
                                           dump_time_width=dump_time_width,
                                           field_id=field_id,
                                           state_id=state_id,
                                           scan_itr=scan_itr))
                    slot += 1
                    if slot == SLOTS:
                        slot = 0

                work_queue.put(ms_async.EndOfScan())
                result = result_queue.get()
                if isinstance(result, Exception):
                    raise result
                scan_size = result.scan_size
                s1 = time.time() - s

                if average_data and utc_seconds.shape != ntime_av:
                    print(
                        f'Averaged {np.shape(utc_seconds)[0]} x {dataset.dump_period} second dumps '
                        f'to {ntime_av} x {dump_time_width} second dumps')

                scan_size_mb = float(scan_size) / (1024**2)

                print(f'Wrote scan data ({scan_size_mb:.3f} MiB) '
                      f'in {s1:.3f} s ({scan_size_mb / s1:.3f} MiBps)\n')

                scan_itr += 1
                total_size += scan_size

        finally:
            work_queue.put(None)
            writer_exc = None
            # Drain the result_queue so that we unblock the writer process
            while True:
                result = result_queue.get()
                if isinstance(result, Exception):
                    writer_exc = result
                elif result is None:
                    break
            writer_process.join()
        # This raise is deferred to outside the finally block, so that we don't
        # raise an exception while unwinding another one.
        if isinstance(writer_exc, Exception):
            raise writer_exc

        if total_size == 0:
            raise RuntimeError("No usable data found in MVF dataset "
                               "(pick another reference antenna, maybe?)")

        # Remove spaces from source names, unless otherwise specified
        field_names = [f.replace(' ', '') for f in field_names] \
            if not options.keep_spaces else field_names

        ms_dict = {}
        ms_dict['SPECTRAL_WINDOW'] = ms_extra.populate_spectral_window_dict(
            out_freqs, channel_freq_width * np.ones(len(out_freqs)))
        ms_dict['FIELD'] = ms_extra.populate_field_dict(
            field_centers, field_times, field_names)
        ms_dict['STATE'] = ms_extra.populate_state_dict(obs_modes)
        ms_dict['SOURCE'] = ms_extra.populate_source_dict(
            field_centers, field_times, field_names)

        print("\nWriting dynamic fields to disk....\n")
        # Finally we write the MS as per our created dicts
        ms_extra.write_dict(ms_dict, ms_name, verbose=options.verbose)
        if options.tar:
            tar = tarfile.open(f'{ms_name}.tar', 'w')
            tar.add(ms_name, arcname=os.path.basename(ms_name))
            tar.close()

        # --------------------------------------
        # Now write calibration product tables if required
        # Open first HDF5 file in the list to extract TelescopeState parameters from
        #   (can't extract telstate params from contatenated katdal file as it
        #    uses the hdf5 file directly)
        first_dataset = katdal.open(args[0], ref_ant=options.ref_ant)
        main_table = ms_extra.open_table(ms_name, verbose=options.verbose)

        if options.caltables:
            # copy extra subtable dictionary values necessary for caltable
            caltable_dict['SPECTRAL_WINDOW'] = ms_dict['SPECTRAL_WINDOW']
            caltable_dict['FIELD'] = ms_dict['FIELD']

            solution_types = ['G', 'B', 'K']
            ms_soltype_lookup = {
                'G': 'G Jones',
                'B': 'B Jones',
                'K': 'K Jones'
            }

            print("\nWriting calibration solution tables to disk....")
            if 'TelescopeState' not in first_dataset.file.keys():
                print(
                    " No TelescopeState in first dataset. Can't create solution tables.\n"
                )
            else:
                # first get solution antenna ordering
                #   newer files have the cal antlist as a sensor
                if 'cal_antlist' in first_dataset.file['TelescopeState'].keys(
                ):
                    a0 = first_dataset.file['TelescopeState/cal_antlist'][()]
                    antlist = telstate_decode(a0[0][1])
                #   older files have the cal antlist as an attribute
                elif 'cal_antlist' in first_dataset.file[
                        'TelescopeState'].attrs.keys():
                    antlist = np.safe_eval(
                        first_dataset.file['TelescopeState'].
                        attrs['cal_antlist'])
                else:
                    print(" No calibration antenna ordering in first dataset. "
                          "Can't create solution tables.\n")
                    continue
                antlist_indices = list(range(len(antlist)))

                # for each solution type in the file, create a table
                for sol in solution_types:
                    caltable_name = f'{basename}.{sol}'
                    sol_name = f'cal_product_{sol}'

                    if sol_name in first_dataset.file['TelescopeState'].keys():
                        print(
                            f' - creating {sol} solution table: {caltable_name}\n'
                        )

                        # get solution values from the file
                        solutions = first_dataset.file['TelescopeState'][
                            sol_name][()]
                        soltimes, solvals = [], []
                        for t, s in solutions:
                            soltimes.append(t)
                            solvals.append(telstate_decode(s))
                        solvals = np.array(solvals)

                        # convert averaged UTC timestamps to MJD seconds.
                        sol_mjd = np.array([
                            katpoint.Timestamp(time_utc).to_mjd() * 24 * 60 *
                            60 for time_utc in soltimes
                        ])

                        # determine solution characteristics
                        if len(solvals.shape) == 4:
                            ntimes, nchans, npols, nants = solvals.shape
                        else:
                            ntimes, npols, nants = solvals.shape
                            nchans = 1
                            solvals = solvals.reshape(ntimes, nchans, npols,
                                                      nants)

                        # create calibration solution measurement set
                        caltable_desc = ms_extra.caltable_desc_float \
                            if sol == 'K' else ms_extra.caltable_desc_complex
                        caltable = ms_extra.open_table(caltable_name,
                                                       tabledesc=caltable_desc)

                        # add other keywords for main table
                        if sol == 'K':
                            caltable.putkeyword('ParType', 'Float')
                        else:
                            caltable.putkeyword('ParType', 'Complex')
                        caltable.putkeyword('MSName', ms_name)
                        caltable.putkeyword('VisCal', ms_soltype_lookup[sol])
                        caltable.putkeyword('PolBasis', 'unknown')
                        # add necessary units
                        caltable.putcolkeywords(
                            'TIME', {
                                'MEASINFO': {
                                    'Ref': 'UTC',
                                    'type': 'epoch'
                                },
                                'QuantumUnits': ['s']
                            })
                        caltable.putcolkeywords('INTERVAL',
                                                {'QuantumUnits': ['s']})
                        # specify that this is a calibration table
                        caltable.putinfo({
                            'readme': '',
                            'subType': ms_soltype_lookup[sol],
                            'type': 'Calibration'
                        })

                        # get the solution data to write to the main table
                        solutions_to_write = solvals.transpose(
                            0, 3, 1, 2).reshape(ntimes * nants, nchans, npols)

                        # MS's store delays in nanoseconds
                        if sol == 'K':
                            solutions_to_write = 1e9 * solutions_to_write

                        times_to_write = np.repeat(sol_mjd, nants)
                        antennas_to_write = np.tile(antlist_indices, ntimes)
                        # just mock up the scans -- this doesnt actually correspond to scans in the data
                        scans_to_write = np.repeat(list(range(len(sol_mjd))),
                                                   nants)
                        # write the main table
                        main_cal_dict = ms_extra.populate_caltable_main_dict(
                            times_to_write, solutions_to_write,
                            antennas_to_write, scans_to_write)
                        ms_extra.write_rows(caltable,
                                            main_cal_dict,
                                            verbose=options.verbose)

                        # create and write subtables
                        subtables = [
                            'OBSERVATION', 'ANTENNA', 'FIELD',
                            'SPECTRAL_WINDOW', 'HISTORY'
                        ]
                        subtable_key = [(os.path.join(caltable.name(), st))
                                        for st in subtables]

                        # Add subtable keywords and create subtables
                        # ------------------------------------------------------------------------------
                        # # this gives an error in casapy:
                        # *** Error *** MSObservation(const Table &) - table is not a valid MSObservation
                        # for subtable, subtable_location in zip(subtables, subtable_key)
                        #    ms_extra.open_table(subtable_location, tabledesc=ms_extra.ms_desc[subtable])
                        #    caltable.putkeyword(subtable, 'Table: {0}'.format(subtable_location))
                        # # write the static info for the table
                        # ms_extra.write_dict(caltable_dict, caltable.name(), verbose=options.verbose)
                        # ------------------------------------------------------------------------------
                        # instead try just copying the main table subtables
                        #   this works to plot the data casapy, but the solutions still can't be
                        #   applied in casapy...
                        for subtable, subtable_location in zip(
                                subtables, subtable_key):
                            main_subtable = ms_extra.open_table(
                                os.path.join(main_table.name(), subtable))
                            main_subtable.copy(subtable_location, deep=True)
                            caltable.putkeyword(subtable,
                                                f'Table: {subtable_location}')
                            if subtable == 'ANTENNA':
                                caltable.putkeyword('NAME', antlist)
                                caltable.putkeyword('STATION', antlist)
                        if sol != 'B':
                            spw_table = ms_extra.open_table(
                                os.path.join(caltable.name(),
                                             'SPECTRAL_WINDOW'))
                            spw_table.removerows(spw_table.rownumbers())
                            cen_index = len(out_freqs) // 2
                            # the delay values in the cal pipeline are calculated relative to frequency 0
                            ref_freq = 0.0 if sol == 'K' else None
                            spw_dict = {
                                'SPECTRAL_WINDOW':
                                ms_extra.populate_spectral_window_dict(
                                    np.atleast_1d(out_freqs[cen_index]),
                                    np.atleast_1d(channel_freq_width),
                                    ref_freq=ref_freq)
                            }
                            ms_extra.write_dict(spw_dict,
                                                caltable.name(),
                                                verbose=options.verbose)

                        # done with this caltable
                        caltable.flush()
                        caltable.close()

        main_table.close()
Пример #17
0
def read_and_plot_data(filename,
                       output_dir='.',
                       pdf=True,
                       Ku=False,
                       verbose=False,
                       error_bars=False,
                       target='off1',
                       write_nd=False,
                       rfi_mask='/var/kat/katsdpscripts/RTS/rfi_mask.pickle',
                       **kwargs):
    print('inside', kwargs)
    file_base = filename.split('/')[-1].split('.')[0]
    nice_filename = file_base + '_T_sys_T_nd'

    # Set up logging: logging everything (DEBUG & above), both to console and file
    logger = logging.root
    logger.setLevel(logging.DEBUG)
    fh = logging.FileHandler(nice_filename + '.log', 'w')
    fh.setLevel(logging.DEBUG)
    fh.setFormatter(logging.Formatter('%(levelname)s: %(message)s'))
    logger.addHandler(fh)
    logger.info('Beginning data processing with:\n%s' % git_info('standard'))

    if Ku:
        logger.debug("Using Ku band ... unsetting L band RFI flags")
        h5 = katfile.open(filename, centre_freq=12500.5e6, **kwargs)
        length = h5.shape[1]
        # Don't subtract half a channel width as channel 0 is centred on 0 Hz in baseband
        rfi_static_flags = np.tile(True, length)
    else:
        h5 = katfile.open(filename, **kwargs)
        length = h5.shape[1]
        pickle_file = open(rfi_mask, mode='rb')
        rfi_static_flags = pickle.load(pickle_file)
        pickle_file.close()
        # Now find the edges of the mask
        rfi_freqs_width = (856000000.0 / rfi_static_flags.shape[0])
        rfi_freqs_min = 856000000.0 - rfi_freqs_width / 2.  # True Start of bin
        rfi_freqs_max = rfi_freqs_min * 2 - rfi_freqs_width / 2.  # Middle of Max-1 bin
        rfi_freqs = np.linspace(rfi_freqs_min, rfi_freqs_max,
                                rfi_static_flags.shape[0])
        rfi_function = get_fit(
            np.r_[rfi_freqs, rfi_freqs + rfi_freqs_width * 0.9999],
            np.r_[rfi_static_flags, rfi_static_flags])
        rfi_static_flags = rfi_function(h5.channel_freqs)
        #print ( (rfi_static_flags_new-rfi_static_flags)**2).sum()
    if verbose: logger.debug(h5.__str__())
    edge = np.tile(True, length)
    #edge[slice(211,3896)] = False #Old
    edge[slice(int(round(length * 0.0515)),
               int(round(0.9512 * length)))] = False  ###
    static_flags = np.logical_or(edge, rfi_static_flags)

    ants = h5.ants

    colour = ['b', 'g', 'r', 'c', 'm', 'y', 'k']
    pols = ['v', 'h']

    for a in ants:
        ant = a.name
        try:
            rx_sn = h5.receivers[ant]
        except KeyError:
            logger.error(
                'Receiver serial number for antennna %s not found in the H5 file'
                % ant)
            rx_sn = 'l.SN_NOT_FOUND'
        band, SN = rx_sn.split('.')
        if pdf:
            pdf_filename = output_dir + '/' + nice_filename + '.' + rx_sn + '.' + a.name + '.pdf'
            pp = PdfPages(pdf_filename)
            logger.debug("Created output PDF file: %s" % pdf_filename)

        #fig0 = plt.figure(0,figsize=(20,5))
        h5.select()
        h5.select(ants=a.name, channels=~static_flags)
        observer = h5.ants[0].observer
        observer.date = time.gmtime(
            h5.timestamps.mean())[:6]  # katdal resets this date to now()!
        fig0 = plot_ts(h5)
        Tsys, TAc, Tsys_std = {}, {}, {}
        eta_A = {}
        Tdiode = {}
        nd_temp = {}
        for pol in pols:
            logger.debug("Processing: %s%s" % (a.name, pol))
            Tsys_std[pol] = None
            if not (Ku):
                diode_filename = '/var/kat/katconfig/user/noise-diode-models/mkat/rx.' + rx_sn + '.' + pol + '.csv'
                logger.info('Loading noise diode file %s from config' %
                            diode_filename)
                try:
                    nd = scape.gaincal.NoiseDiodeModel(diode_filename)
                except:
                    logger.error(
                        "Error reading the noise diode file ... using a constant value of 20k"
                    )
                    logger.error(
                        "Be sure to reprocess the data once the file is in the config"
                    )
                    nd = scape.gaincal.NoiseDiodeModel(freq=[856, 1712],
                                                       temp=[20, 20])

            #cold data
            logger.debug('Using off target %s' % target)
            h5.select(ants=a.name,
                      pol=pol,
                      channels=~static_flags,
                      targets=target,
                      scans='track')
            freq = h5.channel_freqs

            cold_data = h5.vis[:].real
            cold_on, cold_off = get_nd_on_off(h5, log=logger)
            #hot data
            h5.select(ants=a.name,
                      pol=pol,
                      channels=~static_flags,
                      targets='Moon',
                      scans='track')
            hot_on, hot_off = get_nd_on_off(h5, log=logger)
            hot_data = h5.vis[:].real

            cold_spec = np.mean(cold_data[cold_off, :, 0], 0)
            hot_spec = np.mean(hot_data[hot_off, :, 0], 0)
            cold_nd_spec = np.mean(cold_data[cold_on, :, 0], 0)
            hot_nd_spec = np.mean(hot_data[hot_on, :, 0], 0)

            if not (Ku):
                nd_temp[pol] = nd.temperature(freq / 1e6)
                # antenna temperature on the moon (from diode calibration)
                TAh = hot_spec / (hot_nd_spec - hot_spec) * nd_temp[pol]
                # antenna temperature on cold sky (from diode calibration) (Tsys)
                TAc[pol] = cold_spec / (cold_nd_spec -
                                        cold_spec) * nd_temp[pol]
                print("Mean TAh = %f  mean TAc = %f " %
                      (TAh.mean(), TAc[pol].mean()))
            Y = hot_spec / cold_spec
            D = 13.5  # Efficiency tables are defined for 13.5
            lam = 299792458. / freq
            HPBW = 1.18 * (lam / D)
            Om = 1.133 * HPBW**2  # main beam solid angle for a gaussian beam
            R = 0.5 * Dmoon(observer)  # radius of the moon
            Os = 2 * np.pi * (1 - np.cos(R))  # disk source solid angle
            _f_MHz, _eff_pct = np.loadtxt(
                "/var/kat/katconfig/user/aperture-efficiency/mkat/ant_eff_%s_%s_AsBuilt.csv"
                % (band.upper(), pol.upper()),
                skiprows=2,
                delimiter="\t",
                unpack=True)
            eta_A[pol] = np.interp(freq, _f_MHz,
                                   _eff_pct) / 100.  # EMSS aperture efficiency
            if Ku: eta_A[pol] = 0.7
            Ag = np.pi * (D / 2)**2  # Antenna geometric area
            Ae = eta_A[pol] * Ag  # Effective aperture
            x = 2 * R / HPBW  # ratio of source to beam
            K = ((x / 1.2)**
                 2) / (1 - np.exp(-((x / 1.2)**2))
                       )  # correction factor for disk source from Baars 1973
            TA_moon = 225 * (Os / Om) * (
                1 / K
            )  # contribution from the moon (disk of constant brightness temp)
            gamma = 1.0
            Thot = TA_moon
            Tcold = 0
            Tsys[pol] = gamma * (Thot - Tcold) / (
                Y - gamma)  # Tsys from y-method ... compare with diode TAc
            if error_bars:
                cold_spec_std = np.std(cold_data[cold_off, :, 0], 0)
                hot_spec_std = np.std(hot_data[hot_off, :, 0], 0)
                cold_nd_spec_std = np.std(cold_data[cold_on, :, 0], 0)
                hot_nd_spec_std = np.std(hot_data[hot_on, :, 0], 0)
                Y_std = Y * np.sqrt((hot_spec_std / hot_spec)**2 +
                                    (cold_spec_std / cold_spec)**2)
                Thot_std = 2.25
                gamma_std = 0.01
                # This is not definded
                raise NotImplementedError(
                    "The factor Thot  has not been defined ")
                Tsys_std[pol] = Tsys[pol] * np.sqrt((Thot_std / Thot)**2 +
                                                    (Y_std / Y)**2 +
                                                    (gamma_std / gamma)**2)
            else:
                Tsys_std[pol] = None
            if not (Ku):
                Ydiode = hot_nd_spec / hot_spec
                Tdiode_h = (Tsys[pol] - Tcold + Thot) * (
                    Ydiode / gamma - 1
                )  # Tsys as computed above includes Tcold
                Ydiode = cold_nd_spec / cold_spec
                Tdiode_c = Tsys[pol] * (Ydiode / gamma - 1)
                Tdiode[pol] = (
                    Tdiode_h + Tdiode_c
                ) / 2.  # Average two equally valid, independent results
            if write_nd:
                outfilename = save_ND(diode_filename, file_base, freq,
                                      Tdiode[pol])
                logger.info('Noise temp data written to file %s' % outfilename)

        fig2 = plot_nd(freq, Tdiode, nd_temp, ant=ant, file_base=file_base)
        fig1 = plot_Tsys_eta_A(freq,
                               Tsys,
                               eta_A,
                               TAc,
                               Tsys_std=Tsys_std,
                               ant=ant,
                               file_base=file_base,
                               Ku=Ku)
        if pdf:
            if not (Ku):
                fig2.savefig(pp, format='pdf')
            fig1.savefig(pp, format='pdf')
            fig0.savefig(pp, format='pdf')
            pp.close()  # close the pdf file
            plt.close("all")
    logger.info('Processing complete')
Пример #18
0
parser.add_argument('--time', type=int, default=10, help='Number of times to read per batch')
parser.add_argument('--channels', type=int, help='Number of channels to read')
parser.add_argument('--dumps', type=int, help='Number of times to read')
parser.add_argument('--joint', action='store_true', help='Load vis, weights, flags together')
parser.add_argument('--applycal', help='Calibration solutions to apply')
parser.add_argument('--workers', type=int, help='Number of dask workers')
args = parser.parse_args()

logging.basicConfig(level='INFO', format='%(asctime)s [%(levelname)s] %(message)s')
if args.workers is not None:
    dask.config.set(num_workers=args.workers)
logging.info('Starting')
kwargs = {}
if args.applycal is not None:
    kwargs['applycal'] = args.applycal
f = katdal.open(args.filename, **kwargs)
logging.info('File loaded, shape %s', f.shape)
if args.channels:
    f.select(channels=np.s_[:args.channels])
if args.dumps:
    f.select(dumps=np.s_[:args.dumps])
# Trigger creation of the dask graphs, population of sensor cache for applycal etc
_ = (f.vis[0, 0, 0], f.weights[0, 0, 0], f.flags[0, 0, 0])
logging.info('Selection complete')
start = time.time()
last_time = start
for st in range(0, f.shape[0], args.time):
    et = st + args.time
    if args.joint:
        vis, weights, flags = DaskLazyIndexer.get([f.vis, f.weights, f.flags], np.s_[st:et])
    else:
Пример #19
0
    parser.add_option('-o', '--out',
                      action='store',
                      dest='outfile',
                      type=str,
                      default=None,
                      help='Full path name of output PDF report file.')
    (opts, args) = parser.parse_args()

    if len(args) < 1: raise SystemExit(parser.print_usage())
    datafile = args[0]
    if opts.outfile is None: opts.outfile = os.path.splitext(os.path.basename(datafile))[0]
    else:                    opts.outfile = os.path.splitext(os.path.basename(opts.outfile))[0]

    # Read data file
    try:
        h5 = katdal.open(datafile, quicklook=True)
    except Exception as err_msg: raise SystemExit('An error as occured:\n%s' % err_msg)

    # Read progress output
    if opts.aux is None: raise RuntimeError('Please provide progress.out file for gain settings')
    progress = opts.aux
    f = open(progress)
    myfile = f.readlines()
    f.close()

    # Correlate gain change timestamps from progress to spectra timestamps from observation file
    timestamps = []
    req_gains = []
    gain_idx = []
    for line in myfile:
        if line.strip().find("Set digital gain on selected DBE") > 0:
Пример #20
0
import katdal
import numpy as np
import matplotlib.pylab as plt

import katcal
from katcal import calprocs

# ------------------------------------------------------------------------
# open file
file_name = "/data1/NASSP/reduction_script/1355292163.h5"
f = katdal.open(file_name)
# select polarisation
#  solver can only work on one polarisation at a time in this framework
f.select(pol="h")

# get info that is needed for the solver
antlist = [a.name for a in f.ants]
corr_products = f.corr_products
antlist1, antlist2 = calprocs.get_solver_antlists(antlist, corr_products)

# ------------------------------------------------------------------------
# solve for gains

glist = []
tlist = []

for scan_ind, scan_state, target in f.scans():
    if "track" in scan_state and "gaincal" in target.tags:

        vis = f.vis[:]
        times = f.timestamps[:]
Пример #21
0
    elif arg.endswith('.h5'):
        files.append(arg)
    else:
        for rootdir, subdirs, dirfiles in os.walk(arg):
            files.extend([
                os.path.join(rootdir, name) for name in dirfiles
                if name.endswith('.h5')
            ])

# Open each file in turn and print a one-line summary
print(
    "Name          Ver Observer   StartTimeSAST       Shape               SizeGB "
    "DumpHz SPW CFreqMHz Ants    Tgts Scans Description")
for f in files:
    try:
        d = katdal.open(f, quicklook=True)
    except Exception, e:
        print '%s %s - %s' % (f, e.__class__.__name__, e)
        continue
    name = os.path.basename(f)
    name = (name[:10] + '...') if len(name) > 13 else name
    all_ants = ('ant1', 'ant2', 'ant3', 'ant4', 'ant5', 'ant6', 'ant7')
    file_ants = [ant.name for ant in d.ants]
    ants = ''.join([(ant[3:] if ant in file_ants else '-')
                    for ant in all_ants])
    print '%13s %3s %10s %19s (%6d,%5d,%4d) %6.2f %6.3f %3d %8.3f %s %4d %5d %s' % \
          (name, d.version, d.observer.strip()[:10].ljust(10), d.start_time.local()[:19],
           d.shape[0], d.shape[1], d.shape[2], d.size / 1024. / 1024. / 1024., 1.0 / d.dump_period,
           len(d.spectral_windows), d.spectral_windows[d.spw].centre_freq / 1e6, ants,
           len(d.catalogue), len(d.scan_indices), d.description)
    del d
Пример #22
0
    help=
    "This is the frequency range of the channels to use in the reduction. this is passed as a comma delimatated pair of integer values', default = '%default'"
)

(opts, args) = parser.parse_args()

if len(args) < 1:
    raise RuntimeError('Please specify the data file to reduce')
height = 1.0
bins = opts.bins

if opts.ku_band is None:
    pickle_fn = open(opts.mask, mode='rb')
    rfi_static_flags = pickle.load(pickle_fn)
    pickle_fn.close()
    h5 = katdal.open(args[0])
else:
    centre_freq = 12500.5e6
    h5 = katdal.open(args[0], centre_freq=np.float(centre_freq))
    rfi_static_flags = rfi.detect_spikes_median(
        h5.vis[:], spike_width=3, outlier_sigma=5.0).max(axis=2).max(axis=0)

freqst, freqend = opts.freq.split(',')
rfi_static_flags[0:np.int(freqst)] = True
rfi_static_flags[np.int(freqend):-1] = True

#1392246099.h5
if opts.ant == '':
    ant_list = [ant.name for ant in h5.ants]
else:
    ant_list = [opts.ant]
Пример #23
0
        type=float,
        default=1575e6,
        help='Frequency of expected target in Hz, default = \'%default\' Hz.')
    parser.add_option('--out',
                      action='store',
                      dest='outfile',
                      type=str,
                      default=None,
                      help='Name of output report file.')

    (opts, args) = parser.parse_args()

    if opts.filename is None: raise SystemExit(parser.print_usage())

    try:
        h5 = katdal.open(opts.filename, quicklook=True)
    except Exception as err_msg:
        raise SystemExit('An error as occured:\n%s' % err_msg)

    outfile = opts.outfile
    if outfile is None:
        outfile = os.path.splitext(os.path.basename(opts.filename))[0]

    ants = [opts.ant]
    pols = [opts.pol]
    if opts.ant == 'all':
        ants = [ant.name for ant in h5.ants]
        outants = 'all_antennas'
    else:
        outants = opts.ant
    if opts.pol == 'all':
Пример #24
0
def MKContPipeline(files, outputdir, **kwargs):
    """MeerKAT Continuum pipeline.

    Parameters
    ----------
    files : list
        h5 filenames (note: support for multiple h5 files 
        i.e. ConcatenatedDataSet is not currently supported)
    outputdir : string
        Directory location to write output data, 
    scratchdir : string, optional
        The directory location of the aips disk
    parmFile : string, optional
        Overwrite the default imaging parameters using this parameter file.
    """
    #if len(files) > 1:
    #    raise TooManyKatfilesException('Processing multiple katfiles are not currently supported')
    # Onle be concatenated if we have to be
    if len(files) == 1:
        h5file = files[0]
    else:
        h5file = files

    # Die gracefully if we cannot write to the output area...
    if not os.path.exists(outputdir):
        print('Specified output directory: ' + outputdir + 'does not exist.')
        exit(-1)

    # Obit error logging
    err = OErr.OErr()

    #################### Initialize filenames #######################################################
    fileRoot = os.path.join(outputdir,
                            os.path.basename(os.path.splitext(
                                files[0])[0]))  # root of file name
    logFile = fileRoot + ".log"  # Processing log file
    avgClass = ("UVAv")[0:6]  # Averaged data AIPS class
    manifestfile = outputdir + '/manifest.pickle'

    ############################# Initialize OBIT and AIPS ##########################################
    noScrat = []
    # Logging directly to logFile
    OErr.PInit(err, 2, logFile)
    EVLAAddOutFile(os.path.basename(logFile), 'project', 'Pipeline log file')
    if kwargs.get('reuse'):
        ObitSys = AIPSSetup.AIPSSetup(err,
                                      configfile=kwargs.get('configFile'),
                                      scratchdir=kwargs.get('scratchdir'),
                                      aipsdisk=kwargs.get('aipsdisk'),
                                      overwrite=False)
    else:
        ObitSys = AIPSSetup.AIPSSetup(err,
                                      configfile=kwargs.get('configFile'),
                                      scratchdir=kwargs.get('scratchdir'),
                                      aipsdisk=kwargs.get('aipsdisk'))

    # Get the set up AIPS environment.
    AIPS_ROOT = os.environ['AIPS_ROOT']
    AIPS_VERSION = os.environ['AIPS_VERSION']

    nThreads = 72
    user = OSystem.PGetAIPSuser()
    AIPS.userno = user
    disk = 1
    fitsdisk = 0
    nam = os.path.basename(os.path.splitext(files[0])[0])[0:10]
    cls = "Raw"
    seq = 1

    ############################# Initialise Parameters ##########################################
    ####### Initialize parameters dictionary #####
    parms = KATInitContParms()
    ####### User defined parameters ######
    if kwargs.get('parmFile'):
        print("parmFile", kwargs.get('parmFile'))
        exec(open(kwargs.get('parmFile')).read())
        EVLAAddOutFile(os.path.basename(kwargs.get('parmFile')), 'project',
                       'Pipeline input parameters')

    ############### Initialize katfile object, uvfits object and condition data #########################
    OK = False
    # Open the h5 file as a katfile object
    try:
        #open katfile and perform selection according to kwargs
        katdata = katfile.open(h5file)
        OK = True
    except Exception as exception:
        print(exception)
    if not OK:
        OErr.PSet(err)
        OErr.PLog(err, OErr.Fatal,
                  "Unable to read KAT HDF5 data in " + str(h5file))
        raise KATUnimageableError("Unable to read KAT HDF5 data in " +
                                  str(h5file))

    #Are we MeerKAT or KAT-7
    telescope = katdata.ants[0].name[0]
    if telescope == 'm':
        sefd = 500.
    else:
        sefd = 1200.
    #Get calibrator models
    fluxcals = katpoint.Catalogue(
        open(FITSDir.FITSdisks[0] + "/" + parms["fluxModel"]))
    #Condition data (get bpcals, update names for aips conventions etc)
    KATh5Condition(katdata, fluxcals, err)

    ###################### Data selection and static edits ############################################
    # Select data based on static imageable parameters
    MKATh5Select(katdata, parms, err, **kwargs)

    # General AIPS data parameters at script level
    dataClass = ("UVDa")[0:6]  # AIPS class of raw uv data
    band = katdata.spectral_windows[0].product  #Correlator product
    project = os.path.basename(os.path.splitext(files[0])[0])[
        0:10]  # Project name (12 char or less, used as AIPS Name)
    outIClass = parms["outIClass"]  # image AIPS class
    debug = parms["debug"]
    check = parms["check"]

    ####################### Import data into AIPS #####################################################
    # Reuse or nay?
    if kwargs.get('reuse'):
        uv = UV.newPAUV("AIPS UV DATA", EVLAAIPSName(project), dataClass, disk,
                        seq, True, err)
        obsdata = KATH5toAIPS.GetKATMeta(katdata, err)
        # Extract AIPS parameters of the uv data to the metadata
        obsdata["Aproject"] = uv.Aname
        obsdata["Aclass"] = uv.Aclass
        obsdata["Aseq"] = uv.Aseq
        obsdata["Adisk"] = disk
        obsdata["calInt"] = katdata.dump_period
        obsdata["fitsdisk"] = fitsdisk
        # TODO: Check if the input data has been Hanned.
        doneHann = True
    else:
        # Number of baselines gives batch size
        nbl = len(
            np.unique([(cp[0][:-1] + cp[1][:-1]).upper()
                       for cp in katdata.corr_products]))
        # Construct a template uvfits file from master template
        mastertemplate = ObitTalkUtil.FITSDir.FITSdisks[
            fitsdisk] + 'MKATTemplate.uvtab.gz'
        outtemplate = nam + '.uvtemp'
        KATH5toAIPS.MakeTemplate(mastertemplate,
                                 outtemplate,
                                 len(katdata.channel_freqs),
                                 nvispio=nbl)
        uv = OTObit.uvlod(outtemplate, 0, EVLAAIPSName(project), cls, disk,
                          seq, err)
        obsdata = KATH5toAIPS.KAT2AIPS(katdata,
                                       uv,
                                       disk,
                                       fitsdisk,
                                       err,
                                       calInt=katdata.dump_period,
                                       **kwargs)
        MakeIFs.UVMakeIF(uv, 8, err)
        os.remove(outtemplate)
    # Print the uv data header to screen.
    uv.Header(err)
    ############################# Set Project Processing parameters ###################################
    # Parameters derived from obsdata and katdata
    MKATGetObsParms(obsdata, katdata, parms, logFile)

    ###### Initialise target parameters #####
    KATInitTargParms(katdata, parms, err)

    # Load the outputs pickle jar
    EVLAFetchOutFiles()

    OSystem.PAllowThreads(nThreads)  # Allow threads in Obit/oython
    retCode = 0

    maxgap = max(parms["CalAvgTime"], 20 * katdata.dump_period) / 60.
    ################### Start processing ###############################################################

    mess = "Start project "+parms["project"]+" AIPS user no. "+str(AIPS.userno)+\
           ", KAT7 configuration "+parms["KAT7Cfg"]
    printMess(mess, logFile)
    if debug:
        pydoc.ttypager = pydoc.plainpager  # don't page task input displays
        mess = "Using Debug mode "
        printMess(mess, logFile)
    if check:
        mess = "Only checking script"
        printMess(mess, logFile)

    # Log parameters
    printMess("Parameter settings", logFile)
    for p in parms:
        mess = "  " + p + ": " + str(parms[p])
        printMess(mess, logFile)
    clist = []
    for DCal in parms["DCals"]:
        if DCal["Source"] not in clist:
            clist.append(DCal["Source"])
    for PCal in parms["PCals"]:
        if PCal["Source"] not in clist:
            clist.append(PCal["Source"])
    for ACal in parms["ACals"]:
        if ACal["Source"] not in clist:
            clist.append(ACal["Source"])
    if kwargs.get('targets') is not None:
        targets = [
            targ.name for targ in katdata.catalogue
            if (targ.name not in clist) and (
                targ.name in kwargs.get('targets').split(','))
        ]
    else:
        targets = [
            targ.name for targ in katdata.catalogue if (targ.name not in clist)
        ]
    refAnt = FetchObject(fileRoot + ".refAnt.pickle")

    # Save parameters to pickle jar, manifest
    ParmsPicklefile = fileRoot + ".Parms.pickle"  # Where results saved
    SaveObject(parms, ParmsPicklefile, True)
    EVLAAddOutFile(os.path.basename(ParmsPicklefile), 'project',
                   'Processing parameters used')
    loadClass = dataClass

    # Hanning - No Hanning
    parms["doHann"] = False
    doneHann = False

    if doneHann:
        # Halve channels after hanning.
        parms["selChan"] = int(parms["selChan"] / 2)
        parms["BChDrop"] = int(parms["BChDrop"] / 2)
        parms["EChDrop"] = int(parms["EChDrop"] / 2)
        if uv == None and not check:
            raise RuntimeError("Cannot Hann data ")

    # Clear any old calibration/editing
    if parms["doClearTab"] or kwargs.get('reuse'):
        mess = "Clear previous calibration"
        printMess(mess, logFile)
        EVLAClearCal(uv,
                     err,
                     doGain=parms["doClearGain"],
                     doFlag=parms["doClearFlag"],
                     doBP=parms["doClearBP"],
                     check=check)
        OErr.printErrMsg(err, "Error resetting calibration")

        # Quack to remove data from start and end of each scan
    if parms["doQuack"]:
        retCode = EVLAQuack (uv, err, begDrop=parms["quackBegDrop"], endDrop=parms["quackEndDrop"], \
                             Reason=parms["quackReason"], \
                             logfile=logFile, check=check, debug=debug)
        if retCode != 0:
            raise RuntimeError("Error Quacking data")

    # Flag antennas shadowed by others?
    if parms["doShad"]:
        retCode = EVLAShadow (uv, err, shadBl=parms["shadBl"], \
                              logfile=logFile, check=check, debug=debug)
        if retCode != 0:
            raise RuntimeError("Error Shadow flagging data")

    # Median window time editing, for RFI impulsive in time
    if parms["doMednTD1"]:
        mess = "Median window time editing, for RFI impulsive in time:"
        printMess(mess, logFile)
        retCode = EVLAMedianFlag (uv, clist, err, noScrat=noScrat, nThreads=nThreads, \
                                  avgTime=parms["mednAvgTime"], avgFreq=parms["mednAvgFreq"],  chAvg= parms["mednChAvg"], \
                                  timeWind=parms["mednTimeWind"],flagVer=2, flagTab=2,flagSig=parms["mednSigma"], \
                                  logfile=logFile, check=check, debug=False)
        if retCode != 0:
            raise RuntimeError("Error in MednFlag")

    # Median window frequency editing, for RFI impulsive in frequency
    if parms["doFD1"]:
        mess = "Median window frequency editing, for RFI impulsive in frequency:"
        printMess(mess, logFile)
        retCode = EVLAAutoFlag (uv, clist, err, flagVer=2, flagTab=2, doCalib=-1, doBand=-1,   \
                                timeAvg=parms["FD1TimeAvg"], \
                                doFD=True, FDmaxAmp=1.0e20, FDmaxV=1.0e20, FDwidMW=parms["FD1widMW"],  \
                                FDmaxRMS=[1.0e20,0.1], FDmaxRes=parms["FD1maxRes"],  \
                                FDmaxResBL= parms["FD1maxRes"],  FDbaseSel=parms["FD1baseSel"],\
                                nThreads=nThreads, logfile=logFile, check=check, debug=debug)
        if retCode != 0:
            raise RuntimeError("Error in AutoFlag")

    # Parallactic angle correction?
    if parms["doPACor"]:
        retCode = EVLAPACor(uv, err, \
                                logfile=logFile, check=check, debug=debug)
        if retCode != 0:
            raise RuntimeError("Error in Parallactic angle correction")

    # Need to find a reference antenna?  See if we have saved it?
    if (parms["refAnt"] <= 0):
        refAnt = FetchObject(fileRoot + ".refAnt.pickle")
        if refAnt:
            parms["refAnt"] = refAnt

    # Use bandpass calibrator and center half of each spectrum
    if parms["refAnt"] <= 0:
        mess = "Find best reference antenna: run Calib on BP Cal(s) "
        printMess(mess, logFile)
        parms["refAnt"] = EVLAGetRefAnt(uv, parms["BPCals"], err, flagVer=0, \
                                        solInt=parms["bpsolint1"], nThreads=nThreads, \
                                        logfile=logFile, check=check, debug=debug)
        if err.isErr:
            raise RuntimeError("Error finding reference antenna")
        if parms["refAnts"][0] <= 0:
            parms["refAnts"][0] = parms["refAnt"]
        mess = "Picked reference antenna " + str(parms["refAnt"])
        printMess(mess, logFile)
        # Save it
        ParmsPicklefile = fileRoot + ".Parms.pickle"  # Where results saved
        SaveObject(parms, ParmsPicklefile, True)
        refAntPicklefile = fileRoot + ".refAnt.pickle"  # Where results saved
        SaveObject(parms["refAnt"], refAntPicklefile, True)

    # Plot Raw, edited data?
    parms["doRawSpecPlot"] = False
    parms["doSpecPlot"] = False
    if parms["doRawSpecPlot"] and parms["plotSource"]:
        mess = "Raw Spectral plot for: " + ' '.join(parms["BPCal"])
        printMess(mess, logFile)
        plotFile = fileRoot + "_RawSpec.ps"
        retCode = EVLASpectrum(uv, parms["BPCal"], parms["plotTime"], maxgap, plotFile, parms["refAnt"], err, \
                               Stokes=["RR","LL"], doband=-1,          \
                               check=check, debug=debug, logfile=logFile )
        if retCode != 0:
            raise RuntimeError("Error in Plotting spectrum")
        EVLAAddOutFile(plotFile, 'project', 'Pipeline log file')

    # delay calibration
    if parms["doDelayCal"] and parms["DCals"] and not check:
        plotFile = fileRoot + "_DelayCal.ps"
        retCode = EVLADelayCal(uv, parms["DCals"], err,  \
                               BChan=parms["delayBChan"], EChan=parms["delayEChan"], \
                               doCalib=2, flagVer=0, doBand=-1, \
                               solInt=parms["delaySolInt"], smoTime=parms["delaySmoo"],  \
                               refAnts=[parms["refAnt"]], doTwo=parms["doTwo"],
                               doZeroPhs=parms["delayZeroPhs"], \
                               doPlot=parms["doSNPlot"], plotFile=plotFile, \
                               nThreads=nThreads, noScrat=noScrat, \
                               logfile=logFile, check=check, debug=debug)
        if retCode != 0:
            raise RuntimeError("Error in delay calibration")

        # Plot corrected data?
        if parms["doSpecPlot"] and parms["plotSource"]:
            plotFile = fileRoot + "_DelaySpec.ps"
            retCode = EVLASpectrum(uv, parms["BPCal"], parms["plotTime"], maxgap, \
                                   plotFile, parms["refAnt"], err, \
                                   Stokes=["RR","LL"], doband=-1,          \
                                   check=check, debug=debug, logfile=logFile )
            if retCode != 0:
                raise RuntimeError("Error in Plotting spectrum")
        print(parms["bpBChan1"], parms["bpEChan1"], parms["bpBChan2"],
              parms["bpEChan2"], parms["bpChWid2"])
    # Bandpass calibration
    if parms["doBPCal"] and parms["BPCals"]:
        retCode = KATBPCal(uv, parms["BPCals"], err, noScrat=noScrat, solInt1=parms["bpsolint1"], \
                            solInt2=parms["bpsolint2"], solMode=parms["bpsolMode"], \
                            BChan1=parms["bpBChan1"], EChan1=parms["bpEChan1"], \
                            BChan2=parms["bpBChan2"], EChan2=parms["bpEChan2"], ChWid2=parms["bpChWid2"], \
                            doCenter1=parms["bpDoCenter1"], refAnt=parms["refAnt"], \
                            UVRange=parms["bpUVRange"], doCalib=2, gainUse=0, flagVer=0, doPlot=False, \
                            nThreads=nThreads, logfile=logFile, check=check, debug=debug)
        if retCode != 0:
            raise RuntimeError("Error in Bandpass calibration")

        # Plot corrected data?
        if parms["doSpecPlot"] and parms["plotSource"]:
            plotFile = fileRoot + "_BPSpec.ps"
            retCode = EVLASpectrum(uv, parms["BPCal"], parms["plotTime"], maxgap, plotFile, \
                                   parms["refAnt"], err, Stokes=["RR","LL"], doband=2,          \
                                   check=check, debug=debug, logfile=logFile )
            if retCode != 0:
                raise RuntimeError("Error in Plotting spectrum")

    # Amp & phase Calibrate
    if parms["doAmpPhaseCal"]:
        plotFile = fileRoot + "_APCal.ps"
        retCode = KATCalAP (uv, [], parms["ACals"], err, PCals=parms["PCals"],
                             doCalib=2, doBand=2, BPVer=1, flagVer=0, \
                             BChan=parms["ampBChan"], EChan=parms["ampEChan"], \
                             solInt=parms["solInt"], solSmo=parms["solSmo"], ampScalar=parms["ampScalar"], \
                             doAmpEdit=parms["doAmpEdit"], ampSigma=parms["ampSigma"], \
                             ampEditFG=parms["ampEditFG"], \
                             doPlot=parms["doSNPlot"], plotFile=plotFile,  refAnt=parms["refAnt"], \
                             nThreads=nThreads, noScrat=noScrat, logfile=logFile, check=check, debug=debug)
        #print parms["ACals"],parms["PCals"]
        if retCode != 0:
            raise RuntimeError("Error calibrating")

    # More editing

    if parms["doAutoFlag"]:
        mess = "Post calibration editing:"
        printMess(mess, logFile)
        # if going to redo then only calibrators
        if parms["doRecal"]:
            # Only calibrators
            clist = []
            for DCal in parms["DCals"]:
                if DCal["Source"] not in clist:
                    clist.append(DCal["Source"])
            for PCal in parms["PCals"]:
                if PCal["Source"] not in clist:
                    clist.append(PCal["Source"])
            for ACal in parms["ACals"]:
                if ACal["Source"] not in clist:
                    clist.append(ACal["Source"])
        else:
            clist = []

        retCode = EVLAAutoFlag (uv, clist, err, flagVer=0, flagTab =2, \
                                doCalib=2, gainUse=0, doBand=2, BPVer=1,  \
                                IClip=parms["IClip"], minAmp=parms["minAmp"], timeAvg=parms["timeAvg"], \
                                doFD=parms["doFirstAFFD"], FDmaxAmp=parms["FDmaxAmp"], FDmaxV=parms["FDmaxV"], \
                                FDwidMW=parms["FDwidMW"], FDmaxRMS=parms["FDmaxRMS"], \
                                FDmaxRes=parms["FDmaxRes"],  FDmaxResBL=parms["FDmaxResBL"], \
                                FDbaseSel=parms["FDbaseSel"], \
                                nThreads=nThreads, logfile=logFile, check=check, debug=debug)
        if retCode != 0:
            raise RuntimeError("Error in AutoFlag")

    # Redo the calibration using new flagging?
    if parms["doBPCal2"] == None:
        parms["doBPCal2"] = parms["doBPCal"]
    if parms["doDelayCal2"] == None:
        parms["doDelayCal2"] = parms["doDelayCal2"]
    if parms["doAmpPhaseCal2"] == None:
        parms["doAmpPhaseCal2"] = parms["doAmpPhaseCal"]
    if parms["doAutoFlag2"] == None:
        parms["doAutoFlagCal2"] = parms["doAutoFlag"]
    if parms["doRecal"]:
        mess = "Redo calibration:"
        printMess(mess, logFile)
        EVLAClearCal(uv,
                     err,
                     doGain=True,
                     doFlag=False,
                     doBP=True,
                     check=check,
                     logfile=logFile)
        OErr.printErrMsg(err, "Error resetting calibration")
        # Parallactic angle correction?
        if parms["doPACor"]:
            retCode = EVLAPACor(uv, err, \
                                logfile=logFile, check=check, debug=debug)
            if retCode != 0:
                raise RuntimeError("Error in Parallactic angle correction")

        # Delay recalibration
        if parms["doDelayCal2"] and parms["DCals"] and not check:
            plotFile = fileRoot + "_DelayCal2.ps"
            retCode = EVLADelayCal(uv, parms["DCals"], err, \
                                   BChan=parms["delayBChan"], EChan=parms["delayEChan"], \
                                   doCalib=2, flagVer=0, doBand=-1, \
                                   solInt=parms["delaySolInt"], smoTime=parms["delaySmoo"],  \
                                   refAnts=[parms["refAnt"]], doTwo=parms["doTwo"], \
                                   doZeroPhs=parms["delayZeroPhs"], \
                                   doPlot=parms["doSNPlot"], plotFile=plotFile, \
                                   nThreads=nThreads, noScrat=noScrat, \
                                   logfile=logFile, check=check, debug=debug)
            if retCode != 0:
                raise RuntimeError("Error in delay calibration")

            # Plot corrected data?
            if parms["doSpecPlot"] and parms["plotSource"]:
                plotFile = fileRoot + "_DelaySpec2.ps"
                retCode = EVLASpectrum(uv, parms["BPCal"], parms["plotTime"], maxgap, plotFile, parms["refAnt"], err, \
                                       Stokes=["RR","LL"], doband=-1,          \
                                       check=check, debug=debug, logfile=logFile )
                if retCode != 0:
                    raise RuntimeError("Error in Plotting spectrum")

        # Bandpass calibration
        if parms["doBPCal2"] and parms["BPCals"]:
            retCode = KATBPCal(uv, parms["BPCals"], err, noScrat=noScrat, solInt1=parms["bpsolint1"], \
                            solInt2=parms["bpsolint2"], solMode=parms["bpsolMode"], \
                            BChan1=parms["bpBChan1"], EChan1=parms["bpEChan1"], \
                            BChan2=parms["bpBChan2"], EChan2=parms["bpEChan2"], ChWid2=parms["bpChWid2"], \
                            doCenter1=parms["bpDoCenter1"], refAnt=parms["refAnt"], \
                            UVRange=parms["bpUVRange"], doCalib=2, gainUse=0, flagVer=0, doPlot=False, \
                            nThreads=nThreads, logfile=logFile, check=check, debug=debug)
            if retCode != 0:
                raise RuntimeError("Error in Bandpass calibration")

            # Plot corrected data?
            if parms["doSpecPlot"] and parms["plotSource"]:
                plotFile = fileRoot + "_BPSpec2.ps"
                retCode = EVLASpectrum(uv, parms["BPCal"], parms["plotTime"], maxgap, plotFile, parms["refAnt"], err, \
                                   Stokes=["RR","LL"], doband=2,          \
                                   check=check, debug=debug, logfile=logFile )
            if retCode != 0:
                raise RuntimeError("Error in Plotting spectrum")

        # Amp & phase Recalibrate
        if parms["doAmpPhaseCal2"]:
            plotFile = fileRoot + "_APCal2.ps"
            retCode = KATCalAP (uv, [], parms["ACals"], err, PCals=parms["PCals"], \
                                 doCalib=2, doBand=2, BPVer=1, flagVer=0, \
                                 BChan=parms["ampBChan"], EChan=parms["ampEChan"], \
                                 solInt=parms["solInt"], solSmo=parms["solSmo"], ampScalar=parms["ampScalar"], \
                                 doAmpEdit=True, ampSigma=parms["ampSigma"], \
                                 ampEditFG=parms["ampEditFG"], \
                                 doPlot=parms["doSNPlot"], plotFile=plotFile, refAnt=parms["refAnt"], \
                                 noScrat=noScrat, nThreads=nThreads, logfile=logFile, check=check, debug=debug)
            if retCode != 0:
                raise RuntimeError("Error calibrating")

        # More editing
        parms["doAutoFlag2"] = False
        if parms["doAutoFlag2"]:
            mess = "Post recalibration editing:"
            printMess(mess, logFile)
            retCode = EVLAAutoFlag (uv, [], err, flagVer=0, flagTab=2, \
                                    doCalib=2, gainUse=0, doBand=2, BPVer=1,  \
                                    IClip=parms["IClip"], minAmp=parms["minAmp"], timeAvg=parms["timeAvg"], \
                                    doFD=parms["doSecAFFD"], FDmaxAmp=parms["FDmaxAmp"], FDmaxV=parms["FDmaxV"], \
                                    FDwidMW=parms["FDwidMW"], FDmaxRMS=parms["FDmaxRMS"], \
                                    FDmaxRes=parms["FDmaxRes"],  FDmaxResBL= parms["FDmaxResBL"], \
                                    FDbaseSel=parms["FDbaseSel"], \
                                    nThreads=nThreads, logfile=logFile, check=check, debug=debug)
            if retCode != 0:
                raise RuntimeError("Error in AutoFlag")
    # end recal
    # Calibrate and average data
    # Overwrite avgStokes from command line
    parms["avgFreq"] = 0
    parms["chAvg"] = 1
    parms["doCalAvg"] = 'Splat'
    if kwargs.get('halfstokes'):
        parms["avgStokes"] = 'HALF'
    if parms["doCalAvg"] == 'Splat':
        retCode = KATCalAvg (uv, avgClass, parms["seq"], parms["CalAvgTime"], err, \
                              flagVer=2, doCalib=2, gainUse=0, doBand=2, BPVer=1, doPol=False, \
                              avgFreq=parms["avgFreq"], chAvg=parms["chAvg"], Stokes=parms["avgStokes"], \
                              BChan=1, EChan=parms["selChan"] - 1, doAuto=parms["doAuto"], \
                              BIF=parms["CABIF"], EIF=parms["CAEIF"], Compress=parms["Compress"], \
                              nThreads=nThreads, logfile=logFile, check=check, debug=debug)
        if retCode != 0:
            raise RuntimeError("Error in CalAvg")
    elif parms["doCalAvg"] == 'BL':
        retCode = KATBLCalAvg (uv, avgClass, parms["seq"], err, \
                              flagVer=2, doCalib=2, gainUse=0, doBand=2, BPVer=1, doPol=False, \
                              avgFreq=parms["avgFreq"], chAvg=parms["chAvg"], FOV=parms['FOV'], \
                              maxInt=min(parms["solPInt"],parms["solAInt"]), Stokes=parms["avgStokes"], \
                              BChan=1, EChan=parms["selChan"] - 1, timeAvg=parms["CalAvgTime"], \
                              BIF=parms["CABIF"], EIF=parms["CAEIF"], Compress=parms["Compress"], \
                              logfile=logFile, check=check, debug=debug)
        if retCode != 0:
            raise RuntimeError("Error in BLCalAvg")

    if parms["doSaveTab"]:
        filename = project + ".CalTab.uvtab"
        _ = EVLAUVFITSTab(uv, filename, 0, err, logfile=logFile)

    #Zap unaveraged data if requested
    if kwargs.get('zapraw'):
        uv.Zap(err)

    # Get calibrated/averaged data
    if not check:
        uv = UV.newPAUV("AIPS UV DATA", EVLAAIPSName(project), avgClass[0:6], \
                        disk, parms["seq"], True, err)
        if err.isErr:
            OErr.printErrMsg(err, "Error creating cal/avg AIPS data")

    plotFile = fileRoot + "_Spec.ps"
    retCode = EVLASpectrum(uv, parms["BPCal"], parms["plotTime"], maxgap, \
                               plotFile, parms["refAnt"], err, \
                               Stokes=["I"], doband=-1, docalib=-1,      \
                               check=check, debug=debug, logfile=logFile )
    if retCode != 0:
        raise RuntimeError("Error in Plotting spectrum")

    # KATUVFITS(uv, 'preimage.uvfits', 0, err, exclude=["AIPS HI", "AIPS SL", "AIPS PL"],
    # include=["AIPS AN", "AIPS FQ"], compress=parms["Compress"], logfile=logFile)
    KATUVFITab(uv, project + '.uvtab', 0, err)
    #Gzip the data?
    if kwargs.get('gzip'):
        os.system('pigz -p %d %s' % (nThreads, project + '.uvtab'))
        os.system('rm -f %s' % (project + '.uvtab'))
Пример #25
0
            res = get_reduction_metadata(
                filename.split('/')[-1],
                reduction_name='AR1 Generate RFI Flags')
            flag_results = res[0]['CAS.ReferenceDatastore']
            for fl in flag_results:
                if fl.endswith('flags.h5'):
                    flag_filename = fl.split(':')[-1]
            print flag_filename
            h5_flags = h5py.File(flag_filename, 'r')
            cal_flags = True
        except:
            print "no calibration pipeline flags found"
            cal_flags = False

        #Loading data
        data = katdal.open(filename)
        if cal_flags:
            data._flags = h5_flags['flags']

        #Nice name for pdf
        h5name = data.name.split('/')[-1]
        obs_details = h5name + '_AR1_observation_report'
        pp = PdfPages(obs_details + '.pdf')

        N = data.shape[0]
        ext = 930
        step = max(int(math.floor(N / ext)), 1)

        #Loading flags
        data.select()
        M = 4 * np.shape(data)[1] / 4096
Пример #26
0
if len(args) > 1:
    print "Concatenating multiple h5 files into single MS."

if not ms_extra.casacore_binding:
    raise RuntimeError(
        "Failed to find casacore binding. You need to install both "
        "casacore and pyrap, or run the script from within a modified "
        "casapy containing h5py and katpoint.")
else:
    print "Using '%s' casacore binding to produce MS" % (
        ms_extra.casacore_binding, )

# Open HDF5 file
# if len(args) == 1: args = args[0]
# katdal can handle a list of files, which get virtually concatenated internally
h5 = katdal.open(args, ref_ant=options.ref_ant)

#Get list of unique polarisation products in the file
pols_in_file = np.unique([(cp[0][-1] + cp[1][-1]).upper()
                          for cp in h5.corr_products])

#Which polarisation do we want to write into the MS
#select all possible pols if full-pol selected, otherwise the selected polarisations via pols_to_use
#otherwise finally select any of HH,VV present (the default).
pols_to_use = ['HH', 'HV', 'VH', 'VV'] if (options.full_pol or options.circular) else \
              list(np.unique(options.pols_to_use.split(','))) if options.pols_to_use else \
              [pol for pol in ['HH','VV'] if pol in pols_in_file]

#Check we have the chosen polarisations
if np.any([pol not in pols_in_file for pol in pols_to_use]):
    raise RuntimeError("Selected polarisation(s): %s not available. "
    default=10.,
    help=
    "Keep jumps that are bigger than margin by this factor (default %default)")
parser.add_option(
    "-c",
    "--channel-mask",
    default='/var/kat/katsdpscripts/RTS/rfi_mask.pickle',
    help=
    "Optional pickle file with boolean array specifying channels to mask (default is no mask)"
)

(opts, args) = parser.parse_args()
if len(args) < 1:
    raise RuntimeError('Please specify an HDF5 file to check')

data = katdal.open(args[0])

n_chan = np.shape(data.channels)[0]
if opts.freq_chans is not None:
    start_f = int(opts.freq_chans.split(',')[0])
    end_f = int(opts.freq_chans.split(',')[1])
    chan_range = slice(start_f, end_f)
else:
    chan_range = slice(data.shape[1] // 4, 3 * data.shape[1] // 4)
# load static flags if pickle file is given
channel_mask = opts.channel_mask
if channel_mask > 0:
    pickle_file = open(channel_mask)
    rfi_static_flags = pickle.load(pickle_file)
    pickle_file.close()
    if n_chan > rfi_static_flags.shape[0]:
#command-line parameters
parser = optparse.OptionParser(
    usage="Please specify the input file\n\
    USAGE: python analyse_self_generated_rfi.py <inputfile.h5> ",
    description=
    "Evaluate the auto & cross correlation spectra to Find the RFI spikes\
    that appear consistently in all observations/pointings.")

opts, args = parser.parse_args()

# if no enough arguments, raise the runtimeError
if len(args) < 1:
    raise RuntimeError("No File passed as argument to script")

filename = args[0]
h5 = katdal.open(filename)

# user defined variables
print("Please wait while analysis is in progress...")
pdf = PdfPages(filename.split('/')[-1] + '_RFI.pdf')

page_length = 70
#antennas = [ant.name for ant in fileopened.ants]
#targets = [('%s' % (i.name)) for i in fileopened.catalogue.targets]
chan_range = slice(1, -1)  # remove dc spike
#freqs = fileopened.channel_freqs*1.0e-6
detection_function = detect_spikes_sumthreshold
#plot_horizontal_selection_per_antenna
for pol in ['H', 'V']:
    (all_text, figlist) = plot_selection_per_antenna(h5, pol, chan_range,
                                                     detection_function)
Пример #29
0
    output = None 
    for scan, _, target in kd.scans():
        scan_length = len(kd.dumps)
        if scan_length > max_scan:
            max_scan, scan_select = scan_length, scan
    if scan_select >= 0:
        output = f'{kd.obs_params["capture_block_id"]:13s} {scan:<5d} {max_scan:<6d} {target.name}'
    return output


parser = argparse.ArgumentParser()
parser.add_argument("katdata", help="URL of observation for which to find the associated delaycal CBID.")

args = parser.parse_args()

base_katdata = katdal.open(args.katdata)
sb_cbids = base_katdata.source.telstate.get_range('sdp_capture_block_id', st=0)
delay_cbids = [cbid[0] for cbid in sb_cbids[::-1]
                       if 'calibrate_delays.py' in 
                       base_katdata.source.telstate.view(cbid[0])['obs_params']['script_name']]
# Check each candidate delaycal CBID for an appropriate noise-diode scan
out = []
for cbid in delay_cbids:
    dc_katdata = katdal.open(args.katdata, capture_block_id=cbid)
    dc_search = _get_noise_diode_scan(dc_katdata)
    if dc_search is not None:
        out += [dc_search]

if out == []:
    print(f'No valid delay calibration observations found.')
else:
Пример #30
0
#open ouput files
text_log = open(text_log_filename, 'w')
pp = PdfPages(pdf_filename)

print 'Searching the data file from the mounted archive'
if opts.noarchive:
    d = [opts.filename]
else:
    import katarchive
    d = katarchive.get_archived_products(datafile)
    while len(d) == 0:
        time.sleep(10)
        d = katarchive.get_archived_products(datafile)

print "Opening %s using katfile, this might take a while" % (datafile, )
f = katfile.open(d[0], quicklook=True)
#start a figure
figure(figsize=(13.5, 6.5))
axes(frame_on=False)
xticks([])
yticks([])
title(datafile + " Observation Report", fontsize=16, fontweight="bold")

frontpage = make_frontpage(f)
text_log.write(frontpage)
text(0, 0, frontpage, fontsize=12)
savefig(pp, format='pdf')
print f

lst_time, loc_datetime = lst_date(f)
Пример #31
0
 def __init__(self, cbid_stream_rdb_file):
     katdata = katdal.open(cbid_stream_rdb_file)
     metfilename = '{}.met'.format(katdata.source.data.name)
     super(MeerKATTelescopeProductMetExtractor,
           self).__init__(katdata, metfilename)
     self.product_type = 'MeerKATTelescopeProduct'