xcor module
This optional module allows to compute cross-correlation from a 2D ndarray (or a A1Section) containing a DAS section. The core function is written in fortran and parallelized using openMP.
Instead of processing cross-correlation using individual records, the xcor module uses directly the 2D float array containing DAS data. A pre-processing step to select the couple of traces to be cross-correlated is achieved by calling the register_couple() function. A number of pre-processing are built-in and available (one-bit, whitenning, bandpass filtering, …) by calling the register_par() function.
Requirements
This module requires:
C and fortran compilers (e.g gfortran) and make (gmake is ok)
numpy
one of the MKL or OpenBlas+FFTW3 libraries.
For linux, these are standard and free libraries that can be easily download using apt-get. Try; apt-get install libfftw3 apt-get install libfftw3-dev apt-get install libopenblas-dev
For mac with arm cpu (M1, M2, …) using OpenBlas and FFTW is mandatory, they can be get from brew. Getting a fortran compiler usually requires to install Apple xcode.
Download and installation
Install (tar.gz archive) the xcor module in the same directory as a1das from the gitlab repository (e.g. in2p3 gitlab), you should see a directory named A1-XCORPY.
Check that the required libraries are installed and find their locations (/opt/…, /usr/local/lib, /usr/lib/x86_64-linux-gnu, /opt/homebrew, ….). You should look for libopenblas.a, libfftw3.a or libmkl
change to A1-XCORPY directory and under a python environment, run the shell configure_var.sh, this will create the Makefile.python file
select one of the proposed Makefile.inc.???, edit and change according to your needs, then copy it as Makefile.inc
run the compilation step by typing “make python”
This should have installed the binary module under the a1das directory. If you have already installed the a1das package you can either
a) uninstall and reinstall it: python -m pip uninstall a1das pip install .
b) or copy the _a1xcorPy.cpython.?? file in the directory where a1das has been installed (e.g.
Usage
- xcor.compute_xcorr(arrayIn, lag=None, stack=False, verbose=0, base=0, flip=False)
Description
xcorr, lags, ijx, ier = compute_xcorr(arrayIn, lag=None, stack=False, verbose=0)
Compute cross-correlations in a 2D array of traces [Ntime x Nspace] The array is given either as a 2D ndarray or as an A1Section class instance.
Cross-correlations are computed for the couple of traces {i,j} declared previously by a1das.xcor.register_couple() and using the parameter declared previously by a1das.xcor.register_par()
!!!!! WARNING !!!! currently process only float64 data array
TODO: write a float32 version
Input
- arrayIn:
2D (float64) ndarray [nSpace x nTime], or <A1Section> class instance (with float64 data array)
- lag:
(float) time lag, in sample for ndarray input, in sec for <A1Section>
- stack:
(bool) stack the correlations for consecutive windows of 2*lag+1 length if 2*lag+1 < length signal (default False)
- base:
(int) <0> if first index of trace is 0, <1> if first index is 1 (default 0)
- flip:
(bool) reverse time lags with respect to usual python correlation (default false)
- verbose:
verbosity (default 0)
function return
- xcorr:
2D ndarray of cross-correlations [nxcor x nTime] (float64)
- lags:
vector of lag times, in sample for ndarray input, in sec for <A1Section> input
- ijx:
2D ndarray of size[nxcor, 2] giving trace index for each correlation
- ier:
return code, 0 if ok
Usage example
>>> import a1das >>> f = a1das.open(filename, format='febus') >>> a1 = f.read() >>> a1das.xcor.register_couple([[1,2],[1,3],[1,4]]) # compute xcorr between traces 1&2, 1&3, 1&4 >>> a1das.xcor.register_par('onebit') # set onebit pre-processing >>> lag = 5. # set lag time to 5sec >>> # compute xcorr between -5sec and 5sec, compute FFT over consecutive windows of 10 sec and stack them >>> xcorr, lags, ijx, ier = compute_xcorr(a1, lag=lag, stack = True) >>> # same but for ndarray with no stack, >>> xcorr, lags, ijx, ier = compute_xcorr(a1.data, lag=5./a1['dt'], stack = False)
- xcor.register_couple(couple, ntrace, base=0)
Description
Register the list of trace couples {i,j} for which we compute the cross-correlation
- if base = 0 (default = python, C convention)
0 <= i < ntrace 0 <= j < ntrace
- if base = 1 (Fortran, matlab convention)
1 <= i <= ntrace 1 <= j <= ntrace
Input and return
- couple:
2D ndarray (or list, or tuple) of size [ncouple , 2] (ex: [[1,1],[1,2],[1,3]] to compute {1,1}, {1,2}, {1,3} cross-correlations
- trace:
(int) number of traces in the 2D das section
- base:
(int) starting index for trace number, 0 (default) or 1
function return
- status:
0 ok; 1 wrong index number (<0 or >ntrace)
Usage example
>>> #For a section containing 500 traces >>> #Compute correlation of trace 0 and 1 with all other traces >>> import a1das >>> ntrace=500 >>> couple = [list([0,j]) for j in range(0,ntrace)] >>> couple += [list([1,j]) for j in range(0,ntrace)] >>> a1das.xcor.register_couple(couple,ntrace=ntrace)
- xcor.sort_xcorr(i0, ijx, xcorr=None)
Description
I, J = sort_xcorr(i0, ijx) or xcorr_sorted = sort_xcorr(i0, ijx ,xcorr)
return the xcorr indices I that correspond to correlation couple {i0, ?}, xcorr[I,:] are the cross-correlation that implies trace i0 Among these correlation, those with index J need to be time-flipped If an xcorr[ncor, nlags] array is given as input, the function returns a sorted version of xcorr
Input
- src:
index of the “source” trace
- ijx:
array of indices obtained from the compute_xcorr()
function return
- I:
array of index such that xcorr[I, :] correspond to cross-correlation of couple {src, ?} or {?, src)
- J:
array of index xcorr[J,:] where one needs to flip time to get {i0,?} xcorr instead of {?,i0}
- xcorr_sorted[ncor, ntime]:
sub-array of xcorr that corresponds only to {i0,?} cross-correlations
Usage example
>>> #a1 = a <A1Section> instance >>> xcorr, lags, ijx, ier = xcor.compute_xcorr(a1,lag=lag,stack=True,verbose=0) >>> >>> # return all the indices {i1} that correspond to correlations {i0,?} >>> I, J = xcor.sort_xcorr(i0,ijx) >>> xcorrs = xcor.sort_xcorr(i0,ijx, xcorr) >>> xcorr_sorted = xcorr[I,:] >>> xcorr_flipped = numpy.flip(xcorr_sorted[J],axis=1) >>> # xcorrs and xcorr_flipped are identical
- xcor.get_nxcorr()
get the number of xcorr couple of trace that have been registered for the computation of cross correlation in the current section