Browse Source

First version of To be debugged

Benito Marcote 3 years ago
  1. 244
  2. 73


@ -0,0 +1,244 @@
#!/usr/bin/env python3
Creates a .comment file for the EVN Pipeline.
Given a default template, customizes it to include the basic data from the given experiment.
The script will ask you in the terminal about all the required inputs.
Version: 1.0
Date: April 2019
Author: Benito Marcote (
import os
import sys
import argparse
import subprocess
import datetime as dt
__version__ = 1.0
# The .comment file template is located in the same directory as this script. Or it should be.
template_file = os.path.dirname(os.path.abspath(__file__)) + '/template.comment'
help_str = """Creates a .comment file for the EVN Pipeline.
Given a default template, customizes it to include the basic data from the given experiment.
The script will ask you in the terminal about all the required inputs.
parser = argparse.ArgumentParser(description=help_str, prog='')
parser.add_argument('experiment', type=str, default=None, help='Experiment name. Note: in case of multiple passes write {exp}_number (e.g. ev100_1')
parser.add_argument('-v', '--version', action='version', version='%(prog)s {}'.format(__version__))
args = parser.parse_args()
def get_sources():
"""Parse the observed sources from the pipeline input file ($IN/{exp}/{exp}.inp.txt).
It searches for the bandpass=, target= and phaseref= lines.
- refant : str
The reference antenna
- bpass : list
The bandpass calibrators and fringe finders used in the pipeline.
- phaseref : list
The phase referencing calibrators used in the pipeline. None if no phase referencing experiment.
- target : list
The targets. Should have the same dimension than the phaseref (unless it is not a phase
referencing experiment).
with open('$IN/{}/{}.inp.txt'.format(args.experiment.lower().split('_')[0],
args.experiment.lower()), 'r') as inpfile:
phaseref = None
target = None
for inpline in inpfile.readlines():
if 'refant' in inpline:
refant = inpline.split('=')[1].strip().split(',')[0]
if 'bpass' in inpline:
bpass = [i.strip() for i in inpline.split('=')[1].strip().split(',')]
if ('phaseref' in inpline) and inpline[0] != '#':
phaseref = [i.strip() for i in inpline.split('=')[1].strip().split(',')]
if ('target' in inpline) and inpline[0] != '#':
target = [i.strip() for i in inpline.split('=')[1].strip().split(',')]
if ('sources' in inpline) and inpline[0] != '#':
if target is None:
target = [i.strip() for i in inpline.split('=')[1].strip().split(',')]
if target is None:
raise ValueError('No sources found for target (neither target or sources are defined in INP file')
return refant, bpass, phaseref, target
def parse_sources(bpass, phaseref, target):
"""Returns the sentences to be placed in the comment file concerning the observed sources
s = ''
if phaseref is not None:
assert len(phaseref) == len(target)
for a_phaseref, a_target in zip(phaseref, target):
s += 'The target source {} was calibrated using the phase-reference source {}.<br>\n'.format(
a_phaseref, a_target)
if len(target) > 1:
s += 'The target sources {} were directly fringe-fitted and bandpass calibrated.<br>\n'.format(
', '.join(target))
s += 'The target source {} was directly fringe-fitted and bandpass calibrated.<br>\n'.format(target[0])
if len(bpass) == 1:
keys = ('was', '')
keys = ('were', 's')
s += '{0} {1} also observed as calibrator{2} and fringe finder{2}.<br>\n'.format(', '.join(bpass), *keys)
return s
def get_setup():
"""Get the observation setup from the {exp}.SCAN file created by the Pipeline:
It takes the file {exp}.SCAN that should be in $OUT/{exp}/.
- freq : float (GHz)
The central frequency of the observation.
- datarate : float (Mbps)
The datarate of the observation.
- number_ifs : int
Number of IFs or subbands.
- bandwidth : float (MHz)
The bandwidth of each IF or subband.
- pols : int
Number of polarizations:
1 - single pol.
2 - dual pol.
4 - ful pol.
with open('$OUT/{}/{}.SCAN'.format(args.experiment.lower().split('_')[0],
args.experiment.lower()), 'r') as scanfile:
for scanline in scanfile.readlines():
# Getting the frequency and the number of polarizations
# The line is like Freq = XXXX GHz Ncor = X No. vis = XXXX
if 'Freq = ' in scanline:
# freq, pols = [i for i in map([i.strip() for i in scanline.split('=')].__getitem__, ())
temp = ' '.join(scanline.split('=')).split()
freq = float(temp[1])
if temp[2] == 'GHz':
elif temp[2] == 'MHz':
freq *= 1e-3
elif temp[2] == 'kHz':
freq *= 1e-6
elif temp[2] == 'Hz':
freq *= 1e-9
raise ValueError('Not units found in the Freq = XXX line inside the SCAN file')
pols = int(temp[4]) # number of polarizations 2= dual, 4 = full)
assert pols in (1, 2, 4)
raise IOError('The SCAN file does not contain a line with Freq = XXX')
# # The line with the Frequency Table summary, listing all IFs,.
# if 'FQID IF#' in scanline:
# pass
# The very last line (if not empty) is the last IF with Freq, BW, ch.Sep, and Sideband
last_if = scanfile.readlines()[-1].split()
if len(last_if) == 6:
# It contains the FQID value
number_ifs = int(last_if[1])
bandwidth = int(float(last_if[3])*1e-3)
elif len(last_if) == 5:
# It does not contain the FQID value
number_ifs = int(last_if[0])
bandwidth = int(float(last_if[2])*1e-3)
ValueError('Unexpected number of parameters at the end of the SCAN file.')
if pols == 1:
datarate = number_ifs*bandwidth*2*2
datarate = number_ifs*bandwidth*2*2*2
return freq, datarate, number_ifs, bandwidth, pols
def parse_setup(exp, freq, datarate, number_ifs, bandwidth, pols):
"""Returns the text to place in the comment file concerning the experiment setup.
# It gets the date of the experiment from the MASTER_PROJECTS.LIS file in ccsbeta
date = subprocess.getoutput('ssh jops@ccsbeta grep {} /ccs/var/log2vex/MASTER_PROJECTS.LIS | cut -d " " -f 3'.format(exp.upper())
obsdate = dt.strptime(date, '%Y%m%d')
if freq < 0.6:
band = 'P'
elif freq < 1.9:
band = 'L'
elif freq < 3.0:
band = 'S'
elif freq < 7.0:
band = 'C'
elif freq < 11.0:
band = 'X'
elif freq < 18.0:
band = 'U'
elif freq < 30:
band = 'K'
elif freq >= 30:
band = 'Q'
name_pols = {1: 'single', 2: 'dual', 4: 'full'}
s = '{}. {}-band experiment observed on {}.<br>\n'.format(exp.upper(), band, obsdate.strftime('%d %B %Y'))
s += 'Data rate was {} Mbps ({} x {} MHz subbands, {} polarization, two-bit sampling)<br>\n'.format(
datarate, number_ifs, bandwidth, name_pols[pols])
return s
def get_antennas():
"""Returns a list of all antennas participating in the experiment. It takes the information
from the {exp}.DTSUM located in $OUT/{exp}/.
with open('$OUT/{}/{}.DTSUM'.format(args.experiment.lower().split('_')[0],
args.experiment.lower()), 'r') as dtsumfile:
list_antennas = []
inside_array = False
for dtline in dtsumfile.readlines():
if inside_array:
if '(' in dtline:
templine = dtline
# More antennas to get
while '(' in templine:
templine = templine[templine.index(')')+1:]
# We are done
inside_array = False
if 'Array name' in dtline:
inside_array = True
return list_antennas
def parse_antennas(list_antennas):
"""Returns the text to include in the comment file concerning the participating antennas
return '{} stations participated: {}.<br>\n'.format(len(list_antennas), ', '.join(list_antennas))
with open(template_file, 'r') as template:
full_text =
refant, *all_sources = get_sources()
full_text.format(setup_header=parse_setup(args.experiment, *get_setup()),
comment_file = open('$OUT/{}/{}.comment'.format(args.experiment.lower().split('_')[0],
args.experiment.lower()), 'w')
print('File {0}.comment created successfully in $OUT/{0}.'.format(args.experiment.lower()))


@ -0,0 +1,73 @@
The following are plots from the EVN pipeline analysis, in which the reference antena was: {ref_antenna}.
Auto-corr amplitude vs frequency plots for each station showing all IFs and Pols.
Amplitude and phase vs time, for the whole experiment, no calibration applied. Shows visibilities on all baselines to the reference antenna. All IFs and Pols shown. This is a good place to look for stations that missed scans during the experiment.
Uncalibrated, vector averaged, cross power specra for baselines to the reference antenna. No bandpass calibration applied yet. This is a good place to look check how well detected sources are on each baseline.
Plots of system temperature vs time for each station (and each IF). Flat-line plots indicate that this information was not available for a given station, in which case we create a generic Tsys table scalled to the station's gain (Jy/K). This information is stored in the TY1 table.
Gain info in CL2, determined using Tsys tables. Plot shows Gain vs time for each station, each IF and each Pol.
Plot of CL3. This is the CL table generated using CL2 (amplitude cal) and SN2 (FRING solutions). Plot shows phase calibration data vs time. Missing data indicate possible issues in those previous steps. If the data are complete (all stations and most scans present) then use this table to phase-reference the target.
Plot of SN2. Shows delay vs time from FRING results (usually only calibrators and reference sources). This is a good place to look for times where FRING failed to get solutions. Here FRING uses a signal to noise cutoff of 7. If FRING fails a lot it would be a good idea to retry with a lower signal to noise cutoff. This is the line pass data. We expect better FRING solutions in the continuum data.
SN2 as above, but for rate.
Plot of BP1. Shows the bandpass characteristic of each antenna, determined using the brightest source(s) in the experiment. Look for small dispersion in the phase data, this indicates a high signal to noise - which will lead to better bandpass characterisation.
Plot of visibilities vs time for all baselines to the reference antenna, after applying CL3. This is a good place to look for quickly checking the success of the antab (CL2) and FRING (CL3) stages of the pipeline.
Amplitude and phase vs frequency plots for all baselines to the reference antenna, after applying CL3 and BP1. If CL3 and BP1 are good you will get flat phase and amplitude profiles, therefore this is a good place to check the success of CL2 and particluarly BP1 for each scan/baseline/IF/Pol.
Only phase-referenced targets are shown.
Only phase-referenced targets are shown.
Individual plots for each source that was used in FRING. Shows phase selfcal solutions (SN1 after SPLIT). This is particularly useful to check if the reference source could be self-calibrated, and to look for missing scans/antennas. These are more useful in the continuum pass data.
Individual plots for each source that was used in FRING. Shows amplitude selfcal solutions (SN2). This table is important to properly calibrate amplitudes from stations that had to use generic Tsys tables (see TSYS, above). In the statistical summary values close to one means a good a-priori calibration.
Plot of CL4 which shows amplitude calibrations determined from CL3 and the amplitude selfcal solutions from SN2 (from CALIB_AMP2, above). Comparison with GAIN plot (above) reveals the accuracy of the apriori amplitude calibration derived from the TSYS tables - this is particularly important for stations that have generic generated TSYS tables; Tsys may benefit from aditional scalling if there is a large differnce in SENS and GAIN plots.
Closure phases for all triangles of antennas in the array. Individual plots for each source which was used in FRING.
Similar to VPLOT_CAL for sources used in FRING, however each source has been individually SPLITed and modelled.
Plot of the UV coverage for each source during the experiment.
Plot of amplitude vs baseline lenght for each source. This can be useful to look for inications of structure at different angular scales.
CLEANed image of each source (FRINGed or phase-referened) after applying all relevant calibration by the pipeline up to CL4; amplitude and phase selfcal calibrations.