Axes3D(fig[, rect]) | 3D axes object. |
DirectionFitTriangles([ws, parfile]) | Find the direction of a source provided one has the measured delay of arrival and the positions of the antenna. |
FitMaxima([ws, parfile]) | Find the maxima in multiple datsets and fit a basis spline polynomial to the data around their respective maximum. |
LocatePulseTrain([ws, parfile]) | Usage |
PlotAntennaLayout([ws, parfile]) | Description: |
PlotDirectionTriangles([ws, parfile]) | Description: |
A number of tools useful in calibrating radio data
Module author: Heino Falcke <h.falcke@astro.ru.nl>
Find the direction of a source provided one has the measured delay of arrival and the positions of the antenna.
Description:
This task uses the function hDirectionTriangulationsCartesian() to calculate a list of arrival directions in Cartesian coordinates of a pulse/source from all possible triangles of (groups of three) antennas and the measured arrival times at these antennas.
For the direction finding it is assumed that the signal arrives as a plane wave. If one triangle of antennas does not give a valid solution a solution at the horizion is returned with the complex part of the solution (the “closure error”) returned in Task.error.
To cope with near-field sources for each triangle the coordinates of its center are also calculated. This allows one to later look for points where the dircetions from all triangles intercept.
The inverse of the average lengths of the triangle baselines are returned in weights giving some indication how accurate the measurement in principle can be.
From three antennas we get in general two solutions for the direction, unless the arrival times are out of bounds, i.e. larger than the light-time between two antennas. Usually, when the three antennas are in a more or less horizontal plane, one of the solutions will appear to come from below the horizon (el < 0) and can be discarded. With sign_of_solution one can pick either the positive of the negative elevation.
If
triangles are provided then the Directions, Origins, and weights vectors have
results (times number of components of each result, i.e. times three for origins and times one for the rest.)
The actually measured lag is assumed to consist of two parts: the geometric delay due to light travel times plus the cable delay in each antenna.
measured timelag = expected geometric delay + cable delay + residual delay
What we do in the iteration is to use the above equation in the form
measured timelag - (cable delay + residual delay + delta delays[i]) - expected geometric delay = 0
with a delta delay that is determined at each step and then subsumed into the residual delay.
Output:
The main result will be in Task.meandirection which contains the direction vector to the source in Cartesian coordinates. See also Task.meandirection_azel and Task.meandirection_azel_deg.
The array Task.delays will contain the final cable delays needed to get a coherent signal for the final position. The delays as a function of iteration are in Task.delays_history[iteration]
Coordinate Systems
- Azimuth/Elevation is defined as North (0 degrees) through East (90 degrees) for Az and El running from 90 degree at the zenith to 0 degree at the horizon
- For spherical coordindates Az/phi is defined as East (0 degree) through North (90 degree) and theta running from 0 degree at the zenith to 90 degree at the horizon
See also:
CrossCorrelateAntennas, LocatePulseTrain, FitMaxima
Example:
file=open("$LOFARSOFT/data/lofar/oneshot_level4_CS017_19okt_no-9.h5") file["ANTENNA_SET"]="LBA_OUTER" file["BLOCKSIZE"]=2**17 file["SELECTED_DIPOLES"]=["017000001","017000002","017000005","017000007","017001009","017001010","017001012","017001015","017002017","017002019","017002020","017002023","017003025","017003026","017003029","017003031","017004033","017004035","017004037","017004039","017005041","017005043","017005045","017005047","017006049","017006051","017006053","017006055","017007057","017007059","017007061","017007063","017008065","017008066","017008069","017008071","017009073","017009075","017009077","017009079","017010081","017010083","017010085","017010087","017011089","017011091","017011093","017011095"] timeseries_data=file["TIMESERIES_DATA"] positions=file["ANTENNA_POSITIONS"] # First determine where the pulse is in a simple incoherent sum of all time series data pulse=trun("LocatePulseTrain",timeseries_data,nsigma=7,maxgap=3) # Normalize the data which was cut around the main pulse pulse.timeseries_data_cut[...]-=pulse.timeseries_data_cut[...].mean() pulse.timeseries_data_cut[...]/=pulse.timeseries_data_cut[...].stddev(0) # Cross correlate all pulses with each other crosscorr=trun('CrossCorrelateAntennas',pulse.timeseries_data_cut,oversamplefactor=5) # And determine the relative offsets between them mx=trun('FitMaxima',crosscorr.crosscorr_data,doplot=True,refant=0,plotstart=4,plotend=5,sampleinterval=10**-9,peak_width=6,splineorder=2) # Now fit the direction and iterate over cable delays to get a stable solution direction=trun("DirectionFitTriangles",positions=positions,timelags=hArray(mx.lags),maxiter=10,verbose=True,doplot=True) print "========================================================================" print "Fit Arthur Az/El -> 143.409 deg 81.7932 deg" print "Triangle Fit Az/EL -> ", direction.meandirection_azel_deg,"deg" # Triangle Fit Az/EL -> (144.1118392216996, 81.84042919170588) deg for odd antennas # Triangle Fit Az/EL -> (145.17844721833896, 81.973693266380721) deg for even antennas
Input parameters
Output parameters
Find the maxima in multiple datsets and fit a basis spline polynomial to the data around their respective maximum. Then determine where the maximum in the interpolated data will be. This allows one to determine the maximum with subsample precision.
Usage:
Task = FitMaxima()(data[n_datasets,n_samples], peak_width=20, nsubsamples=16, ncoeffs=5, splineorder=3, doplot=False, plotend=4, plotstart=0, sampleinterval=None, refant=None) -> Task.maxx, Task.maxy, Task.lag
The main result will be in Task.maxx which returns the (fractional) sample number of the maximum and Task.maxy the y-value of the maximum. Task.lag returns the relative offset of the peaks relative to the reference dataset (refant) in user units, specified by sampleinterval.
See also:
CrossCorrelateAntennas, LocatePulseTrain
Example:
file=open("/Users/falcke/LOFAR/usg/data/lofar/oneshot_level4_CS017_19okt_no-9.h5") file["BLOCKSIZE"]=2**int(round(math.log(file["DATA_LENGTH"][0],2))) file["SELECTED_DIPOLES"]=[f for f in file["DIPOLE_NAMES"] if int(f)%2==1] # select uneven antenna IDs timeseries_data=file["TIMESERIES_DATA"] (start,end)=trun("LocatePulseTrain",rf.TimeBeamIncoherent(timeseries_data),nsigma=7,maxgap=3) start-=16 end=start+int(2**math.ceil(math.log(end-start,2))); timeseries_data_cut=hArray(float,[timeseries_data.shape()[-2],end-start]) timeseries_data_cut[...].copy(timeseries_data[...,start:end]) timeseries_data_cut[...]-=timeseries_data_cut[...].mean() timeseries_data_cut[...]/=timeseries_data_cut[...].stddev(0) crosscorr_data=tasks.pulsecal.CrossCorrelateAntennas()(timeseries_data_cut).crosscorr_data crosscorr_data.abs() crosscorr_data[...].runningaverage(15,hWEIGHTS.GAUSSIAN) mx=trun("FitMaxima",crosscorr_data,doplot=True,refant=0,sampleinterval=5) print "Lags =",list(mx.lags),"nanoseconds."
Input parameters
covariance
dim2
fits_xdata
fits_ydata
xpowers
Output parameters
Usage
LocatePulseTrain()(timeseries_data[nantennas,blocklen],timeseries_data_sum[blocklen]=None,nsigma=7,maxgap=7,minpulselen=7) -> Task.start, Task.end, Task.time_series_cut
Description
Finds the pulse train with the highest peak in time series data, determine its location, and cut out the time series data around the pulse. If the input array has multiple dimensions (multiple antennnas are present), then sum the antennas first and search the pulse in the sum of all antennas or look for the mean pulse location for all antennas.
The task calculates noise and threshold level above which to find pulse trains. A pulse train can have gaps of some N=maxgaps samples which are below the threshold and yet are considered part of the pulse train (i.e., this is the maximum separation of individual pulses to be considered part of the pulse train.).
With the parameter search_window the search can be limited to the range of samples between those two numbers.
If the parameter timeseries_data_sum is provided (a 1D array with a time series, e.g. an incoherent beam of all antennas) then the peak will be searched in that time series and not recalculated.
If search_per_antenna=True then the peaks are searched in each antenna. From all antennas where a peak was found the median peak location and length is taken.
- Results:
Returns start and end index of the strongest pulse in Task.start and Task.end. The cut-out time series is returned in Task.timeseries_data_cut.
The summed time series from all data sets (if a 2D array was provided) is returned in Task.timeseries_data_sum
For search_per_antenna=True the list Task.peaks_found_list contains the indices of all antennas where a peak was found. The number of antennas with peaks is self.npeaks_found. Start and end of the pulses for each antenna with peak are found are in self.maxsequences. The smallest and largest start location of all antennas can be found in Task.start_min, Task.start_max. See also Task.lengths_min, Task.lengths_max, and Task.lengths_median for information on the width of these peaks.
See hFindSequenceGreaterThan() for a description of the other parameters.
See also:
hFindSequenceGreaterThan()
Example
file=open("/Users/falcke/LOFAR/usg/data/lofar/oneshot_level4_CS017_19okt_no-9.h5") # file["BLOCKSIZE"]=2**int(round(math.log(file["DATA_LENGTH"][0],2))) file["SELECTED_DIPOLES"]=["017000001", "017000002", "017000005", "017000007", "017001009", "017001010", "017001012", "017001015", "017002017", "017002019", "017002020", "017002023", "017003025", "017003026", "017003029", "017003031", "017004033", "017004035", "017004037", "017004039", "017005041", "017005043", "017005045", "017005047", "017006049", "017006051", "017006053", "017006055", "017007057", "017007059", "017007061", "017007063", "017008065", "017008066", "017008069", "017008071", "017009073", "017009075", "017009077", "017009079", "017010081", "017010083", "017010085", "017010087", "017011089", "017011091", "017011093", "017011095"] pulse=trun('LocatePulseTrain',file["TIMESERIES_DATA"]) #(pulse.start,pulse.end) -> (65806L, 65934L) pulse.timeseries_data_sum.plot(highlight=(pulse.start,pulse.end),nhighlight=1) pulse.timeseries_data_cut[0].plot()
Input parameters
Output parameters
Description:
Plot the layout of the current dataset on the ground.
Usage:
See also: DirectionFitTriangles
Example:
file=open("$LOFARSOFT/data/lofar/oneshot_level4_CS017_19okt_no-9.h5") file["ANTENNA_SET"]="LBA_OUTER" file["SELECTED_DIPOLES"]="odd" positions=file["ANTENNA_POSITIONS"] layout=trun("PlotAntennaLayout",positions=positions,sizes=range(48),names=range(48))
Input parameters
Output parameters
Description:
Plot the directions towards a source found by triangle fitting. This will average directions from triangles of antennas with the same center into one mean direction and then plot a mean direction arrow, for this subarray.
This will als plot the underlying layout of antennas.
Usage:
See also: DirectionFitTriangles
Example:
filename="oneshot_level4_CS017_19okt_no-9.h5" file=open("$LOFARSOFT/data/lofar/"+filename) file["ANTENNA_SET"]="LBA_OUTER" file["BLOCKSIZE"]=2**17 file["SELECTED_DIPOLES"]=["017000001","017000002","017000005","017000007","017001009","017001010","017001012","017001015","017002017","017002019","017002020","017002023","017003025","017003026","017003029","017003031","017004033","017004035","017004037","017004039","017005041","017005043","017005045","017005047","017006049","017006051","017006053","017006055","017007057","017007059","017007061","017007063","017008065","017008066","017008069","017008071","017009073","017009075","017009077","017009079","017010081","017010083","017010085","017010087","017011089","017011091","017011093","017011095"] timeseries_data=file["TIMESERIES_DATA"] positions=file["ANTENNA_POSITIONS"] # First determine where the pulse is in a simple incoherent sum of all time series data pulse=trun("LocatePulseTrain",timeseries_data,nsigma=7,maxgap=3) # Normalize the data which was cut around the main pulse for correlation pulse.timeseries_data_cut[...]-=pulse.timeseries_data_cut[...].mean() pulse.timeseries_data_cut[...]/=pulse.timeseries_data_cut[...].stddev(0) # Cross correlate all pulses with each other crosscorr=trun('CrossCorrelateAntennas',pulse.timeseries_data_cut,oversamplefactor=5) # And determine the relative offsets between them mx=trun('FitMaxima',crosscorr.crosscorr_data,doplot=True,refant=0,plotstart=4,plotend=5,sampleinterval=10**-9,peak_width=6,splineorder=2) # Now fit the direction and iterate over cable delays to get a stable solution direction=trun("DirectionFitTriangles",positions=positions,timelags=hArray(mx.lags),maxiter=10,verbose=True,doplot=True) print "========================================================================" print "Fit Arthur Az/El -> 143.409 deg 81.7932 deg" print "Triangle Fit Az/EL -> ", direction.meandirection_azel_deg,"deg" # Triangle Fit Az/EL -> (144.1118392216996, 81.84042919170588) deg for odd antennas # Triangle Fit Az/EL -> (145.17844721833896, 81.973693266380721) deg for even antennas p=trun("PlotDirectionTriangles",centers=direction.centers,positions=direction.positions,directions=direction.directions,title=filename)
Input parameters
Output parameters